@Test public void testElongatedLoopGenerator() throws Exception { Geometry geom = geometry("LINESTRING(0 0, 5 0, 5 -10, 7 -10, 7 0, 10 0)"); Geometry offset = offset(geom, 1.5); assertTrue(offset.isValid()); assertTrue(offset.getLength() > 0); Geometry expected = geometry( "LINESTRING (0 1.5, 5 1.5, 5.260472266500395 1.477211629518312, 5.513030214988503 1.4095389311788626, 5.75 1.299038105676658, 5.964181414529809 1.149066664678467, 6.149066664678467 0.9641814145298091, 6.299038105676658 0.7500000000000002, 6.409538931178862 0.5130302149885032, 6.477211629518312 0.2604722665003956, 6.5 0.0000000000000001, 6.5 -8.5, 5.5 -8.5, 5.5 0.0000000000000001, 5.522788370481688 0.2604722665003956, 5.590461068821138 0.5130302149885032, 5.700961894323342 0.7499999999999998, 5.850933335321533 0.9641814145298091, 6.035818585470191 1.149066664678467, 6.25 1.299038105676658, 6.486969785011497 1.4095389311788624, 6.739527733499605 1.477211629518312, 7 1.5, 10 1.5)"); 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; }