0

假设您在下面有以下正坐标区域:在此处输入图像描述

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

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

但是,如果我要剪辑段 B,那么它将具有 (55,65) 的起始坐标和 (76, 80) 的结束坐标。

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

4

1 回答 1

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
于 2021-11-11T23:58:22.050 回答