Java-多边形和直线的交点

有没有任何函数可以给我一个PolygonLine2D的交点?

我有一个Polygon和一个我知道相交的线段我希望交点的实际值不是布尔答案。

这个给你。 有趣的方法是getIntersections和getIntersection。 前者解析所有多边形段并检查交叉点,后者执行实际计算。 请记住,计算可以严格优化,不会检查除以0.这也适用于多边形。 如果引入立方和二次曲线的计算,它可以适用于其他形状。 假设使用Line2D.Double而不是Line2D.Float。 Set用于避免重复点(可能出现在多边形角交叉点上)。

请不要在没有经过大量测试的情况下使用它,因为我刚刚快速将它们整合在一起并且不确定它是否完全合理。

 package quickpolygontest; import java.awt.Polygon; import java.awt.geom.Line2D; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Main { public static void main(String[] args) throws Exception { final Polygon poly = new Polygon(new int[]{1,2,2,1}, new int[]{1,1,2,2}, 4); final Line2D.Double line = new Line2D.Double(2.5, 1.3, 1.3, 2.5); final Set intersections = getIntersections(poly, line); for(Iterator it = intersections.iterator(); it.hasNext();) { final Point2D point = it.next(); System.out.println("Intersection: " + point.toString()); } } public static Set getIntersections(final Polygon poly, final Line2D.Double line) throws Exception { final PathIterator polyIt = poly.getPathIterator(null); //Getting an iterator along the polygon path final double[] coords = new double[6]; //Double array with length 6 needed by iterator final double[] firstCoords = new double[2]; //First point (needed for closing polygon path) final double[] lastCoords = new double[2]; //Previously visited point final Set intersections = new HashSet(); //List to hold found intersections polyIt.currentSegment(firstCoords); //Getting the first coordinate pair lastCoords[0] = firstCoords[0]; //Priming the previous coordinate pair lastCoords[1] = firstCoords[1]; polyIt.next(); while(!polyIt.isDone()) { final int type = polyIt.currentSegment(coords); switch(type) { case PathIterator.SEG_LINETO : { final Line2D.Double currentLine = new Line2D.Double(lastCoords[0], lastCoords[1], coords[0], coords[1]); if(currentLine.intersectsLine(line)) intersections.add(getIntersection(currentLine, line)); lastCoords[0] = coords[0]; lastCoords[1] = coords[1]; break; } case PathIterator.SEG_CLOSE : { final Line2D.Double currentLine = new Line2D.Double(coords[0], coords[1], firstCoords[0], firstCoords[1]); if(currentLine.intersectsLine(line)) intersections.add(getIntersection(currentLine, line)); break; } default : { throw new Exception("Unsupported PathIterator segment type."); } } polyIt.next(); } return intersections; } public static Point2D getIntersection(final Line2D.Double line1, final Line2D.Double line2) { final double x1,y1, x2,y2, x3,y3, x4,y4; x1 = line1.x1; y1 = line1.y1; x2 = line1.x2; y2 = line1.y2; x3 = line2.x1; y3 = line2.y1; x4 = line2.x2; y4 = line2.y2; final double x = ( (x2 - x1)*(x3*y4 - x4*y3) - (x4 - x3)*(x1*y2 - x2*y1) ) / ( (x1 - x2)*(y3 - y4) - (y1 - y2)*(x3 - x4) ); final double y = ( (y3 - y4)*(x1*y2 - x2*y1) - (y1 - y2)*(x3*y4 - x4*y3) ) / ( (x1 - x2)*(y3 - y4) - (y1 - y2)*(x3 - x4) ); return new Point2D.Double(x, y); } } 

java.awt.geom.Area.intersect(Area)使用带有Polygon的构造函数Area(Shape) ,并将Line2D作为Area传递给Line2D ,它将为您提供相交的Area。

你需要记住它可能在多个地方交叉。

让我们调用多边形P的线段和实线段L.

我们找到每条线的斜率(斜率是m)

 ml = (ly1-ly2) / (lx1-lx2); mp = (ply-pl2) / (px1-px2); 

找到每条线的y截距// y = mx + b其中b是y-截距bl = ly1 – (ml * lx1); bp = py1 – (pl * px1);

您可以使用以下方法求解x值:

 x = (bp - bl) / (ml - mp) 

然后将X插入其中一个方程式中以获得Y.

 y = ml * x + bl 

这是算法的实现版本

 class pointtest { static float[] intersect(float lx1, float ly1, float lx2, float ly2, float px1, float py1, float px2, float py2) { // calc slope float ml = (ly1-ly2) / (lx1-lx2); float mp = (py1-py2) / (px1-px2); // calc intercept float bl = ly1 - (ml*lx1); float bp = py1 - (mp*px1); float x = (bp - bl) / (ml - mp); float y = ml * x + bl; return new float[]{x,y}; } public static void main(String[] args) { float[] coords = intersect(1,1,5,5,1,4,5,3); System.out.println(coords[0] + " " + coords[1]); } } 

和结果:

 C:\Documents and Settings\glow\My Documents>java pointtest 3.4 3.4 C:\Documents and Settings\glow\My Documents> 

取得了巨大的成功,我使用了这种方法:

 Area a = new Area(shape1); Area b = new Area(shape2); b.intersect(a); if (!b.isEmpty()) { //Shapes have non-empty intersection, so do you actions. //In case of need, actual intersection is in Area b. (its destructive operation) } 

如果您不限制使用PolygonLine2D对象,我建议使用JTS 。

  • 创建LinearRing几何(您的多边形)。
  • 创建LineString几何体。
  • 使用交集方法创建交叉点。

简单的代码示例:

 // create ring: P1(0,0) - P2(0,10) - P3(10,10) - P4(0,10) LinearRing lr = new GeometryFactory().createLinearRing(new Coordinate[]{new Coordinate(0,0), new Coordinate(0,10), new Coordinate(10,10), new Coordinate(10,0), new Coordinate(0,0)}); // create line: P5(5, -1) - P6(5, 11) -> crossing the ring vertically in the middle LineString ls = new GeometryFactory().createLineString(new Coordinate[]{new Coordinate(5,-1), new Coordinate(5,11)}); // calculate intersection points Geometry intersectionPoints = lr.intersection(ls); // simple output of points for(Coordinate c : intersectionPoints.getCoordinates()){ System.out.println(c.toString()); } 

结果是:

 (5.0, 0.0, NaN) (5.0, 10.0, NaN)