Java-多边形和直线的交点

Java-多边形和直线的交点,java,line,polygon,intersection,Java,Line,Polygon,Intersection,是否有任何函数可以为我提供多边形和线2D的交点 我有一个多边形和一条线段,我知道它们相交,我希望交点的实际值不是布尔值。有java.awt.geom.Area.intersect(Area)使用构造函数Area(Shape)使用多边形并将线2D作为要相交的区域传递,将得到相交的区域。您需要记住,它可能在多个位置相交 我们把多边形的线段称为p,把实线线段称为L 我们找到每条线的坡度(坡度为m) 找到每条线的y截距 // y = mx+b where b is y-intercept bl = ly

是否有任何函数可以为我提供
多边形
线2D
的交点


我有一个多边形和一条线段,我知道它们相交,我希望交点的实际值不是布尔值。

java.awt.geom.Area.intersect(Area)
使用构造函数
Area(Shape)
使用多边形并将线2D作为要相交的区域传递,将得到相交的区域。

您需要记住,它可能在多个位置相交

我们把多边形的线段称为p,把实线线段称为L

我们找到每条线的坡度(坡度为m)

找到每条线的y截距

// y = mx+b where b is y-intercept
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]);

    }
}
结果:

3.4 3.4

给你。有趣的方法是getcrossions和getcrossion。前者分析所有多边形段并检查交点,后者进行实际计算。请记住,计算可以进行认真的优化,并且不检查是否除以0。这也仅适用于多边形。如果引入三次曲线和二次曲线的计算,则可以将其调整为适用于其他形状。假定使用Line2D.Double而不是Line2D.Float。集合用于避免重复点(可能发生在多边形角交点上)

请不要在没有广泛测试的情况下使用它,因为我刚刚快速地将它拼凑在一起,不确定它是否完全完好

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<Point2D> intersections = getIntersections(poly, line);
        for(Iterator<Point2D> it = intersections.iterator(); it.hasNext();) {
            final Point2D point = it.next();
            System.out.println("Intersection: " + point.toString());
        }

    }

    public static Set<Point2D> 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<Point2D> intersections = new HashSet<Point2D>(); //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);

    }

}
封装QuickPolyContest;
导入java.awt.Polygon;
导入java.awt.geom.Line2D;
导入java.awt.geom.PathIterator;
导入java.awt.geom.Point2D;
导入java.util.HashSet;
导入java.util.Iterator;
导入java.util.Set;
公共班机{
公共静态void main(字符串[]args)引发异常{
最终多边形多边形=新多边形(新int[]{1,2,2,1},新int[]{1,1,2,2},4);
最终线条2D.双线=新线条2D.双线(2.5,1.3,1.3,2.5);
最终设置交点=获取交点(多边形、直线);
for(Iterator it=crossions.Iterator();it.hasNext();){
final Point2D point=it.next();
System.out.println(“交点:+point.toString());
}
}
公共静态集GetCrossons(最终多边形多边形,最终线条2D.Double line)引发异常{
最终路径迭代器polyIt=poly.getPathIterator(null);//沿多边形路径获取迭代器
final double[]coords=new double[6];//迭代器需要长度为6的双数组
final double[]firstCoords=new double[2];//第一个点(闭合多边形路径所需)
final double[]lastCoords=new double[2];//以前访问过的点
final Set crossions=new HashSet();//保存找到的交叉点的列表
polyIt.currentSegment(firstCoords);//获取第一个坐标对
lastCoords[0]=firstCoords[0];//启动上一个坐标对
lastCoords[1]=firstCoords[1];
polyIt.next();
而(!polyIt.isDone()){
最终整数类型=polyIt.currentSegment(coords);
开关(类型){
案例PathIterator.SEG_LINETO:{
final Line2D.Double currentLine=新的Line2D.Double(lastCoords[0],lastCoords[1],coords[0],coords[1]);
if(当前线.相交线(线))
添加(获取交叉点(currentLine,line));
lastCoords[0]=coords[0];
lastCoords[1]=coords[1];
打破
}
案例PathIterator.SEG_关闭:{
final Line2D.Double currentLine=新的Line2D.Double(coords[0],coords[1],firstCoords[0],firstCoords[1]);
if(当前线.相交线(线))
添加(获取交叉点(currentLine,line));
打破
}
默认值:{
抛出新异常(“不支持的PathIterator段类型”);
}
}
polyIt.next();
}
返回交叉口;
}
公共静态点2D getIntersection(最终线条2D.Double line1,最终线条2D.Double line2){
最终双x1,y1,x2,y2,x3,y3,x4,y4;
x1=line1.x1;y1=line1.y1;x2=line1.x2;y2=line1.y2;
x3=线路2.x1;y3=线路2.y1;x4=线路2.x2;y4=线路2.y2;
最终双x=(
(x2-x1)*(x3*y4-x4*y3)-(x4-x3)*(x1*y2-x2*y1)
) /
(
(x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
);
最终双y=(
(y3-y4)*(x1*y2-x2*y1)-(y1-y2)*(x3*y4-x4*y3)
) /
(
(x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
);
返回新的点2d.Double(x,y);
}
}

我成功地使用了这种方法:

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)
}

如果不限制您使用多边形和Line2D对象,我建议您使用

  • 创建几何体(多边形)
  • 创建几何体
  • 使用该方法创建交点
简单代码示例:

// 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)

我应该指出,这里没有包括一些条件。当线条相同时会发生什么?当直线不相交(坡度相等)时会发生什么情况?如果相交发生在线段之外,会发生什么情况?如果其中一个是零斜率呢?这里有一些特殊情况需要介绍,留给读者作为练习。我应该补充一点,我知道它正好在一个地方相交,因为我知道一个点在多边形的外面,一个在多边形的里面。但我不知道它是多边形的哪一段
(5.0, 0.0, NaN)
(5.0, 10.0, NaN)