Repository navigation
Add index for holes-in-shell validity check #1251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -176,6 +176,20 @@ public void testPolygonHoleWithRepeatedTouchEndPoint() { | |
| public void testPolygonHoleWithRepeatedHolePointTouch() { | ||
| checkValid( "POLYGON ((50 90, 10 10, 90 10, 50 90), (50 90, 50 90, 60 40, 60 40, 40 40, 50 90))"); | ||
| } | ||
|
|
||
| public void testPolygonHolesInConcaveShell() { | ||
| checkValid( "POLYGON ((10 10, 10 90, 40 90, 40 30, 60 30, 60 90, 90 90, 90 10, 10 10), (15 70, 25 70, 25 80, 15 80, 15 70), (70 50, 80 50, 80 60, 70 60, 70 50), (45 15, 55 15, 55 25, 45 25, 45 15), (40 50, 30 45, 30 55, 40 50))"); | ||
| } | ||
|
|
||
| public void testPolygonHoleOutsideShellInConcavity() { | ||
| checkInvalid(TopologyValidationError.HOLE_OUTSIDE_SHELL, | ||
| "POLYGON ((10 10, 10 90, 40 90, 40 30, 60 30, 60 90, 90 90, 90 10, 10 10), (45 60, 55 60, 55 80, 45 80, 45 60))"); | ||
| } | ||
|
|
||
| public void testPolygonHoleOutsideShellInConcavityTouch() { | ||
| checkInvalid(TopologyValidationError.HOLE_OUTSIDE_SHELL, | ||
| "POLYGON ((10 10, 10 90, 40 90, 40 30, 60 30, 60 90, 90 90, 90 10, 10 10), (15 70, 25 70, 25 80, 15 80, 15 70), (70 50, 80 50, 80 60, 70 60, 70 50), (40 50, 50 45, 50 55, 40 50))"); | ||
| } | ||
|
|
||
| //============================================= | ||
|
|
||
|
|
@@ -188,16 +202,29 @@ private void checkValid(boolean isExpectedValid, String wkt) { | |
| Geometry geom = read(wkt); | ||
| boolean isValid = geom.isValid(); | ||
| assertEquals( isExpectedValid, isValid ); | ||
| TopologyValidationError indexedCheck = validateIndexedShell(wkt); | ||
| if (isExpectedValid) { | ||
| assertNull( indexedCheck ); | ||
| } else { | ||
| assertNotNull( indexedCheck ); | ||
| } | ||
| } | ||
|
|
||
| private void checkInvalid(String wkt) { | ||
| checkValid(false, wkt); | ||
| } | ||
|
|
||
| private TopologyValidationError validateIndexedShell(String wkt) { | ||
| IsValidOp validOp = new IsValidOp(read(wkt)); | ||
| validOp.setMinHolesIndexedShell(0); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this to keep the tests verifying index behavior smaller, if you want I could set the min holes to 0 on all tests in this file so they all exercise the new code path, or make the indexed ones create 20 extra holes to force it without the setMinHoles method?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also changed this to validate all test cases with and without an index. |
||
| return validOp.getValidationError(); | ||
| } | ||
|
|
||
| private void checkInvalid(int exepctedErrType, String wkt) { | ||
| Geometry geom = read(wkt); | ||
| IsValidOp validOp = new IsValidOp(geom); | ||
| TopologyValidationError err = validOp.getValidationError(); | ||
| assertEquals( exepctedErrType, err.getErrorType() ); | ||
| assertEquals( exepctedErrType, validateIndexedShell(wkt).getErrorType() ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,78 @@ | ||||||
| /* | ||||||
| * Copyright (c) 2020 Martin Davis. | ||||||
| * | ||||||
| * 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 test.jts.perf.operation.valid; | ||||||
|
|
||||||
| import org.locationtech.jts.geom.Coordinate; | ||||||
| import org.locationtech.jts.geom.Geometry; | ||||||
| import org.locationtech.jts.geom.LinearRing; | ||||||
| import org.locationtech.jts.geom.Polygon; | ||||||
|
|
||||||
| import test.jts.geom.TestShapeFactory; | ||||||
| import test.jts.perf.PerformanceTestCase; | ||||||
| import test.jts.perf.PerformanceTestRunner; | ||||||
|
|
||||||
| /** | ||||||
| * Tests performance of IsValidOp.checkHolesInShell | ||||||
| * for polygons with a large shell and many holes. | ||||||
| */ | ||||||
| public class IsValidHolesInShellPerfTest extends PerformanceTestCase { | ||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On my m1 macbook:
|
||||||
|
|
||||||
| static final int N_ITER = 10; | ||||||
|
|
||||||
| static final int N_PTS_SMALL_SHELL = 1000; | ||||||
| static final int N_PTS_LARGE_SHELL = 100_000; | ||||||
|
|
||||||
| public static void main(String args[]) { | ||||||
| PerformanceTestRunner.run(IsValidHolesInShellPerfTest.class); | ||||||
| } | ||||||
|
|
||||||
| public IsValidHolesInShellPerfTest(String name) | ||||||
| { | ||||||
| super(name); | ||||||
| // number of holes; must be squares | ||||||
| setRunSize(new int[] { 1, 4, 16, 64, 256, 1024, 4096 }); | ||||||
| setRunIterations(N_ITER); | ||||||
| } | ||||||
|
|
||||||
| Geometry smallShellGeom; | ||||||
| Geometry largeShellGeom; | ||||||
|
|
||||||
| @Override | ||||||
| public void startRun(int nHoles) | ||||||
| { | ||||||
| System.out.println("\nRunning with # holes " + nHoles ); | ||||||
| smallShellGeom = createCircleWithHoles(N_PTS_SMALL_SHELL, nHoles); | ||||||
| largeShellGeom = createCircleWithHoles(N_PTS_LARGE_SHELL, nHoles); | ||||||
| } | ||||||
|
|
||||||
| private Geometry createCircleWithHoles(int nPtsShell, int nHoles) { | ||||||
| Coordinate origin = new Coordinate(0, 0); | ||||||
| Polygon circle = TestShapeFactory.createCircle(origin, 100, nPtsShell); | ||||||
| // holes are placed in the square inscribed in the circle | ||||||
| Polygon square = (Polygon) TestShapeFactory.createSquareWithCircleHoles(origin, 70, nHoles, 8); | ||||||
| LinearRing[] holes = new LinearRing[square.getNumInteriorRing()]; | ||||||
| for (int i = 0; i < holes.length; i++) { | ||||||
| holes[i] = square.getInteriorRingN(i); | ||||||
| } | ||||||
| return circle.getFactory().createPolygon(circle.getExteriorRing(), holes); | ||||||
| } | ||||||
|
|
||||||
| public void runValidateSmallShell() | ||||||
| { | ||||||
| smallShellGeom.isValid(); | ||||||
| } | ||||||
|
|
||||||
| public void runValidateLargeShell() | ||||||
| { | ||||||
| largeShellGeom.isValid(); | ||||||
| } | ||||||
| } | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These test add some extra coverage around the indexed version: