Skip to content

Commit

Permalink
Enhance coverage simplification to handle dynamic tolerance. (One per…
Browse files Browse the repository at this point in the history
… geometry)

Signed-off-by: N_Strahl <[email protected]>
  • Loading branch information
nstrahl committed Mar 10, 2024
1 parent 7b1395b commit e4578b9
Show file tree
Hide file tree
Showing 6 changed files with 561 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,27 @@ public static Geometry simplify(Geometry coverage, double tolerance) {
Geometry[] result = CoverageSimplifier.simplify(cov, tolerance);
return FunctionsUtil.buildGeometry(result);
}

@Metadata(description="Simplify a coverage by providing one tolerance per geometry")
public static Geometry simplifyDynamicTolerance(Geometry coverage, String tolerances) {
Geometry[] cov = toGeometryArray(coverage);
Geometry[] result = CoverageSimplifier.simplify(cov, tolerances);
return FunctionsUtil.buildGeometry(result);
}

@Metadata(description="Simplify inner edges of a coverage")
public static Geometry simplifyinner(Geometry coverage, double tolerance) {
Geometry[] cov = toGeometryArray(coverage);
Geometry[] result = CoverageSimplifier.simplifyInner(cov, tolerance);
return FunctionsUtil.buildGeometry(result);
}

@Metadata(description="Simplify inner edges of a coverage by providing one tolerance per geometry")
public static Geometry simplifyinnerDynamicTolerance(Geometry coverage, String tolerances) {
Geometry[] cov = toGeometryArray(coverage);
Geometry[] result = CoverageSimplifier.simplifyInner(cov, tolerances);
return FunctionsUtil.buildGeometry(result);
}

static Geometry extractPolygons(Geometry geom) {
List components = PolygonExtracter.getPolygons(geom);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@
*/
class CoverageEdge {

public static CoverageEdge createEdge(Coordinate[] ring) {
public static CoverageEdge createEdge(Coordinate[] ring, double tolerance) {
Coordinate[] pts = extractEdgePoints(ring, 0, ring.length - 1);
CoverageEdge edge = new CoverageEdge(pts, true);
CoverageEdge edge = new CoverageEdge(pts, true, tolerance);
return edge;
}

public static CoverageEdge createEdge(Coordinate[] ring, int start, int end) {
public static CoverageEdge createEdge(Coordinate[] ring, int start, int end, double tolerance) {
Coordinate[] pts = extractEdgePoints(ring, start, end);
CoverageEdge edge = new CoverageEdge(pts, false);
CoverageEdge edge = new CoverageEdge(pts, false, tolerance);
return edge;
}

Expand Down Expand Up @@ -137,9 +137,12 @@ else if (i > pts.length - 1) {
private int ringCount = 0;
private boolean isFreeRing = true;

public CoverageEdge(Coordinate[] pts, boolean isFreeRing) {
private double tolerance = -1;

public CoverageEdge(Coordinate[] pts, boolean isFreeRing, double tolerance) {
this.pts = pts;
this.isFreeRing = isFreeRing;
this.tolerance = tolerance;
}

public void incRingCount() {
Expand All @@ -160,6 +163,10 @@ public boolean isFreeRing() {
return isFreeRing;
}

public double getTolerance() { return tolerance; }

public void setTolerance(double tolerance) { this.tolerance = tolerance; }

public void setCoordinates(Coordinate[] pts) {
this.pts = pts;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,30 @@ class CoverageRingEdges {
* Create a new instance for a given coverage.
*
* @param coverage the set of polygonal geometries in the coverage
* @param tolerances the simplification tolerances for each geometry
* @return the edges of the coverage
*/
public static CoverageRingEdges create(Geometry[] coverage, List<Double> tolerances) {
CoverageRingEdges edges = new CoverageRingEdges(coverage, tolerances);
return edges;
}

public static CoverageRingEdges create(Geometry[] coverage) {
CoverageRingEdges edges = new CoverageRingEdges(coverage);
CoverageRingEdges edges = new CoverageRingEdges(coverage, new ArrayList<Double>(0));
return edges;
}

private Geometry[] coverage;
private Map<LinearRing, List<CoverageEdge>> ringEdgesMap;
private List<CoverageEdge> edges;

public CoverageRingEdges(Geometry[] coverage) {

private List<Double> coverageTolerances;

public CoverageRingEdges(Geometry[] coverage, List<Double> tolerances) {
this.coverage = coverage;
ringEdgesMap = new HashMap<LinearRing, List<CoverageEdge>>();
edges = new ArrayList<CoverageEdge>();
coverageTolerances = tolerances;
build();
}

Expand Down Expand Up @@ -94,7 +103,8 @@ private void build() {
Set<LineSegment> boundarySegs = CoverageBoundarySegmentFinder.findBoundarySegments(coverage);
nodes.addAll(findBoundaryNodes(boundarySegs));
HashMap<LineSegment, CoverageEdge> uniqueEdgeMap = new HashMap<LineSegment, CoverageEdge>();
for (Geometry geom : coverage) {
for (int icoverage = 0; icoverage < coverage.length; icoverage++) {
Geometry geom = coverage[icoverage];
for (int ipoly = 0; ipoly < geom.getNumGeometries(); ipoly++) {
Polygon poly = (Polygon) geom.getGeometryN(ipoly);

Expand All @@ -104,23 +114,23 @@ private void build() {

//-- extract shell
LinearRing shell = poly.getExteriorRing();
addRingEdges(shell, nodes, boundarySegs, uniqueEdgeMap);
addRingEdges(icoverage, shell, nodes, boundarySegs, uniqueEdgeMap);
//-- extract holes
for (int ihole = 0; ihole < poly.getNumInteriorRing(); ihole++) {
LinearRing hole = poly.getInteriorRingN(ihole);
//-- skip empty rings. Missing rings are copied in result
if (hole.isEmpty())
continue;
addRingEdges(hole, nodes, boundarySegs, uniqueEdgeMap);
addRingEdges(icoverage, hole, nodes, boundarySegs, uniqueEdgeMap);
}
}
}
}

private void addRingEdges(LinearRing ring, Set<Coordinate> nodes, Set<LineSegment> boundarySegs,
private void addRingEdges(int coverageId, LinearRing ring, Set<Coordinate> nodes, Set<LineSegment> boundarySegs,
HashMap<LineSegment, CoverageEdge> uniqueEdgeMap) {
addBoundaryInnerNodes(ring, boundarySegs, nodes);
List<CoverageEdge> ringEdges = extractRingEdges(ring, uniqueEdgeMap, nodes);
List<CoverageEdge> ringEdges = extractRingEdges(coverageId, ring, uniqueEdgeMap, nodes);
if (ringEdges != null)
ringEdgesMap.put(ring, ringEdges);
}
Expand Down Expand Up @@ -149,8 +159,8 @@ private void addBoundaryInnerNodes(LinearRing ring, Set<LineSegment> boundarySeg
}
}

private List<CoverageEdge> extractRingEdges(LinearRing ring,
HashMap<LineSegment, CoverageEdge> uniqueEdgeMap,
private List<CoverageEdge> extractRingEdges(int coverageId, LinearRing ring,
HashMap<LineSegment, CoverageEdge> uniqueEdgeMap,
Set<Coordinate> nodes) {
// System.out.println(ring);
List<CoverageEdge> ringEdges = new ArrayList<CoverageEdge>();
Expand All @@ -164,15 +174,15 @@ private List<CoverageEdge> extractRingEdges(LinearRing ring,
int first = findNextNodeIndex(pts, -1, nodes);
if (first < 0) {
//-- ring does not contain a node, so edge is entire ring
CoverageEdge edge = createEdge(pts, uniqueEdgeMap);
CoverageEdge edge = createEdge(coverageId, pts, uniqueEdgeMap);
ringEdges.add(edge);
}
else {
int start = first;
int end = start;
do {
end = findNextNodeIndex(pts, start, nodes);
CoverageEdge edge = createEdge(pts, start, end, uniqueEdgeMap);
CoverageEdge edge = createEdge(coverageId, pts, start, end, uniqueEdgeMap);
// System.out.println(ringEdges.size() + " : " + edge);
ringEdges.add(edge);
start = end;
Expand All @@ -181,29 +191,37 @@ private List<CoverageEdge> extractRingEdges(LinearRing ring,
return ringEdges;
}

private CoverageEdge createEdge(Coordinate[] ring, HashMap<LineSegment, CoverageEdge> uniqueEdgeMap) {
private CoverageEdge createEdge(int coverageId, Coordinate[] ring, HashMap<LineSegment, CoverageEdge> uniqueEdgeMap) {
CoverageEdge edge;
LineSegment edgeKey = CoverageEdge.key(ring);
if (uniqueEdgeMap.containsKey(edgeKey)) {
edge = uniqueEdgeMap.get(edgeKey);
if (!coverageTolerances.isEmpty()){
edge.setTolerance((edge.getTolerance() < coverageTolerances.get(coverageId)) ? edge.getTolerance() : coverageTolerances.get(coverageId));
}
}
else {
edge = CoverageEdge.createEdge(ring);
double tolerance = coverageTolerances.isEmpty() ? -1 : coverageTolerances.get(coverageId);
edge = CoverageEdge.createEdge(ring, tolerance);
uniqueEdgeMap.put(edgeKey, edge);
edges.add(edge);
}
edge.incRingCount();
return edge;
}

private CoverageEdge createEdge(Coordinate[] ring, int start, int end, HashMap<LineSegment, CoverageEdge> uniqueEdgeMap) {
private CoverageEdge createEdge(int coverageId, Coordinate[] ring, int start, int end, HashMap<LineSegment, CoverageEdge> uniqueEdgeMap) {
CoverageEdge edge;
LineSegment edgeKey = (end == start) ? CoverageEdge.key(ring) : CoverageEdge.key(ring, start, end);
if (uniqueEdgeMap.containsKey(edgeKey)) {
edge = uniqueEdgeMap.get(edgeKey);
if (!coverageTolerances.isEmpty()){
edge.setTolerance((edge.getTolerance() < coverageTolerances.get(coverageId)) ? edge.getTolerance() : coverageTolerances.get(coverageId));
}
}
else {
edge = CoverageEdge.createEdge(ring, start, end);
double tolerance = coverageTolerances.isEmpty() ? -1 : coverageTolerances.get(coverageId);
edge = CoverageEdge.createEdge(ring, start, end, tolerance);
uniqueEdgeMap.put(edgeKey, edge);
edges.add(edge);
}
Expand Down Expand Up @@ -278,7 +296,7 @@ private Set<Coordinate> findBoundaryNodes(Set<LineSegment> boundarySegments) {

/**
* Recreates the polygon coverage from the current edge values.
*
*
* @return an array of polygonal geometries representing the coverage
*/
public Geometry[] buildCoverage() {
Expand Down
Loading

0 comments on commit e4578b9

Please sign in to comment.