Skip to content

Commit

Permalink
Fix buffer element erosion for negative distance and remove overlay d…
Browse files Browse the repository at this point in the history
…eps (#1119)
  • Loading branch information
dr-jts authored Feb 12, 2025
1 parent 6bdb50a commit 49a6349
Show file tree
Hide file tree
Showing 6 changed files with 451 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@
import org.locationtech.jts.noding.MCIndexNoder;
import org.locationtech.jts.noding.Noder;
import org.locationtech.jts.noding.SegmentString;
import org.locationtech.jts.operation.overlay.OverlayNodeFactory;
import org.locationtech.jts.operation.overlay.PolygonBuilder;



/**
* Builds the buffer geometry for a given input geometry and precision model.
Expand Down Expand Up @@ -167,7 +163,7 @@ public Geometry buffer(Geometry g, double distance)
boolean isNodingValidated = distance == 0.0;
computeNodedEdges(bufferSegStrList, precisionModel, isNodingValidated);

graph = new PlanarGraph(new OverlayNodeFactory());
graph = new PlanarGraph(new BufferNodeFactory());
graph.addEdges(edgeList.getEdges());

List subgraphList = createSubgraphs(graph);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2016 Vivid Solutions.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.locationtech.jts.operation.buffer;

/**
* @version 1.7
*/
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geomgraph.DirectedEdgeStar;
import org.locationtech.jts.geomgraph.Node;
import org.locationtech.jts.geomgraph.NodeFactory;
import org.locationtech.jts.geomgraph.PlanarGraph;

/**
* Creates nodes for use in the {@link PlanarGraph}s constructed during
* buffer operations.
*
* @version 1.7
*/
class BufferNodeFactory
extends NodeFactory
{
public Node createNode(Coordinate coord)
{
return new Node(coord, new DirectedEdgeStar());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2016 Vivid Solutions.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.locationtech.jts.operation.buffer;

import java.util.ArrayList;
import java.util.List;

import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geomgraph.DirectedEdge;
import org.locationtech.jts.geomgraph.DirectedEdgeStar;
import org.locationtech.jts.geomgraph.EdgeRing;
import org.locationtech.jts.geomgraph.Node;

/**
* A ring of {@link DirectedEdge}s which may contain nodes of degree > 2.
* A <tt>MaximalEdgeRing</tt> may represent two different spatial entities:
* <ul>
* <li>a single polygon possibly containing inversions (if the ring is oriented CW)
* <li>a single hole possibly containing exversions (if the ring is oriented CCW)
* </ul>
* If the MaximalEdgeRing represents a polygon,
* the interior of the polygon is strongly connected.
* <p>
* These are the form of rings used to define polygons under some spatial data models.
* However, under the OGC SFS model, {@link MinimalEdgeRing}s are required.
* A MaximalEdgeRing can be converted to a list of MinimalEdgeRings using the
* {@link #buildMinimalRings() } method.
*
* @version 1.7
* @see org.locationtech.jts.operation.buffer.MinimalEdgeRing
*/
class MaximalEdgeRing
extends EdgeRing
{

public MaximalEdgeRing(DirectedEdge start, GeometryFactory geometryFactory) {
super(start, geometryFactory);
}

public DirectedEdge getNext(DirectedEdge de)
{
return de.getNext();
}
public void setEdgeRing(DirectedEdge de, EdgeRing er)
{
de.setEdgeRing(er);
}

/**
* For all nodes in this EdgeRing,
* link the DirectedEdges at the node to form minimalEdgeRings
*/
public void linkDirectedEdgesForMinimalEdgeRings()
{
DirectedEdge de = startDe;
do {
Node node = de.getNode();
((DirectedEdgeStar) node.getEdges()).linkMinimalDirectedEdges(this);
de = de.getNext();
} while (de != startDe);
}

public List buildMinimalRings()
{
List minEdgeRings = new ArrayList();
DirectedEdge de = startDe;
do {
if (de.getMinEdgeRing() == null) {
EdgeRing minEr = new MinimalEdgeRing(de, geometryFactory);
minEdgeRings.add(minEr);
}
de = de.getNext();
} while (de != startDe);
return minEdgeRings;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2016 Vivid Solutions.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.locationtech.jts.operation.buffer;

import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geomgraph.DirectedEdge;
import org.locationtech.jts.geomgraph.Edge;
import org.locationtech.jts.geomgraph.EdgeRing;

/**
* A ring of {@link Edge}s with the property that no node
* has degree greater than 2. These are the form of rings required
* to represent polygons under the OGC SFS spatial data model.
*
* @version 1.7
* @see org.locationtech.jts.operation.buffer.MaximalEdgeRing
*/
class MinimalEdgeRing
extends EdgeRing
{

public MinimalEdgeRing(DirectedEdge start, GeometryFactory geometryFactory) {
super(start, geometryFactory);
}

public DirectedEdge getNext(DirectedEdge de)
{
return de.getNextMin();
}
public void setEdgeRing(DirectedEdge de, EdgeRing er)
{
de.setMinEdgeRing(er);
}

}
Loading

0 comments on commit 49a6349

Please sign in to comment.