diff options
Diffstat (limited to 'scripts/create_c_api_projections.py')
| -rwxr-xr-x | scripts/create_c_api_projections.py | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/scripts/create_c_api_projections.py b/scripts/create_c_api_projections.py new file mode 100755 index 00000000..5d10a16b --- /dev/null +++ b/scripts/create_c_api_projections.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python +############################################################################### +# $Id$ +# +# Project: PROJ +# Purpose: Parse XML output of Doxygen on coordinateoperation.hpp to creat +# C API for projections. +# Author: Even Rouault <even.rouault at spatialys.com> +# +############################################################################### +# Copyright (c) 2018, Even Rouault <even.rouault at spatialys.com> +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +############################################################################### + +from lxml import etree +import os + +script_dir_name = os.path.dirname(os.path.realpath(__file__)) + +# Make sure to run doxygen +if not 'SKIP_DOXYGEN' in os.environ: + os.system("bash " + os.path.join(script_dir_name, "doxygen.sh")) + +xmlfilename = os.path.join(os.path.dirname(script_dir_name), + 'docs/build/xml/classosgeo_1_1proj_1_1operation_1_1Conversion.xml') + +tree = etree.parse(open(xmlfilename, 'rt')) +root = tree.getroot() +compounddef = root.find('compounddef') + +header = open('projections.h', 'wt') +cppfile = open('projections.cpp', 'wt') +test_cppfile = open('test_projections.cpp', 'wt') + +header.write("/* BEGIN: Generated by scripts/create_c_api_projections.py*/\n") + +cppfile.write("/* BEGIN: Generated by scripts/create_c_api_projections.py*/\n") +cppfile.write("\n"); + +test_cppfile.write("/* BEGIN: Generated by scripts/create_c_api_projections.py*/\n") + +for sectiondef in compounddef.iter('sectiondef'): + if sectiondef.attrib['kind'] == 'public-static-func': + for func in sectiondef.iter('memberdef'): + name = func.find('name').text + assert name.startswith('create') + if name in ('create', 'createChangeVerticalUnit', + 'createAxisOrderReversal', 'createGeographicGeocentric'): + continue + params = [] + has_angle = False + has_linear = False + for param in func.iter('param'): + type = param.find('type').xpath("normalize-space()") + if type.find('Angle') >= 0: + has_angle = True + if type.find('Length') >= 0: + has_linear = True + paramname = param.find('declname').text + if paramname == 'properties': + continue + params.append((type, paramname)) + + shortName = name[len('create'):] + + decl = "proj_obj_create_projected_crs_" + decl += shortName + decl += "(\n" + decl += " PJ_OBJ* geodetic_crs, const char* crs_name,\n" + for param in params: + if param[0] in ('int', 'bool'): + decl += " int " + param[1] + ",\n" + else: + decl += " double " + param[1] + ",\n" + if has_angle: + decl += " const char* angUnitName, double angUnitConvFactor" + if has_linear: + decl += "," + decl += "\n" + if has_linear: + decl += " const char* linearUnitName, double linearUnitConvFactor" + decl += ")" + + header.write("PJ_OBJ PROJ_DLL *" + decl + ";\n\n") + + briefdescription = func.find('briefdescription/para').xpath("normalize-space()") + briefdescription = briefdescription.replace("Instanciate ", "Instanciate a ProjectedCRS with ") + + cppfile.write("// ---------------------------------------------------------------------------\n\n") + cppfile.write("/** \\brief " + briefdescription + "\n") + cppfile.write(" *\n") + cppfile.write(" * See osgeo::proj::operation::Conversion::create" + shortName + "().\n") + cppfile.write(" *\n") + cppfile.write(" * Linear parameters are expressed in (linearUnitName, linearUnitConvFactor).\n") + if has_angle: + cppfile.write(" * Angular parameters are expressed in (angUnitName, angUnitConvFactor).\n") + cppfile.write(" */\n") + cppfile.write("PJ_OBJ* " + decl + "{\n"); + if not has_linear: + cppfile.write(" const auto& linearUnit = UnitOfMeasure::METRE;\n") + else: + cppfile.write(" UnitOfMeasure linearUnit(createLinearUnit(linearUnitName, linearUnitConvFactor));\n") + if has_angle: + cppfile.write(" UnitOfMeasure angUnit(createAngularUnit(angUnitName, angUnitConvFactor));\n") + cppfile.write(" auto conv = Conversion::create" + shortName + "(PropertyMap()") + for param in params: + if param[0] in 'int': + cppfile.write(", " + param[1]) + elif param[0] in 'bool': + cppfile.write(", " + param[1] + " != 0") + elif param[0].find('Angle') >= 0: + cppfile.write(", Angle(" + param[1] + ", angUnit)") + elif param[0].find('Length') >= 0: + cppfile.write(", Length(" + param[1] + ", linearUnit)") + elif param[0].find('Scale') >= 0: + cppfile.write(", Scale(" + param[1] + ")") + + cppfile.write(");\n") + cppfile.write(" return proj_obj_create_projected_crs(geodetic_crs, crs_name, conv, linearUnit);\n") + cppfile.write("}\n") + + test_cppfile.write("{\n") + test_cppfile.write(" auto projCRS = proj_obj_create_projected_crs_" + shortName + "(\n") + test_cppfile.write(" geogCRS, nullptr") + for param in params: + test_cppfile.write(", 0") + if has_angle: + test_cppfile.write(", \"Degree\", 0.0174532925199433") + if has_angle: + test_cppfile.write(", \"Metre\", 1.0") + test_cppfile.write(");\n") + test_cppfile.write(" ObjectKeeper keeper_projCRS(projCRS);\n") + test_cppfile.write(" ASSERT_NE(projCRS, nullptr);\n") + test_cppfile.write("}\n") + + +header.write("/* END: Generated by scripts/create_c_api_projections.py*/\n") +cppfile.write("/* END: Generated by scripts/create_c_api_projections.py*/\n") + +test_cppfile.write("/* END: Generated by scripts/create_c_api_projections.py*/\n") + +print('projections.h and .cpp, and test_projections.cpp have been generated. Manually merge them now')
\ No newline at end of file |
