Skip to content

Commit 8c8f41b

Browse files
committed
Add checks for invalid and zero input
1 parent e97617b commit 8c8f41b

2 files changed

Lines changed: 114 additions & 6 deletions

File tree

modules/core/src/main/java/org/locationtech/jts/algorithm/distance/DirectedHausdorffDistance.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,14 @@ private static Coordinate[] pair(Coordinate p0, Coordinate p1) {
255255
*/
256256
private static final double FULLY_WITHIN_TOLERANCE_FACTOR = 10 * AUTO_TOLERANCE_FACTOR;
257257

258-
258+
/**
259+
* Computes an automatic distance tolerance for a query geometry.
260+
* A tolerance of zero may be returned (e.g. for a zero-length line);
261+
* this is supported by the distance algorithm.
262+
*
263+
* @param geom the query geometry
264+
* @return the distance tolerance
265+
*/
259266
private static double computeTolerance(Geometry geom) {
260267
return geom.getEnvelopeInternal().getDiameter() / AUTO_TOLERANCE_FACTOR;
261268
}
@@ -363,6 +370,14 @@ public Coordinate[] farthestPoints(Geometry geom, double tolerance) {
363370
}
364371

365372
private Coordinate[] computeDistancePoints(Geometry geom, double tolerance, double maxDistanceLimit) {
373+
/**
374+
* Negative tolerances are not allowed.
375+
* Zero tolerance is allowed, to support zero-size input.
376+
*/
377+
if (tolerance < 0.0 ) {
378+
throw new IllegalArgumentException("Tolerance must be non-negative");
379+
}
380+
366381
if (geom.isEmpty() || target.isEmpty())
367382
return null;
368383

@@ -412,7 +427,8 @@ private Coordinate[] computeForPoints(Geometry geom, double maxDistanceLimit) {
412427
maxDist = dist;
413428
maxDistPtsAB = pair(pA, pB);
414429
}
415-
if (isBeyondLimit(maxDist, maxDistanceLimit)) {
430+
if (isValidLimit(maxDistanceLimit)
431+
&& isBeyondLimit(maxDist, maxDistanceLimit)) {
416432
break;
417433
}
418434
}
@@ -460,10 +476,12 @@ private Coordinate[] computeForEdges(Geometry geom, double tolerance, double max
460476
* - if segment distance bound is less than distance limit, no other segment can be farther
461477
* - if a point of segment is farther than limit, isFulyWithin must be false
462478
*/
463-
if (isWithinLimit(segMaxBound.getMaxDistanceBound(), maxDistanceLimit)
479+
if (isValidLimit(maxDistanceLimit)) {
480+
if (isWithinLimit(segMaxBound.getMaxDistanceBound(), maxDistanceLimit)
464481
|| isBeyondLimit(segMaxBound.getMaxDistance(), maxDistanceLimit)
465482
) {
466-
break;
483+
break;
484+
}
467485
}
468486

469487
/**
@@ -483,9 +501,10 @@ private Coordinate[] computeForEdges(Geometry geom, double tolerance, double max
483501
/**
484502
* If segment is longer than tolerance
485503
* it might provide a better max distance point,
486-
* so bisect and keep searching
504+
* so bisect and keep searching.
487505
*/
488-
if ((segMaxBound.getLength() > tolerance)) {
506+
if (tolerance > 0
507+
&& segMaxBound.getLength() > tolerance) {
489508
DHDSegment[] bisects = segMaxBound.bisect(targetDistance);
490509
addNonInterior(bisects[0], segQueue);
491510
addNonInterior(bisects[1], segQueue);
@@ -514,6 +533,10 @@ private boolean isSameOrCollinear(DHDSegment seg) {
514533
return f0.isSameSegment(f1);
515534
}
516535

536+
private static boolean isValidLimit(double limit) {
537+
return limit >= 0.0;
538+
}
539+
517540
private static boolean isBeyondLimit(double maxDist, double maxDistanceLimit) {
518541
return maxDistanceLimit >= 0 && maxDist > maxDistanceLimit;
519542
}
@@ -561,6 +584,9 @@ private boolean isInterior(DHDSegment segment) {
561584
* or null if it is known to not occur at an interior point
562585
*/
563586
private Coordinate[] computeForAreaInterior(Geometry geom, double tolerance) {
587+
if (tolerance <= 0.0)
588+
return null;
589+
564590
//TODO: extract polygonal geoms from A
565591
Geometry polygonal = geom;
566592

modules/core/src/test/java/org/locationtech/jts/algorithm/distance/DirectedHausdorffDistanceTest.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public static void main(String args[]) {
2626

2727
public DirectedHausdorffDistanceTest(String name) { super(name); }
2828

29+
//-- empty inputs
30+
2931
public void testEmptyPoint()
3032
{
3133
checkDistanceEmpty("POINT EMPTY", "POINT (1 1)");
@@ -42,6 +44,76 @@ public void testEmptyPolygon()
4244
}
4345

4446
//--------------------------------------
47+
//-- extreme and invalid inputs
48+
49+
public void testZeroTolerancePoint()
50+
{
51+
checkDistance("POINT (5 5)", "LINESTRING (5 1, 9 5)",
52+
0,
53+
"LINESTRING (5 5, 7 3)");
54+
}
55+
56+
public void testZeroToleranceLine()
57+
{
58+
checkDistance("LINESTRING (1 5, 5 5)", "LINESTRING (5 1, 9 5)",
59+
0,
60+
"LINESTRING (1 5, 5 1)");
61+
}
62+
63+
public void testZeroToleranceZeroLengthLineQuery()
64+
{
65+
checkDistance("LINESTRING (5 5, 5 5)", "LINESTRING (5 1, 9 5)",
66+
0,
67+
"LINESTRING (5 5, 7 3)");
68+
}
69+
70+
public void testZeroLengthLineQuery()
71+
{
72+
checkDistance("LINESTRING (5 5, 5 5)", "LINESTRING (5 1, 9 5)",
73+
"LINESTRING (5 5, 7 3)");
74+
}
75+
76+
public void testZeroLengthPolygonQuery()
77+
{
78+
checkDistance("POLYGON ((5 5, 5 5, 5 5, 5 5))", "LINESTRING (5 1, 9 5)",
79+
"LINESTRING (5 5, 7 3)");
80+
}
81+
82+
public void testZeroLengthLineTarget()
83+
{
84+
checkDistance("POINT (5 5)", "LINESTRING (5 1, 5 1)",
85+
"LINESTRING (5 5, 5 1)");
86+
}
87+
88+
public void testNegativeTolerancePoint()
89+
{
90+
try {
91+
checkDistance("POINT (5 5)", "LINESTRING (5 1, 9 5)",
92+
-1,
93+
"LINESTRING (5 5, 7 3)");
94+
fail();
95+
}
96+
catch (IllegalArgumentException expected) {
97+
98+
}
99+
}
100+
101+
public void testNegativeToleranceLine()
102+
{
103+
try {
104+
checkDistance("LINESTRING (1 5, 5 5)", "LINESTRING (5 1, 9 5)",
105+
-1,
106+
"LINESTRING (1 5, 5 1)");
107+
fail();
108+
}
109+
catch (IllegalArgumentException expected) {
110+
111+
}
112+
}
113+
114+
//--------------------------------------
115+
116+
45117
public void testPointPoint()
46118
{
47119
checkHausdorff("POINT (0 0)", "POINT (1 1)",
@@ -302,6 +374,16 @@ private void checkDistance(String wkt1, String wkt2, String wktExpected) {
302374
checkEqualExact(expected, result, TOLERANCE);
303375
}
304376

377+
private void checkDistance(String wkt1, String wkt2, double tolerance, String wktExpected) {
378+
Geometry g1 = read(wkt1);
379+
Geometry g2 = read(wkt2);
380+
381+
Coordinate[] pts = DirectedHausdorffDistance.distancePoints(g1, g2, tolerance);
382+
Geometry result = g1.getFactory().createLineString(pts);
383+
Geometry expected = read(wktExpected);
384+
checkEqualExact(expected, result, TOLERANCE);
385+
}
386+
305387
private void checkDistanceStartPtLen(String wkt1, String wkt2,
306388
String wktExpected, double resultTolerance) {
307389
Geometry g1 = read(wkt1);

0 commit comments

Comments
 (0)