package br.com.etyllica.core.linear; import br.com.etyllica.util.math.EtyllicaMath; public class Line2D { private Point2D p1; private Point2D p2; public Line2D(Point2D p1) { super(); this.p1 = p1; } public Line2D(Point2D p1, Point2D p2) { super(); this.p1 = p1; this.p2 = p2; } public Point2D intersection(Line2D line) { return intersection(p1, p2, line.p1, line.p2); } public static Point2D intersection(Point2D p1, Point2D p2, Point2D p3, Point2D p4) { double x1 = p1.getX(); double y1 = p1.getY(); double x2 = p2.getX(); double y2 = p2.getY(); double x3 = p3.getX(); double y3 = p3.getY(); double x4 = p4.getX(); double y4 = p4.getY(); double pxN = (x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4); double pyN = (x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4); double denominator = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4); double px = pxN/denominator; double py = pyN/denominator; return new Point2D(px, py); } public static Point2D[] interpolate(Point2D p1, Point2D p2, int points) { if(points<2) { Point2D[] array = new Point2D[2]; array[0] = Point2D.clone(p1); array[1] = Point2D.clone(p2); return array; } Point2D[] array = new Point2D[points]; array[0] = Point2D.clone(p1); int sections = points-1; array[sections] = Point2D.clone(p2); for(int i=1; i<sections; i++) { double px = p1.getX()+((p2.getX()-p1.getX())/sections)*i; double py = p1.getY()+((p2.getY()-p1.getY())/sections)*i; array[i] = new Point2D(px, py); } return array; } public double distance(Point2D q) { return distance(p1, p2, q); } /** * Found at: https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line * @param p1 * @param p2 * @param q * @return */ public static double distance(Point2D p1, Point2D p2, Point2D q) { double x1 = p1.getX(); double y1 = p1.getY(); double x2 = p2.getX(); double y2 = p2.getY(); double num = (y2 - y1) * q.getX() - (x2 - x1) * q.getY() + (x2 * y1) - (y2 * x1); num = EtyllicaMath.mod(num); double distance = num / Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)); return distance; } public Point2D nearestPoint(Point2D q) { return nearestPoint(p1, p2, q); } /** * Answered at: http://stackoverflow.com/questions/1459368/snap-point-to-a-line-java */ public static Point2D nearestPoint(Point2D p1, Point2D p2, Point2D q) { boolean clampToSegment = true; Point2D out = new Point2D(); double apx = q.getX() - p1.getX(); double apy = q.getY() - p1.getY(); double abx = p2.getX() - p1.getX(); double aby = p2.getY() - p1.getY(); double ab2 = abx * abx + aby * aby; double ap_ab = apx * abx + apy * aby; double t = ap_ab / ab2; if (clampToSegment) { if (t < 0) { t = 0; } else if (t > 1) { t = 1; } } out.setLocation(p1.getX() + abx * t, p1.getY() + aby * t); return out; } public Point2D getP1() { return p1; } public void setP1(Point2D p1) { this.p1 = p1; } public Point2D getP2() { return p2; } public void setP2(Point2D p2) { this.p2 = p2; } public double length() { return p1.distance(p2); } }