package jeql.std.function.geommatch;
import com.vividsolutions.jts.geom.Geometry;
public class GeomMatchFunction
{
/**
* Tests how well two geometries match based on the area of
* their symmetric difference relative to the geometry areas.
* The value computed is:
* <pre>
* 1 - area(symDiff(a, b)) / (area(a) + area(b)
* </pre>
* This value will lie between 0 and 1, inclusive.
* Larger values indicate better matches, with 1 indicating a perfect match.
* It is probably desirable to align the geometries
* based on their centroid first (using {@link #alignToCentroid} )
*
* @param a a Geometry
* @param b a Geometry
* @return a value between 0 and 1
*/
public static double symDiffArea(Geometry a, Geometry b)
{
if (a.isEmpty() || b.isEmpty()) {
return 0;
}
double symDiffArea = a.symDifference(b).getArea();
return 1.0 - (symDiffArea / (a.getArea() + b.getArea()));
}
public static double hausdorffDistance(Geometry a, Geometry b)
{
return new VertexHausdorffDistance(a, b).distance();
}
public static double centroidDistance(Geometry a, Geometry b)
{
return a.getCentroid().distance(b.getCentroid());
}
public static double compactness(Geometry a, Geometry b)
{
double score = 1 - Math.abs(compactness(a) - compactness(b));
return score;
}
/**
* Uses (4 x pi x Area) / (Perimeter^2) as a measure of compactness.
* The maximum value is 1 (attained by circles).
* The minimum value is 0 (attained by lines)
*/
private static double compactness(Geometry g)
{
double len = g.getLength();
return 4 * Math.PI * g.getArea() / (len * len);
}
/**
* Translates a geometry so its centroid is the same as the centroid
* of a target geometry.
*
* @param src
* @param target
*/
public static Geometry alignToCentroid(Geometry src, Geometry target)
{
CentroidAligner aligner = new CentroidAligner(target);
return aligner.align(src);
}
}