Skip to content

Commit

Permalink
Add new CoverageEdgeExtractor class to extract unique edges from a po…
Browse files Browse the repository at this point in the history
…lygonal coverage

Signed-off-by: N_Strahl <[email protected]>
  • Loading branch information
nstrahl committed Sep 29, 2024
1 parent 380bdd2 commit f7d95f3
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.locationtech.jts.coverage.CoverageSimplifier;
import org.locationtech.jts.coverage.CoverageUnion;
import org.locationtech.jts.coverage.CoverageValidator;
import org.locationtech.jts.coverage.CoverageEdgeExtractor;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.util.PolygonExtracter;
import org.locationtech.jtstest.geomfunction.Metadata;
Expand Down Expand Up @@ -53,19 +54,25 @@ public static Geometry findGaps(Geometry geom,
return CoverageGapFinder.findGaps(toGeometryArray(geom),gapWidth);
}

@Metadata(description="Extract edges from a coverage")
public static Geometry extractEdges(Geometry geom) {
Geometry[] edges = CoverageEdgeExtractor.extract(toGeometryArray(geom));
return FunctionsUtil.buildGeometryCollection(edges, geom.getFactory().createLineString());
}

@Metadata(description="Fast Union of a coverage")
public static Geometry union(Geometry coverage) {
Geometry[] cov = toGeometryArray(coverage);
return CoverageUnion.union(cov);
}

@Metadata(description="Simplify a coverage")
public static Geometry simplify(Geometry coverage, double tolerance) {
Geometry[] cov = toGeometryArray(coverage);
Geometry[] result = CoverageSimplifier.simplify(cov, tolerance);
return coverage.getFactory().createGeometryCollection(result);
}

@Metadata(description="Simplify a coverage with a smoothness weight")
public static Geometry simplifySharp(Geometry coverage,
@Metadata(title="Distance tol")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2024 Nick Bowsher.
*
* 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.coverage;

import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.coverage.CoverageRingEdges;
import org.locationtech.jts.geom.LineString;

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

/**
* Extracts the set of unique coverage edges from a polygonal coverage.
* The coverage edges are returned as an array of linear geometries.
* The input coverage should be valid according to {@link CoverageValidator}.
*
* @author Nick Bowsher
*/

public class CoverageEdgeExtractor {
/*
* Extracts the set of unique coverage edges from a polygonal coverage.
*
* @param coverage an array of polygons forming a coverage
* @return an array of linear geometries representing coverage edges
*/
public static Geometry[] extract(Geometry[] coverage) {
CoverageEdgeExtractor e = new CoverageEdgeExtractor(coverage);
return e.extract();
}

/*
* Creates a new coverage edge extractor
*
* @param coverage an array of polygons forming a coverage
*/
public CoverageEdgeExtractor(Geometry[] coverage) {
this.coverage = coverage;
}

/*
* Extracts the set of unique coverage edges from a polygonal coverage.
* The result is an array of the same size as the input coverage.
*
* @return an array of linear geometries representing coverage edges
*/
public Geometry[] extract() {
CoverageRingEdges covRings = new CoverageRingEdges(coverage);
GeometryFactory f = new GeometryFactory();
List<LineString> lines = new ArrayList<LineString>();
for (CoverageEdge edge : covRings.getEdges()) {
lines.add(edge.toLineString(f));
}
return GeometryFactory.toLineStringArray(lines);
}

private Geometry[] coverage;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2024 Nick Bowsher.
*
* 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.coverage;

import junit.textui.TestRunner;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.MultiLineString;
import test.jts.GeometryTestCase;

public class CoverageEdgeExtractorTest extends GeometryTestCase {
public static void main(String args[]) {
TestRunner.run(CoverageEdgeExtractorTest.class);
}

public CoverageEdgeExtractorTest(String name) {
super(name);
}

public void testTwoAdjacent() {
checkEdges("GEOMETRYCOLLECTION (POLYGON ((1 1, 1 6, 6 5, 9 6, 9 1, 1 1)), POLYGON ((1 9, 6 9, 6 5, 1 6, 1 9)))",
"MULTILINESTRING ((1 6, 1 1, 9 1, 9 6, 6 5), (1 6, 1 9, 6 9, 6 5), (1 6, 6 5))");
}

public void testTwoAdjacentWithFilledHole() {
checkEdges("GEOMETRYCOLLECTION (POLYGON ((1 1, 1 6, 6 5, 9 6, 9 1, 1 1), (2 4, 4 4, 4 2, 2 2, 2 4)), POLYGON ((1 9, 6 9, 6 5, 1 6, 1 9)), POLYGON ((4 2, 2 2, 2 4, 4 4, 4 2)))",
"MULTILINESTRING ((1 6, 1 1, 9 1, 9 6, 6 5), (1 6, 1 9, 6 9, 6 5), (1 6, 6 5), (2 4, 2 2, 4 2, 4 4, 2 4))");
}

public void testHolesAndFillWithDifferentEndpoints() {
checkEdges("GEOMETRYCOLLECTION (POLYGON ((0 10, 10 10, 10 0, 0 0, 0 10), (1 9, 4 8, 9 9, 9 1, 1 1, 1 9)), POLYGON ((9 9, 1 1, 1 9, 4 8, 9 9)), POLYGON ((1 1, 9 9, 9 1, 1 1)))",
"MULTILINESTRING ((0 10, 0 0, 10 0, 10 10, 0 10), (1 1, 1 9, 4 8, 9 9), (1 1, 9 1, 9 9), (1 1, 9 9))");
}

public void testMultiPolygons() {
checkEdges("GEOMETRYCOLLECTION (MULTIPOLYGON (((5 9, 2.5 7.5, 1 5, 5 5, 5 9)), ((5 5, 9 5, 7.5 2.5, 5 1, 5 5))), MULTIPOLYGON (((5 9, 6.5 6.5, 9 5, 5 5, 5 9)), ((1 5, 5 5, 5 1, 3.5 3.5, 1 5))))",
"MULTILINESTRING ((1 5, 2.5 7.5, 5 9), (1 5, 3.5 3.5, 5 1), (1 5, 5 5), (5 1, 5 5), (5 1, 7.5 2.5, 9 5), (5 5, 5 9), (5 5, 9 5), (5 9, 6.5 6.5, 9 5))"
);
}

private void checkEdges(String wkt, String wktExpected) {
Geometry geom = read(wkt);
Geometry[] coverage = toArray(geom);
Geometry[] edges = CoverageEdgeExtractor.extract(coverage);
MultiLineString edgeLines = toArray(edges, geom.getFactory());
Geometry expected = read(wktExpected);
checkEqual(expected, edgeLines);
}

private MultiLineString toArray(Geometry[] edges, GeometryFactory geomFactory) {
LineString[] lines = new LineString[edges.length];
for (int i = 0; i < edges.length; i++) {
lines[i] = geomFactory.createLineString(edges[i].getCoordinates());
}
return geomFactory.createMultiLineString(lines);
}

private static Geometry[] toArray(Geometry geom) {
Geometry[] geoms = new Geometry[geom.getNumGeometries()];
for (int i = 0; i < geom.getNumGeometries(); i++) {
geoms[i] = geom.getGeometryN(i);
}
return geoms;
}
}

0 comments on commit f7d95f3

Please sign in to comment.