Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-正确的直线相交检查_Java_Line_Point - Fatal编程技术网

Java-正确的直线相交检查

Java-正确的直线相交检查,java,line,point,Java,Line,Point,我需要确定两条直线段是否相交,但使用line2D.linesIntersect方法存在问题。即使这些行只共享一个端点,该方法也会返回一个真正的结果,如下所示: Point2D.Double temp1 = new Point2D.Double(0, 0); Point2D.Double temp2 = new Point2D.Double(0, 1); Point2D.Double temp3 = new Point2D.Double(1, 0); if(Line2D.linesInterse

我需要确定两条直线段是否相交,但使用line2D.linesIntersect方法存在问题。即使这些行只共享一个端点,该方法也会返回一个真正的结果,如下所示:

Point2D.Double temp1 = new Point2D.Double(0, 0);
Point2D.Double temp2 = new Point2D.Double(0, 1);
Point2D.Double temp3 = new Point2D.Double(1, 0);

if(Line2D.linesIntersect(temp1.x, temp1.y, temp2.x, temp2.y, temp1.x, temp1.y, temp3.x, temp3.y){
    System.out.println("Lines share an endpoint.");
}
else{
    System.out.println("Lines don't intersect.");
}

在这种情况下,我将始终收到“lines share a endpoint”消息。当然,在某些直线共享端点的情况下,它们可能会无限多次相交((0,0)到(0,1)被(0,0)到(0,2)相交),这显然会返回真实结果。但是,在其他情况下,如果只共享端点,而不发生其他交集,程序将无法正常工作。有什么方法可以避免这个问题吗?

这是我用我的基本数学知识可以得出的答案。希望对你有帮助。给定4个点,它会告诉您两条线(从这四个点开始)是否相交、是否共享一个端点或两者都不共享

        //starting point of line 1
        Point2D.Double temp1 = new Point2D.Double(0 , 1);
        //ending point of line 1
        Point2D.Double temp2 = new Point2D.Double(0, -1);
        //starting point of line 2
        Point2D.Double temp3 = new Point2D.Double(-1, 0);
        //ending point of line 2
        Point2D.Double temp4 = new Point2D.Double(1, 0);

        //determine if the lines intersect
        boolean intersects = Line2D.linesIntersect(temp1.x, temp1.y, temp2.x, temp2.y, temp3.x, temp3.y, temp4.x, temp4.y);

        //determines if the lines share an endpoint
        boolean shareAnyPoint = shareAnyPoint(temp1, temp2, temp3, temp4);

        if (intersects && shareAnyPoint) {
            System.out.println("Lines share an endpoint.");
        } else if (intersects && !shareAnyPoint) {
            System.out.println("Lines intersect.");
        } else {
            System.out.println("Lines neither intersect nor share a share an endpoint.");
        }
下面是shareAnyPoint(StartPointA、EndPointA、StartPointB、EndPointB)函数,用于检查任一行的起点/终点是否位于另一行

public static boolean shareAnyPoint(Point2D.Double A, Point2D.Double B, Point2D.Double C, Point2D.Double D) {
    if (isPointOnTheLine(A, B, C)) return true;
    else if (isPointOnTheLine(A, B, D)) return true;
    else if (isPointOnTheLine(C, D, A)) return true;
    else if (isPointOnTheLine(C, D, B)) return true;
    else return false;
}
这里是isPointOnTheLine(StartPoint,EndPoint,MyPoint)函数,它确定一个点是否位于直线上(由另外两个点组成)


试试看,让我知道结果

如果不局限于Point2D和Line2D对象,则可以使用(Java拓扑套件)

  • 将线创建为线字符串对象
  • 使用该方法
简单代码示例:

LineString lineA = new GeometryFactory().createLineString(new Coordinate[]{new Coordinate(0, 0), new Coordinate(0, 10)});
LineString lineB = new GeometryFactory().createLineString(new Coordinate[]{new Coordinate(-5,5), new Coordinate(5,5)});
boolean intersect = lineA.intersects(lineB);

我在网络上找到了一个解决方案,并对其进行了调整和手动测试。 它是自包含的,只需导入java.awt.geom.Point2D即可

/**
 * Test if the first point lies in the bounding box denote by the other two
 * points.
 */
public static boolean isBetween(Point2D pToTest, Point2D p1, Point2D p2) {
    return isBetween(pToTest.getX(), pToTest.getY(), p1.getX(), p1.getY(), p2.getX(), p2.getY());
}

/**
 * Called {@link #isBetween(Point2D, Point2D, Point2D)} passing those points
 * coordinates.
 */
public static boolean isBetween(double pxToTest, double pyToTest, double px1, double py1, double px2, double py2) {
    double w, h;
    // taking inspiration from Rectangle's class
    w = px1 - px2;
    if (w < 0)
        w = -w;
    h = py1 - py2;
    if (h < 0)
        h = -h;
    // use p1 as the left-top corner of the rectangle
    // (the left-top corner is considered as the origin (0;0))
    if (px1 > px2)
        px1 = px2;//
    if (py1 > py2)
        py1 = py2;//
    if (pxToTest < px1 || pyToTest < py1) {
        return false;
    }
    w += px1;
    h += py1;
    // overflow || intersect
    return ((w < px1 || w > pxToTest) && (h < py1 || h > pyToTest));
}

public static double slope(double xa, double ya, double xb, double yb) {
    if (xb == xa)
        return Double.POSITIVE_INFINITY;
    return (yb == ya) ? 0.0 : ((yb - ya) / (xb - xa));
}

/**
 * Called by {@link #areLinesIntersecting(Point2D, Point2D, Point2D, Point2D)}
 * by providing each of those point's coordinates.
 */
public static Point2D areLinesIntersecting(double pxStart1, double pyStart1, double pxEnd1, double pyEnd1,
        double pxStart2, double pyStart2, double pxEnd2, double pyEnd2) {
    double slope_ab, slope_cd, numerator, denominator, q_ab, q_cd, x, y;
    Point2D p;
    slope_ab = slope(pxStart1, pyStart1, pxEnd1, pyEnd1);
    slope_cd = slope(pxStart2, pyStart2, pxEnd2, pyEnd2);
    q_ab = (pyStart1 - slope_ab * pxStart1);
    q_cd = (pyStart2 - slope_cd * pxStart2);
    if ((slope_ab == slope_cd) // parallel?
            && (
            // overlapping?
            ((slope_ab == Double.POSITIVE_INFINITY || slope_ab == Double.NaN) && pxStart1 == pxStart2) //
                    || //
                        // overlapping?
                    (slope_ab == 0.0 && pyStart1 == pyStart2) //
                    || //
                        // if different costant parts of lines, then parallel BUT not overlapping
                    (q_ab == q_cd)//
            )) {
        if (isBetween(pxStart2, pyStart2, pxStart1, pyStart1, pxEnd1, pyEnd1))
            return new Point2D.Double(pxStart2, pyStart2);
        if (isBetween(pxEnd2, pyEnd2, pxStart1, pyStart1, pxEnd1, pyEnd1))
            return new Point2D.Double(pxEnd2, pyEnd2);
        if (isBetween(pxStart1, pyStart1, pxStart2, pyStart2, pxEnd2, pyEnd2))
            return new Point2D.Double(pxStart1, pyStart1);
        if (isBetween(pxEnd1, pyEnd1, pxStart2, pyStart2, pxEnd2, pyEnd2))
            return new Point2D.Double(pxEnd1, pyEnd1);
    }
    if (slope_ab == Double.POSITIVE_INFINITY) {
        // ab vertical line: all a&b's x-es are equals
        x = pxStart1;
        y = (q_cd + (slope_cd * x));
        // it's a cross
        if ((pyStart1 <= pyEnd1) ? (y < pyStart1 || y > pyEnd1)
                // point are reversed
                : (y > pyStart1 || y < pyEnd1))
            return null;
        if ((pxStart2 < pxEnd2) ? (pxStart2 <= x && x <= pxEnd2)//
                : (pxEnd2 <= x && x <= pxStart2))
            return new Point2D.Double(x, y);
        else
            return null;
    }
    if (slope_cd == Double.POSITIVE_INFINITY) {
        // cd vertical line: all c&d's x-es are equals
        x = pxStart2;
        y = (q_ab + (slope_ab * x));
        // it's a cross
        if ((pyStart2 <= pyEnd2) ? (y < pyStart2 || y > pyEnd2)
                // point are reversed
                : (y > pyStart2 || y < pyEnd2))
            return null;
        // if the y lies inside the line a-b, then intersection
        if ((pxStart1 < pxEnd1) ? (pxStart1 <= x && x <= pxEnd1)//
                : (pxEnd1 <= x && x <= pxStart1))
            return new Point2D.Double(x, y);
        else
            return null;

    }
    // slopes cannot be infinity
    if (slope_ab == 0.0) {
        y = pyStart1;
        // slope_cd cannot be Infinity (second group of checks) and zero (first ones)
        x = (y - q_cd) / slope_cd;

        if ((pxStart1 <= pxEnd1) ? (x < pxStart1 || x > pxEnd1)
                // point are reversed
                : (x > pxStart1 || x < pxEnd1))
            return null;
        if ((pxStart2 <= pxEnd2) ? (x < pxStart2 || x > pxEnd2)
                // point are reversed
                : (x > pxStart2 || x < pxEnd2))
            return null;
        if ((pyStart2 < pyEnd2) ? (pyStart2 <= y && y <= pyEnd2)//
                : (pyEnd2 <= y && y <= pyStart2))
            return new Point2D.Double(x, y);
        else
            return null;
    }
    if (slope_cd == 0.0) {
        y = pyStart2;
        // slope_ab cannot be Infinity (second group of checks) and zero (first ones)
        x = (y - q_ab) / slope_ab;

        if ((pxStart2 <= pxEnd2) ? (x < pxStart2 || x > pxEnd2)
                // point are reversed
                : (x > pxStart2 || x < pxEnd2))
            return null;

        if ((pxStart1 <= pxEnd1) ? (x < pxStart1 || x > pxEnd1)
                // point are reversed
                : (x > pxStart1 || x < pxEnd1))
            return null;
        if ((pyStart1 < pyEnd1) ? (pyStart1 <= y && y <= pyEnd1)//
                : (pyEnd1 <= y && y <= pyStart1))
            return new Point2D.Double(x, y);
        else
            return null;
    }
    denominator = slope_cd - slope_ab;
    numerator = q_ab - q_cd;
    x = (numerator / denominator);
    y = (q_ab + (slope_ab * x));
    p = new Point2D.Double(x, y);
    if (isBetween(p.getX(), p.getY(), pxStart1, pyStart1, pxEnd1, pyEnd1)
            && isBetween(p.getX(), p.getY(), pxStart2, pyStart2, pxEnd2, pyEnd2))
        return p;
    y = (q_cd + (slope_cd * x));
    p = new Point2D.Double(x, y);
    if ((isBetween(p.getX(), p.getY(), pxStart1, pyStart1, pxEnd1, pyEnd1)
            && isBetween(p.getX(), p.getY(), pxStart2, pyStart2, pxEnd2, pyEnd2)))
        return p;

    return null;
}
/**
*测试第一个点是否位于由其他两个点表示的边界框中
*要点。
*/
公共静态布尔值介于之间(点2D测试、点2D p1、点2D p2){
返回isBetween(pToTest.getX(),pToTest.getY(),p1.getX(),p1.getY(),p2.getX(),p2.getY());
}
/**
*通过这些点调用{@link#isBetween(Point2D,Point2D,Point2D)}
*坐标。
*/
公共静态布尔值isBetween(双pxToTest、双pyToTest、双px1、双py1、双px2、双py2){
双w,h;
//从矩形的课程中获得灵感
w=px1-px2;
if(w<0)
w=-w;
h=py1-py2;
if(h<0)
h=-h;
//使用p1作为矩形的左上角
//(左上角视为原点(0;0))
如果(px1>px2)
px1=px2//
如果(py1>py2)
py1=py2//
if(pxToTestpxToTest)和&(hpyToTest));
}
公共静态双斜率(双xa、双ya、双xb、双yb){
如果(xb==xa)
返回双正无穷大;
收益率(yb==ya)?0.0:((yb-ya)/(xb-xa));
}
/**
*由{@link#areLinesIntersecting(Point2D,Point2D,Point2D,Point2D)调用
*通过提供每个点的坐标。
*/
公共静态点2D是线性插入检测(双pxStart1、双pyStart1、双pxEnd1、双pyEnd1、,
双pxStart2,双pyStart2,双pxEnd2,双pyEnd2){
双斜率ab,斜率cd,分子,分母,q_ab,q_cd,x,y;
点2dp;
斜率=斜率(pxStart1,pyStart1,pxEnd1,pyEnd1);
斜率=斜率(pxStart2,pyStart2,pxEnd2,pyEnd2);
q_ab=(pyStart1-斜率_ab*pxStart1);
q_cd=(pyStart2-斜率_cd*pxStart2);
如果((斜率=slope\u ab==slope\u cd)//平行?
&& (
//重叠?
(斜率| ab==Double.POSITIVE |斜率| ab==Double.NaN)和&pxStart1==pxStart2)//
|| //
//重叠?
(斜率=0.0&&pyStart1==pyStart2)//
|| //
//如果线的不同共有部分,则平行但不重叠
(q_ab==q_cd)//
)) {
if(isBetween(pxStart2、pyStart2、pxStart1、pyStart1、pxEnd1、pyEnd1))
返回新的点2d.Double(pxStart2,pyStart2);
if(isBetween(pxEnd2,pyEnd2,pxStart1,pyStart1,pxEnd1,pyEnd1))
返回新的点2d.Double(pxEnd2,pyEnd2);
if(isBetween(pxStart1、pyStart1、pxStart2、pyStart2、pxEnd2、pyEnd2))
返回新的点2d.Double(pxStart1,pyStart1);
if(isBetween(pxEnd1,pyEnd1,pxStart2,pyStart2,pxEnd2,pyEnd2))
返回新的点2d.Double(pxEnd1,pyEnd1);
}
if(斜率=双正无穷大){
//ab垂直线:所有a&b的x-E相等
x=pxStart1;
y=(q_cd+(斜率_cd*x));
//这是一个十字架
if((pyStart1 pyEnd1)
//这一点是相反的
:(y>pyStart1 | | y如果((pxStart2/**
 * Test if the first point lies in the bounding box denote by the other two
 * points.
 */
public static boolean isBetween(Point2D pToTest, Point2D p1, Point2D p2) {
    return isBetween(pToTest.getX(), pToTest.getY(), p1.getX(), p1.getY(), p2.getX(), p2.getY());
}

/**
 * Called {@link #isBetween(Point2D, Point2D, Point2D)} passing those points
 * coordinates.
 */
public static boolean isBetween(double pxToTest, double pyToTest, double px1, double py1, double px2, double py2) {
    double w, h;
    // taking inspiration from Rectangle's class
    w = px1 - px2;
    if (w < 0)
        w = -w;
    h = py1 - py2;
    if (h < 0)
        h = -h;
    // use p1 as the left-top corner of the rectangle
    // (the left-top corner is considered as the origin (0;0))
    if (px1 > px2)
        px1 = px2;//
    if (py1 > py2)
        py1 = py2;//
    if (pxToTest < px1 || pyToTest < py1) {
        return false;
    }
    w += px1;
    h += py1;
    // overflow || intersect
    return ((w < px1 || w > pxToTest) && (h < py1 || h > pyToTest));
}

public static double slope(double xa, double ya, double xb, double yb) {
    if (xb == xa)
        return Double.POSITIVE_INFINITY;
    return (yb == ya) ? 0.0 : ((yb - ya) / (xb - xa));
}

/**
 * Called by {@link #areLinesIntersecting(Point2D, Point2D, Point2D, Point2D)}
 * by providing each of those point's coordinates.
 */
public static Point2D areLinesIntersecting(double pxStart1, double pyStart1, double pxEnd1, double pyEnd1,
        double pxStart2, double pyStart2, double pxEnd2, double pyEnd2) {
    double slope_ab, slope_cd, numerator, denominator, q_ab, q_cd, x, y;
    Point2D p;
    slope_ab = slope(pxStart1, pyStart1, pxEnd1, pyEnd1);
    slope_cd = slope(pxStart2, pyStart2, pxEnd2, pyEnd2);
    q_ab = (pyStart1 - slope_ab * pxStart1);
    q_cd = (pyStart2 - slope_cd * pxStart2);
    if ((slope_ab == slope_cd) // parallel?
            && (
            // overlapping?
            ((slope_ab == Double.POSITIVE_INFINITY || slope_ab == Double.NaN) && pxStart1 == pxStart2) //
                    || //
                        // overlapping?
                    (slope_ab == 0.0 && pyStart1 == pyStart2) //
                    || //
                        // if different costant parts of lines, then parallel BUT not overlapping
                    (q_ab == q_cd)//
            )) {
        if (isBetween(pxStart2, pyStart2, pxStart1, pyStart1, pxEnd1, pyEnd1))
            return new Point2D.Double(pxStart2, pyStart2);
        if (isBetween(pxEnd2, pyEnd2, pxStart1, pyStart1, pxEnd1, pyEnd1))
            return new Point2D.Double(pxEnd2, pyEnd2);
        if (isBetween(pxStart1, pyStart1, pxStart2, pyStart2, pxEnd2, pyEnd2))
            return new Point2D.Double(pxStart1, pyStart1);
        if (isBetween(pxEnd1, pyEnd1, pxStart2, pyStart2, pxEnd2, pyEnd2))
            return new Point2D.Double(pxEnd1, pyEnd1);
    }
    if (slope_ab == Double.POSITIVE_INFINITY) {
        // ab vertical line: all a&b's x-es are equals
        x = pxStart1;
        y = (q_cd + (slope_cd * x));
        // it's a cross
        if ((pyStart1 <= pyEnd1) ? (y < pyStart1 || y > pyEnd1)
                // point are reversed
                : (y > pyStart1 || y < pyEnd1))
            return null;
        if ((pxStart2 < pxEnd2) ? (pxStart2 <= x && x <= pxEnd2)//
                : (pxEnd2 <= x && x <= pxStart2))
            return new Point2D.Double(x, y);
        else
            return null;
    }
    if (slope_cd == Double.POSITIVE_INFINITY) {
        // cd vertical line: all c&d's x-es are equals
        x = pxStart2;
        y = (q_ab + (slope_ab * x));
        // it's a cross
        if ((pyStart2 <= pyEnd2) ? (y < pyStart2 || y > pyEnd2)
                // point are reversed
                : (y > pyStart2 || y < pyEnd2))
            return null;
        // if the y lies inside the line a-b, then intersection
        if ((pxStart1 < pxEnd1) ? (pxStart1 <= x && x <= pxEnd1)//
                : (pxEnd1 <= x && x <= pxStart1))
            return new Point2D.Double(x, y);
        else
            return null;

    }
    // slopes cannot be infinity
    if (slope_ab == 0.0) {
        y = pyStart1;
        // slope_cd cannot be Infinity (second group of checks) and zero (first ones)
        x = (y - q_cd) / slope_cd;

        if ((pxStart1 <= pxEnd1) ? (x < pxStart1 || x > pxEnd1)
                // point are reversed
                : (x > pxStart1 || x < pxEnd1))
            return null;
        if ((pxStart2 <= pxEnd2) ? (x < pxStart2 || x > pxEnd2)
                // point are reversed
                : (x > pxStart2 || x < pxEnd2))
            return null;
        if ((pyStart2 < pyEnd2) ? (pyStart2 <= y && y <= pyEnd2)//
                : (pyEnd2 <= y && y <= pyStart2))
            return new Point2D.Double(x, y);
        else
            return null;
    }
    if (slope_cd == 0.0) {
        y = pyStart2;
        // slope_ab cannot be Infinity (second group of checks) and zero (first ones)
        x = (y - q_ab) / slope_ab;

        if ((pxStart2 <= pxEnd2) ? (x < pxStart2 || x > pxEnd2)
                // point are reversed
                : (x > pxStart2 || x < pxEnd2))
            return null;

        if ((pxStart1 <= pxEnd1) ? (x < pxStart1 || x > pxEnd1)
                // point are reversed
                : (x > pxStart1 || x < pxEnd1))
            return null;
        if ((pyStart1 < pyEnd1) ? (pyStart1 <= y && y <= pyEnd1)//
                : (pyEnd1 <= y && y <= pyStart1))
            return new Point2D.Double(x, y);
        else
            return null;
    }
    denominator = slope_cd - slope_ab;
    numerator = q_ab - q_cd;
    x = (numerator / denominator);
    y = (q_ab + (slope_ab * x));
    p = new Point2D.Double(x, y);
    if (isBetween(p.getX(), p.getY(), pxStart1, pyStart1, pxEnd1, pyEnd1)
            && isBetween(p.getX(), p.getY(), pxStart2, pyStart2, pxEnd2, pyEnd2))
        return p;
    y = (q_cd + (slope_cd * x));
    p = new Point2D.Double(x, y);
    if ((isBetween(p.getX(), p.getY(), pxStart1, pyStart1, pxEnd1, pyEnd1)
            && isBetween(p.getX(), p.getY(), pxStart2, pyStart2, pxEnd2, pyEnd2)))
        return p;

    return null;
}