/* * 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 option) 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.vividsolutions.jcs.conflate.polygonmatch; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateFilter; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jump.geom.CoordUtil; import com.vividsolutions.jump.util.CoordinateArrays; import java.util.Iterator; import java.util.List; /** * Functions useful to FeatureMatchers in general. */ public class MatcherUtil { /** * Moves g so that the outline centre-of-mass is at (0,0). * @param g the Geometry to modify */ public static void alignByOutlineCentreOfMass(Geometry g) { align(g, outlineCentreOfMass(g)); } /** * Moves g so that c is at (0,0). * @param g the Geometry to modify * @param c the point to move to the origin */ public static void align(Geometry g, Coordinate c) { final Coordinate move = CoordUtil.subtract(new Coordinate(0,0), c); g.apply(new CoordinateFilter() { @Override public void filter(Coordinate coordinate) { coordinate.x += move.x; coordinate.y += move.y; } }); } /** * Returns the centre-of-mass of g's line segments * @param g the Geometry to analyze * @return the weighted average of the midpoints of g's line segments, * weighted by segment length */ public static Coordinate outlineCentreOfMass(Geometry g) { Coordinate weightedSum = new Coordinate(); double totalLength = 0; List coordArrays = CoordinateArrays.toCoordinateArrays(g, false); for (Iterator i = coordArrays.iterator(); i.hasNext(); ) { Coordinate[] coords = (Coordinate[]) i.next(); for (int j = 1; j < coords.length; j++) { double length = coords[j-1].distance(coords[j]); totalLength += length; weightedSum = CoordUtil.add(weightedSum, CoordUtil.multiply(length, CoordUtil.average(coords[j-1], coords[j]))); } } return CoordUtil.divide(weightedSum, totalLength); } /** * Returns a FeatureMatcher score based on the symmetric difference * @param targetArea area of the target shape * @param candidateArea area of the candidate shape * @param symDiffArea area of the symmetric difference between the two shapes * @return a linear function of the symmetric difference: 1 if the shapes perfectly * overlap; 0 if the shapes do not overlap at all */ public static double toScoreFromSymDiffArea( double targetArea, double candidateArea, double symDiffArea) { return 1d - (symDiffArea / (targetArea + candidateArea)); } }