HausdorffDistanceStressTest.java
/*
* Copyright (c) 2026 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.distance;
import java.util.ArrayList;
import java.util.List;
import org.locationtech.jts.algorithm.distance.DiscreteHausdorffDistance;
import org.locationtech.jts.algorithm.distance.DirectedHausdorffDistance;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.util.SineStarFactory;
import org.locationtech.jts.util.Debug;
public class HausdorffDistanceStressTest {
static final int MAX_ITER = 10000;
static final boolean VERBOSE = false;
static GeometryFactory geomFact = new GeometryFactory();
public static void main(String[] args) {
HausdorffDistanceStressTest test = new HausdorffDistanceStressTest();
test.run();
}
private void run() {
Geometry b = createSineStar(1000, 300, 50);
Debug.println(b);
List<Geometry> grid = createCircleGrid(2000, 100);
int iter = 0;
for (Geometry g : grid) {
iter++;
Debug.println(iter + " ----------------");
Debug.println(g);
checkHausdorff(g, b);
checkFullyWithinDistance(g, b);
//if (iter > 10) break;
}
}
private void checkHausdorff(Geometry g, Geometry b) {
double distDHD = DiscreteHausdorffDistance.distance(g, b, 0.01);
double distHD = DirectedHausdorffDistance.hausdorffDistance(g, b);
//-- performance testing only
//double distDHD = distHD;
double err = Math.abs(distDHD - distHD) / (distDHD + distHD);
Debug.println(distDHD + " " + distHD + " err = " + err);
if (err > .01) {
System.out.println("<<<<<<<<<<< ERROR!");
}
}
private void checkFullyWithinDistance(Geometry g, Geometry b) {
double distDHD = DirectedHausdorffDistance.distance(g, b, 0.01);
boolean isWithin = DirectedHausdorffDistance.isFullyWithinDistance(g, b, 1.05 * distDHD);
boolean isBeyond = ! DirectedHausdorffDistance.isFullyWithinDistance(g, b, 0.95 * distDHD);
if (! (isWithin && isBeyond)) {
System.out.format("ioWithin = %b isBeyond = %b\n", isWithin, isBeyond);
System.out.println("<<<<<<<<<<< ERROR!");
//DirectedHausdorffDistance.isFullyWithinDistance(g, b, 0.75 * distDHD,tol);
}
}
private List<Geometry> createCircleGrid(double size, int nSide) {
List<Geometry> geoms = new ArrayList<Geometry>();
double inc = size / nSide;
for (int i = 0; i < nSide; i++) {
for (int j = 0; j < nSide; j++) {
Coordinate p = new Coordinate(i * inc, j * inc);
Point pt = geomFact.createPoint(p);
Geometry buf = pt.buffer(inc);
geoms.add(buf);
}
}
return geoms;
}
Geometry createSineStar(double loc, double size, int nPts)
{
SineStarFactory gsf = new SineStarFactory(geomFact);
gsf.setCentre(new Coordinate(loc, loc));
gsf.setSize(size);
gsf.setNumPoints(nPts);
Geometry g = gsf.createSineStar().getBoundary();
return g;
}
}