@Test public void testSelfIntersectLeft() throws Exception { Geometry geom = geometry("LINESTRING(0 0, 10 0, 10 -10, 3 -10, 3 3)"); Geometry offset = offset(geom, 2); assertTrue(offset.isValid()); assertTrue(offset.getLength() > 0); Geometry expected = geometry( "LINESTRING (0 2, 10 2, 10.34729635533386 1.969615506024416, 10.684040286651337 1.8793852415718169, 11 1.7320508075688774, 11.28557521937308 1.532088886237956, 11.532088886237956 1.2855752193730787, 11.732050807568877 1.0000000000000002, 11.879385241571816 0.6840402866513376, 11.969615506024416 0.3472963553338608, 12 0.0000000000000001, 12 -10, 11.969615506024416 -10.34729635533386, 11.879385241571818 -10.684040286651337, 11.732050807568877 -11, 11.532088886237956 -11.28557521937308, 11.28557521937308 -11.532088886237956, 11 -11.732050807568877, 10.684040286651339 -11.879385241571816, 10.34729635533386 -11.969615506024416, 10 -12, 2.9999999999999996 -12, 2.6527036446661394 -11.969615506024416, 2.3159597133486622 -11.879385241571816, 2 -11.732050807568877, 1.714424780626921 -11.532088886237956, 1.467911113762044 -11.28557521937308, 1.2679491924311228 -11, 1.1206147584281831 -10.684040286651337, 1.030384493975584 -10.34729635533386, 1 -10, 1 3)"); assertTrue(expected.equalsExact(offset, 0.1)); }
public Geometry offset(Geometry g) { if (abs(offset) < EPS) { return g; } if (g == null) { return null; } double threshold = abs(offset) / 10; final List<LineString> lines = extractLineStrings(g); List<LineString> offsets = new ArrayList<>(); for (LineString ls : lines) { LineString simplified = (LineString) DouglasPeuckerSimplifier.simplify(ls, threshold); if (simplified == null) { return null; } if (ls.isClosed() && !simplified.isClosed()) { CoordinateSequence source = simplified.getCoordinateSequence(); int numCoordinates = source.size(); LiteCoordinateSequence dest = new LiteCoordinateSequence(numCoordinates + 1, 2); for (int i = 0; i < numCoordinates; i++) { dest.setOrdinate(i, 0, source.getOrdinate(i, 0)); dest.setOrdinate(i, 1, source.getOrdinate(i, 1)); } dest.setOrdinate(numCoordinates, 0, source.getOrdinate(0, 0)); dest.setOrdinate(numCoordinates, 1, source.getOrdinate(0, 1)); simplified = simplified.getFactory().createLinearRing(dest); } LineString offsetLine = (LineString) offset(simplified); if (offsetLine != null) { offsets.add(offsetLine); } } if (offsets.isEmpty()) { return null; } else if (offsets.size() == 1) { return offsets.get(0); } else { GeometryFactory factory = offsets.get(0).getFactory(); MultiLineString result = factory.createMultiLineString(offsets.toArray(new LineString[offsets.size()])); return result; } }
OffsetCurveBuilder { public Geometry offset(Geometry g) { if (abs(offset) < EPS) { return g; } if (g == null) { return null; } double threshold = abs(offset) / 10; final List<LineString> lines = extractLineStrings(g); List<LineString> offsets = new ArrayList<>(); for (LineString ls : lines) { LineString simplified = (LineString) DouglasPeuckerSimplifier.simplify(ls, threshold); if (simplified == null) { return null; } if (ls.isClosed() && !simplified.isClosed()) { CoordinateSequence source = simplified.getCoordinateSequence(); int numCoordinates = source.size(); LiteCoordinateSequence dest = new LiteCoordinateSequence(numCoordinates + 1, 2); for (int i = 0; i < numCoordinates; i++) { dest.setOrdinate(i, 0, source.getOrdinate(i, 0)); dest.setOrdinate(i, 1, source.getOrdinate(i, 1)); } dest.setOrdinate(numCoordinates, 0, source.getOrdinate(0, 0)); dest.setOrdinate(numCoordinates, 1, source.getOrdinate(0, 1)); simplified = simplified.getFactory().createLinearRing(dest); } LineString offsetLine = (LineString) offset(simplified); if (offsetLine != null) { offsets.add(offsetLine); } } if (offsets.isEmpty()) { return null; } else if (offsets.size() == 1) { return offsets.get(0); } else { GeometryFactory factory = offsets.get(0).getFactory(); MultiLineString result = factory.createMultiLineString(offsets.toArray(new LineString[offsets.size()])); return result; } } }
OffsetCurveBuilder { public Geometry offset(Geometry g) { if (abs(offset) < EPS) { return g; } if (g == null) { return null; } double threshold = abs(offset) / 10; final List<LineString> lines = extractLineStrings(g); List<LineString> offsets = new ArrayList<>(); for (LineString ls : lines) { LineString simplified = (LineString) DouglasPeuckerSimplifier.simplify(ls, threshold); if (simplified == null) { return null; } if (ls.isClosed() && !simplified.isClosed()) { CoordinateSequence source = simplified.getCoordinateSequence(); int numCoordinates = source.size(); LiteCoordinateSequence dest = new LiteCoordinateSequence(numCoordinates + 1, 2); for (int i = 0; i < numCoordinates; i++) { dest.setOrdinate(i, 0, source.getOrdinate(i, 0)); dest.setOrdinate(i, 1, source.getOrdinate(i, 1)); } dest.setOrdinate(numCoordinates, 0, source.getOrdinate(0, 0)); dest.setOrdinate(numCoordinates, 1, source.getOrdinate(0, 1)); simplified = simplified.getFactory().createLinearRing(dest); } LineString offsetLine = (LineString) offset(simplified); if (offsetLine != null) { offsets.add(offsetLine); } } if (offsets.isEmpty()) { return null; } else if (offsets.size() == 1) { return offsets.get(0); } else { GeometryFactory factory = offsets.get(0).getFactory(); MultiLineString result = factory.createMultiLineString(offsets.toArray(new LineString[offsets.size()])); return result; } } OffsetCurveBuilder(double offset);  OffsetCurveBuilder(double offset, int quadrantSegments); }
OffsetCurveBuilder { public Geometry offset(Geometry g) { if (abs(offset) < EPS) { return g; } if (g == null) { return null; } double threshold = abs(offset) / 10; final List<LineString> lines = extractLineStrings(g); List<LineString> offsets = new ArrayList<>(); for (LineString ls : lines) { LineString simplified = (LineString) DouglasPeuckerSimplifier.simplify(ls, threshold); if (simplified == null) { return null; } if (ls.isClosed() && !simplified.isClosed()) { CoordinateSequence source = simplified.getCoordinateSequence(); int numCoordinates = source.size(); LiteCoordinateSequence dest = new LiteCoordinateSequence(numCoordinates + 1, 2); for (int i = 0; i < numCoordinates; i++) { dest.setOrdinate(i, 0, source.getOrdinate(i, 0)); dest.setOrdinate(i, 1, source.getOrdinate(i, 1)); } dest.setOrdinate(numCoordinates, 0, source.getOrdinate(0, 0)); dest.setOrdinate(numCoordinates, 1, source.getOrdinate(0, 1)); simplified = simplified.getFactory().createLinearRing(dest); } LineString offsetLine = (LineString) offset(simplified); if (offsetLine != null) { offsets.add(offsetLine); } } if (offsets.isEmpty()) { return null; } else if (offsets.size() == 1) { return offsets.get(0); } else { GeometryFactory factory = offsets.get(0).getFactory(); MultiLineString result = factory.createMultiLineString(offsets.toArray(new LineString[offsets.size()])); return result; } } OffsetCurveBuilder(double offset);  OffsetCurveBuilder(double offset, int quadrantSegments); Geometry offset(Geometry g); }
OffsetCurveBuilder { public Geometry offset(Geometry g) { if (abs(offset) < EPS) { return g; } if (g == null) { return null; } double threshold = abs(offset) / 10; final List<LineString> lines = extractLineStrings(g); List<LineString> offsets = new ArrayList<>(); for (LineString ls : lines) { LineString simplified = (LineString) DouglasPeuckerSimplifier.simplify(ls, threshold); if (simplified == null) { return null; } if (ls.isClosed() && !simplified.isClosed()) { CoordinateSequence source = simplified.getCoordinateSequence(); int numCoordinates = source.size(); LiteCoordinateSequence dest = new LiteCoordinateSequence(numCoordinates + 1, 2); for (int i = 0; i < numCoordinates; i++) { dest.setOrdinate(i, 0, source.getOrdinate(i, 0)); dest.setOrdinate(i, 1, source.getOrdinate(i, 1)); } dest.setOrdinate(numCoordinates, 0, source.getOrdinate(0, 0)); dest.setOrdinate(numCoordinates, 1, source.getOrdinate(0, 1)); simplified = simplified.getFactory().createLinearRing(dest); } LineString offsetLine = (LineString) offset(simplified); if (offsetLine != null) { offsets.add(offsetLine); } } if (offsets.isEmpty()) { return null; } else if (offsets.size() == 1) { return offsets.get(0); } else { GeometryFactory factory = offsets.get(0).getFactory(); MultiLineString result = factory.createMultiLineString(offsets.toArray(new LineString[offsets.size()])); return result; } } OffsetCurveBuilder(double offset);  OffsetCurveBuilder(double offset, int quadrantSegments); Geometry offset(Geometry g); static int QUADRANT_SEGMENTS_DEFAULT; static double DEFAULT_THRESHOLD_RATIO; }