Skip to content
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

Fix OverlayNG Area Check heuristic for difference #1005

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,8 @@ public static boolean isResultAreaConsistent(Geometry geom0, Geometry geom1, int
if (geom0 == null || geom1 == null)
return true;

if (result.getDimension() < 2) return true;

double areaResult = result.getArea();
double areaA = geom0.getArea();
double areaB = geom1.getArea();
Expand All @@ -403,8 +405,7 @@ public static boolean isResultAreaConsistent(Geometry geom0, Geometry geom1, int
&& isLess(areaResult, areaB, AREA_HEURISTIC_TOLERANCE);
break;
case OverlayNG.DIFFERENCE:
isConsistent = isLess(areaResult, areaA, AREA_HEURISTIC_TOLERANCE)
&& isGreater(areaResult, areaA - areaB, AREA_HEURISTIC_TOLERANCE);
isConsistent = isDifferenceAreaConsistent(areaA, areaB, areaResult, AREA_HEURISTIC_TOLERANCE);
break;
case OverlayNG.SYMDIFFERENCE:
isConsistent = isLess(areaResult, areaA + areaB, AREA_HEURISTIC_TOLERANCE);
Expand All @@ -417,6 +418,23 @@ && isLess(areaB, areaResult, AREA_HEURISTIC_TOLERANCE)
}
return isConsistent;
}

/**
* Tests if the area of a difference is greater than the minimum possible difference area.
* This is a heuristic which will only detect gross overlay errors.
* @param areaA the area of A
* @param areaB the area of B
* @param areaResult the result area
* @param tolFrac the area tolerance fraction
*
* @return true if the difference area is consistent.
*/
private static boolean isDifferenceAreaConsistent(double areaA, double areaB, double areaResult, double tolFrac) {
if (! isLess(areaResult, areaA, tolFrac))
return false;
double areaDiffMin = areaA - areaB - tolFrac * areaA;
return areaResult > areaDiffMin;
}

private static boolean isLess(double v1, double v2, double tol) {
return v1 <= v2 * (1 + tol);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/
package org.locationtech.jts.operation.overlayng;

import static org.locationtech.jts.operation.overlayng.OverlayNG.DIFFERENCE;
import static org.locationtech.jts.operation.overlayng.OverlayNG.INTERSECTION;
import static org.locationtech.jts.operation.overlayng.OverlayNG.UNION;

Expand Down Expand Up @@ -70,11 +71,27 @@ public void testTrianglesBSegmentsDisplacedUnion() {
checkEqual(expected, union(a, b, 0.1));
}

/**
* Failing due to OverlayUtil#isResultAreaConsistent
* See https://github.com/locationtech/jts/issues/951
*/
public void testRotatedVerticesDifference() {
Geometry a = read("POLYGON ((0.37676311 2.57570853, 7.28652472 0.00028375, 7.60034931 0.81686059, 0.50229292 3.4551325, 0.37676311 2.57570853))");
Geometry b = read("POLYGON ((0.50229292 3.4551325, 7.60034931 0.81686059, 7.28652472 0.00028375, 0.37676311 2.57570853, 0.50229292 3.4551325))");
Geometry expected = read("POLYGON EMPTY");
checkEqual(expected, difference(a, b, 0.00001));
}

public static Geometry union(Geometry a, Geometry b, double tolerance) {
Noder noder = getNoder(tolerance);
return OverlayNG.overlay(a, b, UNION, null, noder );
}

public static Geometry difference(Geometry a, Geometry b, double tolerance) {
Noder noder = getNoder(tolerance);
return OverlayNG.overlay(a, b, DIFFERENCE, null, noder );
}

private static Noder getNoder(double tolerance) {
SnappingNoder snapNoder = new SnappingNoder(tolerance);
return new ValidatingNoder(snapNoder);
Expand Down