/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.geometry.iso.util.algorithm2D; import java.awt.Rectangle; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * @author roehrig * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates * * * @source $URL$ */ public class AlgoPoint2D { public static final double EPSILON = 0.000001; public static final double EPSILONSQ = 0.001; public static final Point2D point00 = new Point2D.Double(0.0, 0.0); public static Point2D copyPoint2D(Point2D p) { return new Point2D.Double(p.getX(),p.getY()); } /** * Compares coodinates of Direct Positions * @param Direct Position to compare with * @return TRUE, if coordinates accord, FALSE if they dont. */ public static boolean equals(Point2D p0, Point2D p1, double tol) { return p0.equals(p1) || p0.distanceSq(p1) < (tol * tol); } public static boolean equalsTol(Point2D p0, Point2D p1) { return AlgoPoint2D.equals(p0, p1, EPSILON); } public static void add(Point2D p0, Point2D p1) { p0.setLocation(p0.getX() + p1.getX(), p0.getY() + p1.getY()); } public static void add(Point2D p0, double factor) { p0.setLocation(p0.getX() + factor, p0.getY() + factor); } /** * Adds a DirectPosition to the position * @param DirectPosition to add * @return new Position */ public static Point2D createAdd(Point2D p0, Point2D p1) { return new Point2D.Double(p0.getX() + p1.getX(), p0.getY() + p1.getY()); } public static Point2D creatAdd(Point2D p0, double factor) { return new Point2D.Double(p0.getX() + factor, p0.getY() + factor); } /** * Subtracts a direct position from the position * @param DirectPosition to subtract * @return new Position */ public static Point2D subtract(Point2D p0, Point2D p1) { return new Point2D.Double(p0.getX() - p1.getX(), p0.getY() - p1.getY()); } public static Point2D scale(Point2D p0, double factor) { return new Point2D.Double(p0.getX() * factor, p0.getY() * factor); } /** * Returns the length (Distance between origin and position) * @return Length */ public static double length(Point2D p0) { return p0.distance(point00); } public static double lengthSq(Point2D p0) { return p0.distanceSq(point00); } /** * Builds the scalar product * @param DirectPosition to multiply with * @return Scalar product */ public static double scalar(Point2D p0, Point2D p1) { return p0.getX() * p1.getX() + p0.getY() + p1.getY(); } public static double cross(Point2D p0, Point2D p1) { // corresponds to the 2*area of two vectors return p0.getX() * p1.getY() - p0.getY() * p1.getX(); } public static Point2D normalize(Point2D p0) { double len = AlgoPoint2D.length(p0); return (len > 0.0) ? AlgoPoint2D.scale(p0, 1.0 / len) : new Point2D.Double(0.0, 0.0); } public static Point2D evaluate(Point2D p0, Point2D p1, double r) { return new Point2D.Double((1.0 - r) * p0.getX() + r * p1.getX(), (1.0 - r) * p0.getY() + r * p1.getY()); } public static Point2D evaluate(Point2D p0, Point2D p1, Point2D eval) { return new Point2D.Double((1.0 - eval.getX()) * p0.getX() + eval.getX() * p1.getX(), (1.0 - eval.getY()) * p0.getY() + eval.getY() * p1.getY()); } public static boolean intersectWithHorizontalLineFromRight2D(Point2D p, Point2D p0, Point2D p1) { // returns true when a horizontal line passing at ME: // 1) intersects the line with origin p0 and and p1 and // 2) when ME is on the right side of the line double x0 = p0.getX(); // line endpoint 2D coords double y0 = p0.getY(); // line endpoint 2D coords double x1 = p1.getX(); // line endpoint 2D coords double y1 = p1.getY(); // line endpoint 2D coords double xa = x0; // swap coordinates double ya = y0; // swap coordinates double xb = x1; // swap coordinates double yb = y1; // swap coordinates double max_x = Math.max(x0, x1); // maximum x coordinate double min_x = Math.min(x0, x1); // minimum x coordinate double max_y = Math.max(y0, y1); // maximum y coordinate double min_y = Math.min(y0, y1); // minimum y coordinate // the horizontal line does not intersect the line to the // left of location pt if: // [1] if line is horizontal if (y0 == y1) return false; // (2) if the y coordinate of node is outside the range // max_y and min_y (but not including min_y) if (((p.getY() < min_y) || (p.getY() >= max_y))) return false; // (3) if given line is vertical and y coordinate of node is // smaller than that of line if (((x0 == x1) && (p.getX() < x0))) return false; // (4) if inclined line is located to the right of given node // (first reduce the problem to a case where yb >ya, always) if ((x0 != x1)) { if (!(((x1 > x0) && (y1 > y0)) || ((x1 < x0) && (y1 > y0)))) { xa = x1; ya = y1; xb = x0; yb = y0; } if ((((p.getY() - ya) * (xb - xa)) > ((p.getX() - xa) * (yb - ya)))) { return false; } } // if we get here that is because the horizontal line passing // at the location this intersects the given line to the left of the pt return true; } public static double getAngle2D(Point2D p0, Point2D p1) { // * p1 // / // / // / // *------>* // (0,0) p0 double angle = Math.atan2(p1.getY(), p1.getX()) - Math.atan2(p0.getY(), p0.getX()); if (angle < 0.0) angle = angle + 2 * Math.PI; if (angle > (2 * Math.PI)) angle = angle - 2 * Math.PI; return angle; } public static double minAngle2D(Point2D p, Point2D p1, Point2D p2) { double ang0 = AlgoPoint2D.getAngle2D(AlgoPoint2D .subtract(p1, p), AlgoPoint2D.subtract(p2, p)); double ang1 = AlgoPoint2D.getAngle2D(AlgoPoint2D.subtract(p2, p1), AlgoPoint2D.subtract(p, p1)); return Math.min(Math.min(ang0, ang1), Math.min(ang0, Math.PI - ang0 - ang1)); } public static Point2D[] split(Point2D p0, Point2D p1, double maxLength) { // The first and last node are not inserted if (maxLength<=0.0 || maxLength==Double.NaN) return null; int n = (int) Math.ceil(p0.distance(p1) / maxLength); if (n==0) return null; double x1 = p0.getX(); double y1 = p0.getY(); double x2 = p1.getX(); double y2 = p1.getY(); double deltaX = (x2-x1) / n; double deltaY = (y2-y1) / n; Point2D result[] = new Point2D[n-1]; for (int i = 1; i < n; ++i) { result[i-1] = new Point2D.Double(x1 + deltaX * i, y1 + deltaY * i); } return result; } public static Point2D createCentroid(Point2D[] points) { if (points==null) return null; int n = points.length; if (n==0) return null; double x = points[0].getX(); double y = points[0].getY(); for (int i = 1; i<n;++i) { x += points[i].getX(); y += points[i].getY(); } return new Point2D.Double(x/n,y/n); } public static ArrayList<Point2D> split(List<Point2D> points, double maxLength) { int n = points.size(); ArrayList<Point2D> pointList = new ArrayList<Point2D>(n); for (int i = 1; i<n;++i) { Point2D p0 = points.get(i-1); Point2D p1 = points.get(i); pointList.add(p0); Point2D sp[] = split(p0, p1, maxLength); if (sp != null) { for (int j = 0; j < sp.length; ++j) { pointList.add(sp[j]); } } } pointList.add(points.get(n-1)); return pointList; } public static Boolean pointsOrientation(Collection points) { double result = 0.0; Iterator it = points.iterator(); if (!it.hasNext()) return null; Point2D p0 = (Point2D) it.next(); if (!it.hasNext()) return null; Point2D p1 = (Point2D) it.next(); Point2D p10 = AlgoPoint2D.subtract(p1, p0); double sum = 0.0; while (it.hasNext()) { Point2D p = (Point2D) it.next(); result += AlgoPoint2D.cross(p10,(AlgoPoint2D.subtract(p, p0))); } return new Boolean(result > 0.0); } /** * @param collection * @return */ public static Rectangle2D getEnvelope(Collection coll) { // Collection<Point2D> Iterator i = coll.iterator(); if (!i.hasNext()) return null; Point2D p = (Point2D)i.next(); Rectangle2D r = new Rectangle.Double(p.getX(),p.getY(),0.0,0.0); while (i.hasNext()) { r.add((Point2D)i.next()); } return r; } }