LineStringCursor { public double getMaxAngleChange(double startOrdinate, double endOrdinate) { if (startOrdinate > endOrdinate) throw new IllegalArgumentException("Invalid arguments, endOrdinate < starOrdinate"); LineStringCursor delegate = new LineStringCursor(this); delegate.moveTo(startOrdinate); int startSegment = delegate.segment; delegate.moveTo(endOrdinate); int endSegment = delegate.segment; if (startSegment == endSegment) return 0; double maxDifference = 0; double prevAngle = getSegmentAngle(startSegment); for (int i = startSegment + 1; i <= endSegment; i++) { double currAngle = getSegmentAngle(i); double difference = currAngle - prevAngle; if(difference > Math.PI) { difference -= 2 * Math.PI; } else if(difference < -Math.PI) { difference += 2 * Math.PI; } difference = Math.abs(difference); if (difference > maxDifference) maxDifference = difference; prevAngle = currAngle; } return maxDifference; } LineStringCursor(LineString ls);  LineStringCursor(LineStringCursor cursor); double getLineStringLength(); void moveTo(double ordinate); boolean moveRelative(double offset); Coordinate getCurrentPosition(); Coordinate getCurrentPosition(Coordinate c); double getCurrentOrdinate(); double getCurrentAngle(); double getLabelOrientation(); double getMaxAngleChange(double startOrdinate, double endOrdinate); LineStringCursor reverse(); LineString getLineString(); LineString getSubLineString(double startOrdinate, double endOrdinate);  }
@Test public void testMaxAngle() throws Exception { LineString ls = (LineString) new WKTReader().read("LINESTRING(20 0, 10 1, 0 0)"); LineStringCursor cursor = new LineStringCursor(ls); double maxAngle = cursor.getMaxAngleChange(0, ls.getLength()); assertTrue(maxAngle < 11.5); }