Skip to content

Commit

Permalink
GML geometry parsing: handle km unit for radius of arcs (fixes #3118)
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Oct 31, 2020
1 parent fc66183 commit 2bf36ad
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 38 deletions.
6 changes: 3 additions & 3 deletions autotest/ogr/ogr_gml_geom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1740,16 +1740,16 @@ def test_gml_CircleByCenterPoint():
assert ogrtest.check_feature_geometry(geom, ogr.CreateGeometryFromWkt('CIRCULARSTRING (-1 2,3 2,-1 2)')) == 0

###############################################################################
# Test GML CircleByCenterPoint with uom="m"
# Test GML CircleByCenterPoint with uom="m" and uom="km"


def test_gml_CircleByCenterPoint_srs_geog_uom_m():
def test_gml_CircleByCenterPoint_srs_geog_uom_m_km():

gml = '<gml:CircleByCenterPoint srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>49 2</gml:pos><gml:radius uom="m">2000</gml:radius></gml:CircleByCenterPoint>'
geom1 = ogr.CreateGeometryFromGML(gml)
geom1.SwapXY()

gml = '<gml:CircleByCenterPoint srsName="URN:OGC:DEF:CRS:OGC:1.3:CRS84"><gml:pos>2 49</gml:pos><gml:radius uom="m">2000</gml:radius></gml:CircleByCenterPoint>'
gml = '<gml:CircleByCenterPoint srsName="URN:OGC:DEF:CRS:OGC:1.3:CRS84"><gml:pos>2 49</gml:pos><gml:radius uom="km">2</gml:radius></gml:CircleByCenterPoint>'
geom2 = ogr.CreateGeometryFromGML(gml)

assert ogrtest.check_feature_geometry(geom1, geom2) == 0
Expand Down
65 changes: 30 additions & 35 deletions gdal/ogr/gml2ogrgeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,31 @@ bool GML2OGRGeometry_AddToMultiSurface( OGRMultiSurface* poMS,
return true;
}

/************************************************************************/
/* GetDistanceInMetre() */
/************************************************************************/

static double GetDistanceInMetre(double dfDistance, const char* pszUnits)
{
if( EQUAL(pszUnits, "m") )
return dfDistance;

if( EQUAL(pszUnits, "km") )
return dfDistance * 1000;

if( EQUAL(pszUnits, "nm") || EQUAL(pszUnits, "[nmi_i]") )
return dfDistance * CPLAtof(SRS_UL_INTL_NAUT_MILE_CONV);

if( EQUAL(pszUnits, "mi") )
return dfDistance * CPLAtof(SRS_UL_INTL_STAT_MILE_CONV);

if( EQUAL(pszUnits, "ft") )
return dfDistance * CPLAtof(SRS_UL_INTL_FOOT_CONV);

CPLDebug("GML2OGRGeometry", "Unhandled unit: %s", pszUnits);
return -1;
}

/************************************************************************/
/* GML2OGRGeometry_XMLNode() */
/* */
Expand Down Expand Up @@ -1211,19 +1236,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal(
}
}
if( bSRSUnitIsDegree && pszUnits != nullptr &&
(EQUAL(pszUnits, "m") ||
EQUAL(pszUnits, "nm") ||
EQUAL(pszUnits, "[nmi_i]") ||
EQUAL(pszUnits, "mi") ||
EQUAL(pszUnits, "ft")) )
(dfRadius = GetDistanceInMetre(dfRadius, pszUnits)) > 0 )
{
bIsApproximateArc = true;
if( EQUAL(pszUnits, "nm") || EQUAL(pszUnits, "[nmi_i]"))
dfRadius *= CPLAtof(SRS_UL_INTL_NAUT_MILE_CONV);
else if( EQUAL(pszUnits, "mi") )
dfRadius *= CPLAtof(SRS_UL_INTL_STAT_MILE_CONV);
else if( EQUAL(pszUnits, "ft") )
dfRadius *= CPLAtof(SRS_UL_INTL_FOOT_CONV);
dfLastCurveApproximateArcRadius = dfRadius;
bLastCurveWasApproximateArcInvertedAxisOrder =
bInvertedAxisOrder;
Expand Down Expand Up @@ -1806,24 +1821,14 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal(
const double dfCenterX = p.getX();
const double dfCenterY = p.getY();

double dfDistance;
if( bSRSUnitIsDegree && pszUnits != nullptr &&
(EQUAL(pszUnits, "m") ||
EQUAL(pszUnits, "nm") ||
EQUAL(pszUnits, "[nmi_i]") ||
EQUAL(pszUnits, "mi") ||
EQUAL(pszUnits, "ft")) )
(dfDistance = GetDistanceInMetre(dfRadius, pszUnits)) > 0 )
{
OGRLineString* poLS = new OGRLineString();
// coverity[tainted_data]
const double dfStep =
CPLAtof(CPLGetConfigOption("OGR_ARC_STEPSIZE", "4"));
double dfDistance = dfRadius;
if( EQUAL(pszUnits, "nm") || EQUAL(pszUnits, "[nmi_i]") )
dfDistance *= CPLAtof(SRS_UL_INTL_NAUT_MILE_CONV);
else if( EQUAL(pszUnits, "mi") )
dfDistance *= CPLAtof(SRS_UL_INTL_STAT_MILE_CONV);
else if( EQUAL(pszUnits, "ft") )
dfDistance *= CPLAtof(SRS_UL_INTL_FOOT_CONV);
const double dfSign = dfStartAngle < dfEndAngle ? 1 : -1;
for( double dfAngle = dfStartAngle;
(dfAngle - dfEndAngle) * dfSign < 0;
Expand Down Expand Up @@ -1935,23 +1940,13 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal(
const double dfCenterX = p.getX();
const double dfCenterY = p.getY();

double dfDistance;
if( bSRSUnitIsDegree && pszUnits != nullptr &&
(EQUAL(pszUnits, "m") ||
EQUAL(pszUnits, "nm") ||
EQUAL(pszUnits, "[nmi_i]") ||
EQUAL(pszUnits, "mi") ||
EQUAL(pszUnits, "ft")) )
(dfDistance = GetDistanceInMetre(dfRadius, pszUnits)) > 0 )
{
OGRLineString* poLS = new OGRLineString();
const double dfStep =
CPLAtof(CPLGetConfigOption("OGR_ARC_STEPSIZE", "4"));
double dfDistance = dfRadius;
if( EQUAL(pszUnits, "nm") || EQUAL(pszUnits, "[nmi_i]") )
dfDistance *= CPLAtof(SRS_UL_INTL_NAUT_MILE_CONV);
else if( EQUAL(pszUnits, "mi") )
dfDistance *= CPLAtof(SRS_UL_INTL_STAT_MILE_CONV);
else if( EQUAL(pszUnits, "ft") )
dfDistance *= CPLAtof(SRS_UL_INTL_FOOT_CONV);
for( double dfAngle = 0; dfAngle < 360; dfAngle += dfStep )
{
double dfLong = 0.0;
Expand Down

0 comments on commit 2bf36ad

Please sign in to comment.