jts icon indicating copy to clipboard operation
jts copied to clipboard

CoordinateXYM causes invalid ordinate exception

Open jnh5y opened this issue 6 years ago • 9 comments

Hugh reported an issue with LineStringM on the GeoTools-user list. From the message:

"I can create a LinestringM object from an array of CoordinateXYM objects. But calling a function on the geom (e.g. line.getLength()) causes the following error. (I’m using Java 11).

Exception in thread "MyAppClient-StreamThread-1" java.lang.IllegalArgumentException: Invalid ordinate index: 3

            at org.locationtech.jts.geom.Coordinate.setM(Coordinate.java:190)

            at org.locationtech.jts.geom.impl.CoordinateArraySequence.getCoordinate(CoordinateArraySequence.java:234)

            at org.locationtech.jts.algorithm.Length.ofLine(Length.java:41)

            at org.locationtech.jts.geom.LineString.getLength(LineString.java:163)

            at au.com.iag.transformation.local.setup.SJSummaryAggregation.lambda$main$1(SJSummaryAggregation.java:136)

            at org.apache.kafka.streams.kstream.internals.KStreamAggregate$KStreamAggregateProcessor.process(KStreamAggregate.java:91)

            at org.apache.kafka.streams.processor.internals.ProcessorNode.process(ProcessorNode.java:115)

....

Here’s my code:

                        CoordinateXYM[] coords = new CoordinateXYM[num_points];

                        int i = 0;



                        for (Waypoint waypoint : waypoints) {

                            CoordinateXYM coord = new CoordinateXYM(waypoint.getLon(), waypoint.getLat(), waypoint.getUnixTime());

                            coords[i] = coord;

                            i++;

                        }



                        LineString line = geometryFactory.createLineString(coords);



                        System.out.println(line.getLength());

"

jnh5y avatar Feb 14 '19 15:02 jnh5y

Thanks for filing this, @jnh5y

The createLineString method converts the arg coordinate array into a CoordinateSequence using the CoordinateSequenceFactory defined in the geometryFactory. So that might be an important piece of information as well.

But I will try testing with the default CoordinateArraySequenceFactory and see if the error can be reproduced.

Amazing how hard it is to get the new Coordinate dimension extensions right...

dr-jts avatar Feb 14 '19 17:02 dr-jts

This error does not occur in master. I have added a unit test for it in #371.

I think there was some fixes to the Coordinate craziness post-release of 1.16? So maybe this is an issue with older code?

dr-jts avatar Feb 14 '19 18:02 dr-jts

FYI - I was using the version of JTS in Geotools 21-RC

minus34 avatar Feb 14 '19 23:02 minus34

Can you indicate the exact JTS jar version?

dr-jts avatar Feb 15 '19 01:02 dr-jts

jts-core version is 1.16.0.

Also, @jodygarnett made this point on the GeoTools-user list:

Can you confirm you have setup the geometryFactory with the correct dimensions?

I haven't done that in my code due to lack of Geotools experience. I'm simply using the default geometryFactory, i.e:

GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);

Does this relate to the issue?

minus34 avatar Feb 15 '19 01:02 minus34

This is caused by a bug in 1.16. The bug was fixed in #333.

dr-jts avatar Feb 15 '19 01:02 dr-jts

@jodygarnett Can this be closed?

dr-jts avatar Feb 24 '19 06:02 dr-jts

Actually I was just about to open a new bug regarding this behavior... when I saw NTS's tests failing, I saw that the defect is actually in the code implicated by the stack trace itself: https://github.com/locationtech/jts/blob/a579291fbd1c1313652c701aa32e0d35e02e0030/modules/core/src/main/java/org/locationtech/jts/algorithm/Length.java#L40-L41

I feel like a fix that only touches CoordinateArraySequence is naive, because the problem isn't specific to that implementation; it's actually that we should be using createCoordinate instead of new Coordinate() for any coordinates that we want to use as the target of getCoordinate(int, Coordinate).

  • At least, assuming that I'm not completely wrong about this being the use case for createCoordinate...

Full disclosure, I've only ported the commits up to 1.16.0, so it's possible that a later fix might have addressed this... I've only looked at the code on master to confirm that the issue is still present in the callers, and that it would likely be present when using packed sequences or other sequences that assume that the Coordinate given to getCoordinate(int, Coordinate) was created via createCoordinate() (which should be a fair assumption because of this note in the javadoc).

My initial fixes were here: NetTopologySuite/NetTopologySuite@35fa4fc (note how RectangleIntersects was solved, to keep heap allocations the same), and so these are the equivalent spots in JTS (edit: missed NetTopologySuite/NetTopologySuite@65bd052 which was masked by another NTS-specific problem):

  1. https://github.com/locationtech/jts/blob/a579291fbd1c1313652c701aa32e0d35e02e0030/modules/core/src/main/java/org/locationtech/jts/algorithm/Area.java#L96-L100
  2. https://github.com/locationtech/jts/blob/a579291fbd1c1313652c701aa32e0d35e02e0030/modules/core/src/main/java/org/locationtech/jts/algorithm/Length.java#L40-L41
  3. https://github.com/locationtech/jts/blob/a579291fbd1c1313652c701aa32e0d35e02e0030/modules/core/src/main/java/org/locationtech/jts/algorithm/PointLocation.java#L62-L67
  4. https://github.com/locationtech/jts/blob/a579291fbd1c1313652c701aa32e0d35e02e0030/modules/core/src/main/java/org/locationtech/jts/operation/distance3d/Distance3DOp.java#L412-L420
  5. https://github.com/locationtech/jts/blob/a579291fbd1c1313652c701aa32e0d35e02e0030/modules/core/src/main/java/org/locationtech/jts/operation/predicate/RectangleContains.java#L126-L130
  6. https://github.com/locationtech/jts/blob/a579291fbd1c1313652c701aa32e0d35e02e0030/modules/core/src/main/java/org/locationtech/jts/operation/predicate/RectangleIntersects.java#L233-L236
  7. Combination of
    • https://github.com/locationtech/jts/blob/a579291fbd1c1313652c701aa32e0d35e02e0030/modules/core/src/main/java/org/locationtech/jts/operation/predicate/RectangleIntersects.java#L269-L270
    • https://github.com/locationtech/jts/blob/a579291fbd1c1313652c701aa32e0d35e02e0030/modules/core/src/main/java/org/locationtech/jts/operation/predicate/RectangleIntersects.java#L327-L328

It's possible that there are more; these are just the ones that caused our tests to fail, because (at least for the time being) our base Coordinate class changed to XY, so we started finding these kinds of errors even with plain ol' XYZ sequences.

Another edit: not sure if AxisPlaneCoordinateSequence.getDimension() returning 2 is going to be a problem for you too if this gets fixed... it was for me, so I'm having ours override CreateCoordinate to return a coordinate with the Z-ordinate.

airbreather avatar Mar 02 '19 14:03 airbreather

Good analysis, @airbreather . I think this is the same as #375 (but more general) ?

dr-jts avatar Mar 02 '19 16:03 dr-jts