这个图是从知乎上保存下来的:
其实主要是利用了三角形的相似:
代码如下:
// 两点式直线公式:(x - x1) / (x2 - x1) = (y - y1) / (y2 - y1) // --> x(y2 - y1) + y(x1 - x2) + x1(y1 - y2) + y1(x2 - x1) = 0 // A = y2-y1, B = x1-x2, C = x1(y1 - y2) + y1(x2 - x1) // (x,y) = d2/(d1+d2) * (x3,y3) + d1/(d1+d2) * (x4,y4) // d2/(d1+d2) = |A*x4 + B*y4 + C|/(|A*x4 + B*y4 + C|+|A*x3 + B*y3 + C|) // d1/(d1+d2) = |A*x3 + B*y3 + C|/(|A*x4 + B*y4 + C|+|A*x3 + B*y3 + C|) public static Point detectIntersection(Point a, Point b, Point c, Point d) { // whether intersect ? boolean intersect = (PointPosition.isLeft(a, b, c) ^ PointPosition.isLeft(a, b, d)) && (PointPosition.isLeft(c, d, a) ^ PointPosition.isLeft(c, d, b)); if (!intersect) return null; double d2 = Math.abs((b.y - a.y) * d.x + (a.x - b.x) * d.y + a.x * (a.y - b.y) + a.y * (b.x - a.x)); double d1 = Math.abs((b.y - a.y) * c.x + (a.x - b.x) * c.y + a.x * (a.y - b.y) + a.y * (b.x - a.x)); double x = d2 / (d1 + d2) * c.x + d1 / (d1 + d2) * d.x; double y = d2 / (d1 + d2) * c.y + d1 / (d1 + d2) * d.y; return new Point(x, y); }
要注意一点的是:这里会检测是否相交了,因此这里要坐下左检测:
/** * -> * a:(x1, y1), point A:(x2, y2) */ private static boolean isLeft(double x1, double y1, double x2, double y2) { // a'=(-y1, x1) or (y1, -x1), return a' x A = (-y1, x1) x (x2, y2) return (-y1 * x2 + x1 * y2) > 0; } /** * -> * pq and point s */ public static boolean isLeft(Point p, Point q, Point s) { return isLeft(q.x - p.x, q.y - p.y, s.x - p.x, s.y - p.y); }