You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@sis.apache.org by Thierry Danard <th...@int.com> on 2019/10/22 23:10:33 UTC
Order of axis attributes in WKT string changes results
Hello,
I noticed a surprising behavior, I do not know whether this is a bug, or
whether it's expected: I found that when the order of the AXIS attributes
is changed, the conversion returns different results
I have the unit test below performing a sample conversion, and getting the
right result
(longitude=-99.20531579390813
latitude=29.225237498621965)
private DefaultGeographicBoundingBox
getExtentFromAreaOfUse(CoordinateReferenceSystem fromCrs,
CoordinateReferenceSystem toCrs,
double minX, double minY, double maxX, double maxY) throws
Exception {
CoordinateOperation operation = CRS.findOperation(fromCrs, toCrs,
null);
MathTransform mt = operation.getMathTransform();
DirectPosition topLeftPosition = new DirectPosition2D(maxY, minX);
DirectPosition topRightPosition = new DirectPosition2D(maxY, maxX);
DirectPosition bottomRightPosition = new DirectPosition2D(minY,
maxX);
DirectPosition bottomLeftPosition = new DirectPosition2D(minY,
minX);
DirectPosition topLeftLatLongPosition =
mt.transform(topLeftPosition, topLeftPosition);
DirectPosition topRightLatLongPosition =
mt.transform(topRightPosition, topRightPosition);
DirectPosition bottomLeftLatLongPosition =
mt.transform(bottomLeftPosition, bottomLeftPosition);
DirectPosition bottomRightLatLongPosition =
mt.transform(bottomRightPosition, bottomRightPosition);
double westBoundLongitude =
Math.min(topLeftLatLongPosition.getCoordinate()[1],
bottomLeftLatLongPosition.getCoordinate()[1]);
double eastBoundLongitude =
Math.max(topLeftLatLongPosition.getCoordinate()[1],
bottomLeftLatLongPosition.getCoordinate()[1]);
double southBoundLatitude =
Math.min(topRightLatLongPosition.getCoordinate()[0],
bottomRightLatLongPosition.getCoordinate()[0]);
double northBoundLatitude =
Math.max(topRightLatLongPosition.getCoordinate()[0],
bottomRightLatLongPosition.getCoordinate()[0]);
return new DefaultGeographicBoundingBox(westBoundLongitude,
eastBoundLongitude, southBoundLatitude, northBoundLatitude);
}
@Test
public void testWKTGitHub() throws FactoryException, Exception {
String wkt = "PROJCS[\"NAD27 / Texas South Central\","
+ "GEOGCS[\"NAD27\","
+ "DATUM[\"North American Datum 1927\","
+ "SPHEROID[\"Clarke 1866\", 6378206.4, 294.97869821]],"
+ "UNIT[\"degree\", 0.0174532925199433],"
+ "AXIS[\"Lat\", NORTH],"
+ "AXIS[\"Long\", EAST]],"
+ "PROJECTION[\"Lambert_Conformal_Conic_2SP\"],"
+ "PARAMETER[\"latitude_of_origin\", 27.833333333333332],"
+ "PARAMETER[\"central_meridian\", -99.0],"
+ "PARAMETER[\"standard_parallel_1\", 28.383333333333333],"
+ "PARAMETER[\"standard_parallel_2\", 30.28333333333333],"
+ "PARAMETER[\"false_easting\", 2000000.0],"
+ "PARAMETER[\"false_northing\", 0.0],"
+ "UNIT[\"US survey foot\", 0.30480060960121924],"
+ "AXIS[\"X\", EAST],"
+ "AXIS[\"Y\", NORTH]]";
CoordinateReferenceSystem fromCrs = CRS.fromWKT(wkt);
CoordinateReferenceSystem toCrs = CRS.forCode("EPSG:4326");
double x = 1934615.424;
double y = 506052.281;
CoordinateOperation operation = CRS.findOperation(fromCrs, toCrs,
getExtentFromAreaOfUse(fromCrs, toCrs, x, y, x, y));
DirectPosition position = new DirectPosition2D(x, y);
double[] coordinate =
operation.getMathTransform().transform(position, position).getCoordinate();
System.out.println("longitude=" + coordinate[1]);
System.out.println("latitude=" + coordinate[0]);
}
If I change the WKT from
+ "AXIS[\"X\", EAST],"
+ "AXIS[\"Y\", NORTH]]";
to
+ "AXIS[\"Y\",NORTH],"
+ "AXIS[\"X\",EAST]]";
I get a different, incorrect result:
(longitude=-103.86819946668828
latitude=33.06508313602342)
Is this an expected behavior (the WKT string does not meet the specs?), or
is it a defect ?
-Thierry
Re: Order of axis attributes in WKT string changes results
Posted by Martin Desruisseaux <ma...@geomatys.com>.
Hello Thierry
Le 24/10/2019 à 23:40, Thierry Danard a écrit :
> After
> using AbstractCRS.castOrCopy(...).forConvention(AxesConvention.DISPLAY_ORIENTED),
> I was able to get consistent results
>
Thanks for letting us know. Alternatively, it is also possible to use
WKTFormat [1] which provides some control on the parsing. In particular,
the following line:
format.setConvention(Convention.WKT1_IGNORE_AXES);
instructs the parser to ignore the AXIS declarations in WKT, in which
case the default is EAST, NORTH axis directions in degrees or metres.
This setting also has another effect on unit of measurements which may
also affect the results when using some old Coordinate Reference System
with grads angular units instead than degrees. The javadoc [2] gives
some more details. Those different conventions are provided for
compatibility with different software who had different interpretations
of WKT 1 specification.
Martin
[1] http://sis.apache.org/apidocs/org/apache/sis/io/wkt/WKTFormat.html
[2] http://sis.apache.org/apidocs/org/apache/sis/io/wkt/Convention.html#WKT1_IGNORE_AXES
Re: Order of axis attributes in WKT string changes results
Posted by Thierry Danard <th...@int.com>.
Thank you
After
using AbstractCRS.castOrCopy(...).forConvention(AxesConvention.DISPLAY_ORIENTED),
I was able to get consistent results
Here is the updated unit test
@Test
public void testWKT throws FactoryException, Exception {
String wkt = "PROJCS[\"NAD27 / Texas South Central\","
+ "GEOGCS[\"NAD27\","
+ "DATUM[\"North American Datum 1927\","
+ "SPHEROID[\"Clarke 1866\", 6378206.4, 294.97869821]],"
+ "UNIT[\"degree\",0.0174532925199433],"
+ "AXIS[\"Lat\",NORTH],"
+ "AXIS[\"Long\",EAST]],"
+ "PROJECTION[\"Lambert_Conformal_Conic_2SP\"],"
+ "PARAMETER[\"latitude_of_origin\",27.83333333333333],"
+ "PARAMETER[\"central_meridian\",-99.0],"
+ "PARAMETER[\"standard_parallel_1\",28.383333333333],"
+ "PARAMETER[\"standard_parallel_2\",30.283333333333],"
+ "PARAMETER[\"false_easting\",2000000],"
+ "PARAMETER[\"false_northing\",0],"
+ "UNIT[\"US survey foot\",0.304800609601219],"
+ "AXIS[\"Y\",NORTH],"
+ "AXIS[\"X\",EAST]]";
CoordinateReferenceSystem fromCrs = CRS.fromWKT(wkt);
CoordinateReferenceSystem toCrs = CRS.forCode("EPSG:4326");
CoordinateReferenceSystem displayOrientedFromCrs =
AbstractCRS.castOrCopy(fromCrs).forConvention(AxesConvention.DISPLAY_ORIENTED);
CoordinateReferenceSystem displayOrientedToCrs =
AbstractCRS.castOrCopy(toCrs).forConvention(AxesConvention.DISPLAY_ORIENTED);
double x = 1934615.424;
double y = 506052.281;
CoordinateOperation operation =
CRS.findOperation(displayOrientedFromCrs, displayOrientedToCrs,
ExtentUtil.getExtentFromAreaOfUse(displayOrientedFromCrs, x, y, x, y));
DirectPosition position = new DirectPosition2D(x, y);
double[] coordinate =
operation.getMathTransform().transform(position, position).getCoordinate();
Assert.assertEquals(coordinate[0], -99.205, 0.001);
Assert.assertEquals(coordinate[1], 29.225, 0.001);
}
public static DefaultGeographicBoundingBox
getExtentFromAreaOfUse(CoordinateReferenceSystem displayOrientedFromCrs,
double minX, double minY, double maxX, double maxY) throws
Exception {
CoordinateReferenceSystem toCrs = CRS.forCode("EPSG:4326");
AbstractCRS displayOrientedToCrs =
AbstractCRS.castOrCopy(toCrs).forConvention(AxesConvention.DISPLAY_ORIENTED);
// longitude should be first
CoordinateOperation operation =
CRS.findOperation(displayOrientedFromCrs, displayOrientedToCrs, null);
MathTransform mt = operation.getMathTransform();
DirectPosition topLeftPosition = new DirectPosition2D(minX, maxY);
DirectPosition topRightPosition = new DirectPosition2D(maxX, maxY);
DirectPosition bottomRightPosition = new DirectPosition2D(maxX,
minY);
DirectPosition bottomLeftPosition = new DirectPosition2D(minX,
minY);
DirectPosition topLeftLatLongPosition =
mt.transform(topLeftPosition, topLeftPosition);
DirectPosition topRightLatLongPosition =
mt.transform(topRightPosition, topRightPosition);
DirectPosition bottomLeftLatLongPosition =
mt.transform(bottomLeftPosition, bottomLeftPosition);
DirectPosition bottomRightLatLongPosition =
mt.transform(bottomRightPosition, bottomRightPosition);
double westBoundLongitude =
Math.min(topLeftLatLongPosition.getCoordinate()[0],
bottomLeftLatLongPosition.getCoordinate()[0]);
double eastBoundLongitude =
Math.max(topLeftLatLongPosition.getCoordinate()[0],
bottomLeftLatLongPosition.getCoordinate()[0]);
double southBoundLatitude =
Math.min(topRightLatLongPosition.getCoordinate()[1],
bottomRightLatLongPosition.getCoordinate()[1]);
double northBoundLatitude =
Math.max(topRightLatLongPosition.getCoordinate()[1],
bottomRightLatLongPosition.getCoordinate()[1]);
return new DefaultGeographicBoundingBox(westBoundLongitude,
eastBoundLongitude, southBoundLatitude, northBoundLatitude);
}
On Wed, Oct 23, 2019 at 3:02 AM Martin Desruisseaux <
martin.desruisseaux@geomatys.com> wrote:
> Hello Thierry
>
> Le 23/10/2019 à 01:10, Thierry Danard a écrit :
>
> I noticed a surprising behavior, I do not know whether this is a bug, or
> whether it's expected: I found that when the order of the AXIS attributes
> is changed, the conversion returns different results (...snip...) If I
> change the WKT from "AXIS["X",EAST], AXIS["Y",NORTH]]" to "AXIS["Y",NORTH],
> AXIS["X",EAST]]" I get a different, incorrect result.
>
> This is expected. The AXIS attributes that are swapped in the test are
> the axes of the source CRS ("fromCRS"). Those axes define the expected
> order of coordinates given to the "transform" methods. If the AXIS
> attributes of the source CRS are swapped, then the input coordinate values
> need to be swapped to. In the following part of the test:
>
> double y = 1934615.424;
> double x = 506052.281;
>
> Just rename "y" as "x" and "x" as "y", and we are back on the expected
> results.
>
> Regards,
>
> Martin
>
>
>
Re: Order of axis attributes in WKT string changes results
Posted by Martin Desruisseaux <ma...@geomatys.com>.
Le 23/10/2019 à 10:02, Martin Desruisseaux a écrit :
> Just rename "y" as "x" and "x" as "y", and we are back on the expected
> results.
>
Just to clarify, swapping the values in the call to "transform" would be
conceptually more appropriate than renaming those variables; the
renaming was just a trick for going quickly.
As a side note, I noticed that the getExtentFromAreaOfUse method
transforms a rectangle. Just for information, SIS provides also an
Envelopes class with static methods doing this task, taking in account
the curvature caused by the projection:
http://sis.apache.org/apidocs/org/apache/sis/geometry/Envelopes.html
Martin
Re: Order of axis attributes in WKT string changes results
Posted by Martin Desruisseaux <ma...@geomatys.com>.
Hello Thierry
Le 23/10/2019 à 01:10, Thierry Danard a écrit :
> I noticed a surprising behavior, I do not know whether this is a bug,
> or whether it's expected: I found that when the order of the AXIS
> attributes is changed, the conversion returns different results
> (...snip...) If I change the WKT from "AXIS["X",EAST],
> AXIS["Y",NORTH]]" to "AXIS["Y",NORTH], AXIS["X",EAST]]" I get a
> different, incorrect result.
This is expected. The AXIS attributes that are swapped in the test are
the axes of the source CRS ("fromCRS"). Those axes define the expected
order of coordinates given to the "transform" methods. If the AXIS
attributes of the source CRS are swapped, then the input coordinate
values need to be swapped to. In the following part of the test:
double y = 1934615.424;
double x = 506052.281;
Just rename "y" as "x" and "x" as "y", and we are back on the expected
results.
Regards,
Martin