/*
* The JCS Conflation Suite (JCS) is a library of Java classes that
* can be used to build automated or semi-automated conflation solutions.
*
* Copyright (C) 2003 Vivid Solutions
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your opointion) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* For more information, contact:
*
* Vivid Solutions
* Suite #1A
* 2328 Government Street
* Victoria BC V8T 5G5
* Canada
*
* (250)385-6040
* www.vividsolutions.com
*/
package com.revolsys.geometry.algorithm;
import com.revolsys.geometry.algorithm.distance.PointPairDistance;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.geometry.model.Point;
import com.revolsys.geometry.model.segment.LineSegment;
import com.revolsys.geometry.model.vertex.Vertex;
/**
* Implements algorithm for computing a distance metric which can be thought of
* as the "Vertex Hausdorff Distance". This is the Hausdorff distance restricted
* to vertices for one of the geometries. Also computes two points of the
* Geometries which are separated by the computed distance.
* <p>
* <b>NOTE: This algorithm does NOT compute the full Hausdorff distance
* correctly, but an approximation that is correct for a large subset of useful
* cases. One important part of this subset is Linestrings that are roughly
* parallel to each other, and roughly equal in length - just what is needed for
* line matching. </b>
*/
public class VertexHausdorffDistance {
public static double distance(final Geometry geometry1, final Geometry geometry2) {
final VertexHausdorffDistance vhd = new VertexHausdorffDistance(geometry1, geometry2);
return vhd.distance();
}
private final PointPairDistance pointDistance = new PointPairDistance();
public VertexHausdorffDistance(final Geometry geometry1, final Geometry geometry2) {
computeMaxPointDistance(geometry1, geometry2, this.pointDistance);
computeMaxPointDistance(geometry2, geometry1, this.pointDistance);
}
public VertexHausdorffDistance(final LineSegment line1, final LineSegment line2) {
computeMaxPointDistance(line1, line2, this.pointDistance);
computeMaxPointDistance(line2, line1, this.pointDistance);
}
private void computeMaxPointDistance(final Geometry pointGeometry, final Geometry geometry,
final PointPairDistance pointDistance) {
pointDistance.setMaximum(pointDistance);
final PointPairDistance maxPointDist = new PointPairDistance();
final PointPairDistance minPointDist = new PointPairDistance();
for (final Vertex vertex : pointGeometry.vertices()) {
minPointDist.initialize();
final double x = vertex.getX();
final double y = vertex.getY();
minPointDist.setMinimum(geometry, x, y);
maxPointDist.setMaximum(minPointDist);
}
pointDistance.setMaximum(maxPointDist);
}
/**
* Computes the maximum oriented distance between two line segments, as well
* as the point pair separated by that distance.
*
* @param line1 the line segment containing the furthest point
* @param line2 the line segment containing the closest point
* @param pointDistance the point pair and distance to be updated
*/
private void computeMaxPointDistance(final LineSegment line1, final LineSegment line2,
final PointPairDistance pointDistance) {
for (int i = 0; i < 2; i++) {
final double line2x = line2.getX(i);
final double line2y = line2.getY(i);
final Point closestPoint = line1.closestPoint(line2x, line2y);
final double closestX = closestPoint.getX();
final double closestY = closestPoint.getY();
pointDistance.setMaximum(closestX, closestY, line2x, line2y);
}
}
public double distance() {
return this.pointDistance.getDistance();
}
public Point[] getCoordinates() {
return this.pointDistance.getPoints();
}
}