Java-多边形和线的交点

发布于 2024-10-19 22:00:51 字数 111 浏览 4 评论 0原文

是否有任何函数可以提供 PolygonLine2D 的交点?

我有一个多边形和一个我知道相交的线段,我想要交点的实际值而不是布尔答案。

Is there any function that will give me the intersection point of a Polygon and Line2D ?

I have a Polygon and a line segment that I know intersect I want the actual value of the intersection point not a boolean answer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

野侃 2024-10-26 22:00:51

给你。有趣的方法是 getIntersections 和 getIntersection。前者解析所有多边形线段并检查交点,后者进行实际计算。请记住,可以认真优化计算,并且不检查除以 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);

    }

}

Here you are. The interesting methods are getIntersections and getIntersection. The former parses over all polygon segments and checks for intersections, the latter does the actual calculation. Do keep in mind that the calculation can be seriously optimized and doesn't check for division by 0. This will also work only for polygons. It could be adapted to work with other shapes if you introduce calculations for cubic and quadratic curves. It is assumed that Line2D.Double is used instead of Line2D.Float. A Set is used to avoid duplicate points (might occur on polygon corner intersections).

Please don't use this without extensive testing, since I've just hacked it together quickly and am not sure it's completely sound.

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

    }

}
对你而言 2024-10-26 22:00:51

java.awt.geom.Area.intersect(Area) 使用构造函数 Area(Shape) 与您的 Polygon 并将您的 Line2D 传递为要相交的区域将为您提供相交的区域。

There is java.awt.geom.Area.intersect(Area) using the constructor Area(Shape) with your Polygon and passing your Line2D as an Area to intersect will give you the Area which is intersected.

帅哥哥的热头脑 2024-10-26 22:00:51

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

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

With great success, i used this approach:

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)
}
画▽骨i 2024-10-26 22:00:51

您需要记住它可能在多个地方相交。

我们将多边形的线段称为 P,将实线段称为 L。

我们求出每条线的斜率(斜率为 m)

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

求出每条线的 y 截距

// y = mx+b where b is y-intercept
bl = ly1 - (ml*lx1);
bp = py1 - (pl*px1);

您可以通过以下方式求解 x 值:

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

然后将 X 代入 1得到 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

You need to bear in mind that it might intersect at multiple places.

Let's call the line segment of the polygon P and the real line segment L.

We find the slope of each line (slope is m)

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

Find the y intercept of each line

// y = mx+b where b is y-intercept
bl = ly1 - (ml*lx1);
bp = py1 - (pl*px1);

You can solve for the x value with:

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

Then plug that X into one of the equations to get the Y

y = ml * x + bl

Here's an implemented version of the algorithm

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]);

    }
}

and results:

3.4 3.4
疾风者 2024-10-26 22:00:51

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

简单的代码示例:

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

If you are not restricted to use the Polygon and Line2D Objects I would recommend to use JTS.

Simple code example:

// 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());
}

Result is:

(5.0, 0.0, NaN)
(5.0, 10.0, NaN)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文