ingo@3227: package de.intevation.flys.artifacts.geom; sascha@1797: sascha@1797: import java.awt.geom.Point2D; sascha@1797: sascha@1797: public final class VectorUtils sascha@1797: { sascha@1797: public static final double EPSILON = 1e-4; sascha@1797: sascha@1797: private VectorUtils() { sascha@1797: } sascha@1797: sascha@1799: public static final double X(Point2D p) { sascha@1797: return p.getX(); sascha@1797: } sascha@1797: sascha@1799: public static final double Y(Point2D p) { sascha@1797: return p.getY(); sascha@1797: } sascha@1797: sascha@1797: public static final Point2D sub(Point2D a, Point2D b) { sascha@1797: return new Point2D.Double(X(a)-X(b), Y(a)-Y(b)); sascha@1797: } sascha@1797: sascha@1797: public static final double dot(Point2D a, Point2D b) { sascha@1797: return X(a)*X(b) + Y(a)*Y(b); sascha@1797: } sascha@1797: sascha@1797: public static final Point2D add(Point2D a, Point2D b) { sascha@1797: return new Point2D.Double(X(a)+X(b), Y(a)+Y(b)); sascha@1797: } sascha@1797: sascha@1797: public static final Point2D negate(Point2D a) { sascha@1797: return new Point2D.Double(-X(a), -Y(a)); sascha@1797: } sascha@1797: sascha@1797: public static final Point2D ortho(Point2D a) { sascha@1797: return new Point2D.Double(-Y(a), X(a)); sascha@1797: } sascha@1797: sascha@1797: public static final Point2D scale(Point2D a, double s) { sascha@1797: return new Point2D.Double(s*X(a), s*Y(a)); sascha@1797: } sascha@1797: sascha@1797: public static final double lengthSq(Point2D a) { sascha@1797: double x = X(a); sascha@1797: double y = Y(a); sascha@1797: return x*x + y*y; sascha@1797: } sascha@1797: sascha@1797: public static final double length(Point2D a) { sascha@1797: return Math.sqrt(lengthSq(a)); sascha@1797: } sascha@1797: sascha@1797: public static final Point2D normalize(Point2D a) { sascha@1797: double length = length(a); sascha@1797: return length != 0d sascha@3076: ? scale(a, 1d/length) sascha@1797: : new Point2D.Double(X(a), Y(a)); sascha@1797: } sascha@1797: sascha@1797: public static final double L1(Point2D a, Point2D b) { sascha@1797: return Math.abs(X(a)-X(b)) + Math.abs(Y(a)-Y(b)); sascha@1797: } sascha@1797: sascha@1797: public static final boolean collinear(Point2D a, Point2D b, Point2D c) { sascha@1797: double x1 = X(a); sascha@1797: double y1 = Y(a); sascha@1797: double x2 = X(b); sascha@1797: double y2 = Y(b); sascha@1797: double x3 = X(c); sascha@1797: double y3 = Y(c); sascha@1797: sascha@1797: return Math.abs((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)) < EPSILON; sascha@1797: } sascha@1797: sascha@1797: public static boolean epsilonEquals(Point2D a, Point2D b) { sascha@3076: return Math.abs(X(a)-X(b)) < EPSILON sascha@1797: && Math.abs(Y(a)-Y(b)) < EPSILON; sascha@1797: } sascha@1797: sascha@1801: public static final Point2D intersection( sascha@1801: Point2D p1, Point2D p2, sascha@1801: Point2D p3, Point2D p4 sascha@1801: ) { sascha@1801: double x1 = X(p1); sascha@1801: double y1 = Y(p1); sascha@1801: double x2 = X(p2); sascha@1801: double y2 = Y(p2); sascha@1801: double x3 = X(p3); sascha@1801: double y3 = Y(p3); sascha@1801: double x4 = X(p4); sascha@1801: double y4 = Y(p4); sascha@1801: sascha@1801: // Compute a1, b1, c1, where line joining points 1 and 2 sascha@1801: // is "a1 x + b1 y + c1 = 0". sascha@1801: double a1 = y2 - y1; sascha@1801: double b1 = x1 - x2; sascha@1801: double c1 = x2*y1 - x1*y2; sascha@1801: sascha@1801: // Compute r3 and r4. sascha@1801: double r3 = a1*x3 + b1*y3 + c1; sascha@1801: double r4 = a1*x4 + b1*y4 + c1; sascha@1801: sascha@1801: if (r3 != 0d && r4 != 0d && r3*r4 >= 0) { sascha@1801: return null; sascha@1801: } sascha@1801: sascha@1801: // Compute a2, b2, c2 sascha@1801: double a2 = y4 - y3; sascha@1801: double b2 = x3 - x4; sascha@1801: double c2 = (x4 * y3) - (x3 * y4); sascha@1801: sascha@1801: // Compute r1 and r2 sascha@1801: double r1 = a2*x1 + b2*y1 + c2; sascha@1801: double r2 = a2*x2 + b2*y2 + c2; sascha@1801: sascha@1801: if (r1 != 0d && r2 != 0d && r1*r2 >= 0) { sascha@1801: return null; sascha@1801: } sascha@1801: sascha@1801: // Line segments intersect: compute intersection point. sascha@1801: double denom = a1*b2 - a2*b1; sascha@1801: sascha@1801: if (denom == 0d) { // collinear sascha@1801: return null; sascha@1801: } sascha@1801: sascha@1801: double offset = Math.abs(denom)/2d; sascha@1801: sascha@1801: // The denom/2 is to get rounding instead of truncating. It sascha@1801: // is added or subtracted to the numerator, depending upon the sascha@1801: // sign of the numerator. sascha@1801: double num = b1*c2 - b2*c1; sascha@1801: sascha@1801: double x = num < 0d sascha@1801: ? (num - offset)/denom sascha@1801: : (num + offset)/denom; sascha@1801: sascha@1801: num = a2*c1 - a1*c2; sascha@1801: sascha@1801: double y = num < 0d sascha@1801: ? (num - offset)/denom sascha@1801: : (num + offset)/denom; sascha@1801: sascha@1801: return new Point2D.Double(x, y); sascha@1801: } sascha@1801: sascha@1797: } sascha@3076: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :