【问题标题】:How to find where two line segments intersect programmatically如何以编程方式查找两条线段相交的位置
【发布时间】:2021-12-24 08:46:56
【问题描述】:

假设下面有如下正坐标区域:

在这个区域中,我们有一个代表计算机窗口的矩形。如您所见,还有覆盖该区域的线段。我正在尝试解决一个问题,当线段位于窗口之外时,我将对其进行剪辑。

例如,下面窗口的左上坐标为 (20,80),左下坐标为 (20, 20),右上坐标为 (120, 80),右下坐标将是 (120, 20)。线段 B 的起始坐标为 (55, 65),结束坐标为 (90, 90)。

如果我要剪辑片段 B,那么它的起始坐标为 (55,65),结束坐标为 (76, 80)。

以编程方式,我将如何计算线段与窗口的线段相交的位置?同样,我将如何发现它们根本不像段 E 相交。

【问题讨论】:

    标签: java math grid coordinates line-segment


    【解决方案1】:

    试试这个。

    public static boolean clipLine(Line2D line, Rectangle2D rect) {
    
        double x1 = line.getX1(), y1 = line.getY1(), x2 = line.getX2(), y2 = line.getY2();
        double minX = rect.getMinX(), maxX = rect.getMaxX(), minY = rect.getMinY(), maxY = rect.getMaxY();
        int f1 = rect.outcode(x1, y1);
        int f2 = rect.outcode(x2, y2);
    
        while ((f1 | f2) != 0) {
            if ((f1 & f2) != 0) {
                return false;
            }
            double dx = (x2 - x1);
            double dy = (y2 - y1);
            // update (x1, y1), (x2, y2) and f1 and f2 using intersections
            // then recheck
            if (f1 != 0) {
                // first point is outside, so we update it against one of the
                // four sides then continue
                if ((f1 & Rectangle2D.OUT_LEFT) == Rectangle2D.OUT_LEFT
                        && dx != 0.0) {
                    y1 = y1 + (minX - x1) * dy / dx;
                    x1 = minX;
                }
                else if ((f1 & Rectangle2D.OUT_RIGHT) == Rectangle2D.OUT_RIGHT
                        && dx != 0.0) {
                    y1 = y1 + (maxX - x1) * dy / dx;
                    x1 = maxX;
                }
                else if ((f1 & Rectangle2D.OUT_BOTTOM) == Rectangle2D.OUT_BOTTOM
                        && dy != 0.0) {
                    x1 = x1 + (maxY - y1) * dx / dy;
                    y1 = maxY;
                }
                else if ((f1 & Rectangle2D.OUT_TOP) == Rectangle2D.OUT_TOP
                        && dy != 0.0) {
                    x1 = x1 + (minY - y1) * dx / dy;
                    y1 = minY;
                }
                f1 = rect.outcode(x1, y1);
            }
            else if (f2 != 0) {
                // second point is outside, so we update it against one of the
                // four sides then continue
                if ((f2 & Rectangle2D.OUT_LEFT) == Rectangle2D.OUT_LEFT
                        && dx != 0.0) {
                    y2 = y2 + (minX - x2) * dy / dx;
                    x2 = minX;
                }
                else if ((f2 & Rectangle2D.OUT_RIGHT) == Rectangle2D.OUT_RIGHT
                        && dx != 0.0) {
                    y2 = y2 + (maxX - x2) * dy / dx;
                    x2 = maxX;
                }
                else if ((f2 & Rectangle2D.OUT_BOTTOM) == Rectangle2D.OUT_BOTTOM
                        && dy != 0.0) {
                    x2 = x2 + (maxY - y2) * dx / dy;
                    y2 = maxY;
                }
                else if ((f2 & Rectangle2D.OUT_TOP) == Rectangle2D.OUT_TOP
                        && dy != 0.0) {
                    x2 = x2 + (minY - y2) * dx / dy;
                    y2 = minY;
                }
                f2 = rect.outcode(x2, y2);
            }
        }
    
        line.setLine(x1, y1, x2, y2);
        return true;  // the line is visible - if it wasn't, we'd have
                      // returned false from within the while loop above
    
    }
    

    public static void main(String[] args) {
        Rectangle2D.Double rectangle = new Rectangle2D.Double(20, 20, 100, 60); // x, y, width, height
        Line2D.Double line = new Line2D.Double(55, 65, 90, 90); // x1, y1, x2, y2
        boolean result = clipLine(line, rectangle);
        System.out.println("result=" + result
            + " x1=" + line.x1 + " y1=" + line.y1
            + " x2=" + line.x2 + " y2=" + line.y2);
    }
    

    输出:

    result=true x1=55.0 y1=65.0 x2=76.0 y2=80.0
    

    【讨论】:

    • 这看起来很不错。以前从未使用过 Rectangle2D,所以我一定会检查并尝试使用它。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    • 2014-11-07
    • 2011-12-04
    • 2017-02-09
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多