-
Notifications
You must be signed in to change notification settings - Fork 449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix writing XYM geometries as WKB #1092
base: master
Are you sure you want to change the base?
Fix writing XYM geometries as WKB #1092
Conversation
@@ -0,0 +1,79 @@ | |||
/* | |||
* Copyright (c) 2016 Vivid Solutions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is incorrect for a new file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All source code in this file is taken from WKTWriter.java
, which is an old file. Should we update the copyright header or preserve the copyright header of the file where it originates from?
Issue #733 is closed but the problem still exists in the latest master. |
@jodygarnett @dr-jts Would you please merge this PR? We are working on adding Geo support into Apache Iceberg and Parquet Java reader and writer. JTS is a fundamental lib in this process. WKB is the encoding mechanism used in all these PRs. |
@jnh5y CC James too 🙏🏻 |
I'd like to provide more context for the problem we are solving. Given the following String wkt = "MULTILINESTRING M((1 1 1, 2 2 2))";
WKTReader wktReader = new WKTReader();
Geometry geometryBefore = wktReader.read(wkt); Writing it using WKBWriter and read it back using WKBReader will result in a WKBWriter wkbWriter = new WKBWriter(3);
byte[] write = wkbWriter.write(geometryBefore);
WKBReader wkbReader = new WKBReader();
Geometry geometryAfter = wkbReader.read(write);
System.out.println(Arrays.asList(geometryAfter.getCoordinates())); // [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0)] If we use WKTWriter and WKTReader for serializing and deserializing the WKTWriter wktWriter = new WKTWriter(3);
String write = wktWriter.write(geometryBefore);
Geometry geometryAfter = wktReader.read(write);
System.out.println(Arrays.asList(geometryAfter.getCoordinates())); // [(1.0, 1.0, NaN), (2.0, 2.0, NaN)] We found that JTS will only output M ordinate when WKTWriter wktWriter = new WKTWriter(4);
String write = wktWriter.write(geometryBefore);
System.out.println(write); // MULTILINESTRING M((1 1 1, 2 2 2))
Geometry geometryAfter = wktReader.read(write);
System.out.println(Arrays.asList(geometryAfter.getCoordinates())); // [(1.0, 1.0 m=1.0), (2.0, 2.0 m=2.0)] I believe that WKBWriter should behave the same as WKTWriter. However, specifying WKBWriter wkbWriter = new WKBWriter(4);
byte[] write = wkbWriter.write(geometryBefore); // <- exception raised here
// java.lang.IllegalArgumentException: Invalid ordinate index: 3
//
// at org.locationtech.jts.geom.CoordinateXYM.getOrdinate(CoordinateXYM.java:140)
// at org.locationtech.jts.geom.impl.CoordinateArraySequence.getOrdinate(CoordinateArraySequence.java:260)
// at org.locationtech.jts.io.WKBWriter.writeCoordinate(WKBWriter.java:524)
// at org.locationtech.jts.io.WKBWriter.writeCoordinateSequence(WKBWriter.java:502)
// at org.locationtech.jts.io.WKBWriter.writeLineString(WKBWriter.java:425)
// at org.locationtech.jts.io.WKBWriter.write(WKBWriter.java:388)
// at org.locationtech.jts.io.WKBWriter.writeGeometryCollection(WKBWriter.java:454)
// at org.locationtech.jts.io.WKBWriter.write(WKBWriter.java:395)
// at org.locationtech.jts.io.WKBWriter.write(WKBWriter.java:367) This PR resolves the above issue by making the behavior of WKBWriter consistent with WKTWriter. No Z or M ordinates will be written with WKBWriter wkbWriter = new WKBWriter(3);
byte[] write = wkbWriter.write(geometryBefore);
WKBReader wkbReader = new WKBReader();
Geometry geometryAfter = wkbReader.read(write);
System.out.println(Arrays.asList(geometryAfter.getCoordinates())); // [(1.0, 1.0), (2.0, 2.0)] The M ordinate will be written as expected with WKBWriter wkbWriter = new WKBWriter(4);
byte[] write = wkbWriter.write(geometryBefore);
WKBReader wkbReader = new WKBReader();
Geometry geometryAfter = wkbReader.read(write);
System.out.println(Arrays.asList(geometryAfter.getCoordinates())); // [(1.0, 1.0 m=1.0), (2.0, 2.0 m=2.0)] |
Fixes #733
Please note that we must specify
outputDimension = 4
when writing geometries with M dimension, even when the geometry is XYM instead of XYZM. This behavior is the same as WKTWriter.