最优雅的方式剪线?

时间:2022-11-14 20:21:23

I have a Rectangle2D and a Line2D. I want to "clip" the line so that only the part of the line which is within the rectangle remains. If none of the line is within the rectangle I want the line to be set to (0,0,0,0). Basically something along the lines of a

我有一个Rectangle2D和一个Line2D。我想“剪切”该线,以便只保留矩形内的线条部分。如果该行都不在矩形内,我希望将该行设置为(0,0,0,0)。基本上是一些东西

Rectangle2D.intersect(Line2D src, Line2D dest)

or something similar.

或类似的东西。

Is there a way to do this with the java.awt.geom API? Or an elegant way to code it "by hand"?

有没有办法用java.awt.geom API做到这一点?还是一种“手工”编码的优雅方式?

4 个解决方案

#1


The source code for Rectangle2D.intersectLine() might be helpful:

Rectangle2D.intersectLine()的源代码可能会有所帮助:

public boolean intersectsLine(double x1, double y1, double x2, double y2) {
    int out1, out2;
    if ((out2 = outcode(x2, y2)) == 0) {
        return true;
    }
    while ((out1 = outcode(x1, y1)) != 0) {
        if ((out1 & out2) != 0) {
            return false;
        }
        if ((out1 & (OUT_LEFT | OUT_RIGHT)) != 0) {
            double x = getX();
            if ((out1 & OUT_RIGHT) != 0) {
                x += getWidth();
            }
            y1 = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
            x1 = x;
        } else {
            double y = getY();
            if ((out1 & OUT_BOTTOM) != 0) {
                y += getHeight();
            }
            x1 = x1 + (y - y1) * (x2 - x1) / (y2 - y1);
            y1 = y;
        }
    }
    return true;
}

where outcode() is defined as:

其中outcode()定义为:

public int outcode(double x, double y) {
    int out = 0;
    if (this.width <= 0) {
        out |= OUT_LEFT | OUT_RIGHT;
    } else if (x < this.x) {
        out |= OUT_LEFT;
    } else if (x > this.x + this.width) {
        out |= OUT_RIGHT;
    }
    if (this.height <= 0) {
        out |= OUT_TOP | OUT_BOTTOM;
    } else if (y < this.y) {
        out |= OUT_TOP;
    } else if (y > this.y + this.height) {
        out |= OUT_BOTTOM;
    }
    return out;
}

(from OpenJDK)

It shouldn't be extremely difficult to change this to clip instead of returning true or false.

将其更改为剪辑而不是返回true或false应该不是非常困难。

#2


There's no pretty way to do it with AWT. Your best bet is something like the Cohen-Sutherland algorithm. Here's a link with example Java code (lern2indent, amirite?) to show you how it's done.

使用AWT没有很好的办法。你最好的选择就是Cohen-Sutherland算法。这里有一个示例Java代码(lern2indent,amirite?)的链接,向您展示它是如何完成的。

#3


The usual thing to do is restrict the clipping region in the graphics context with Graphics2D.clip. You might want to call Graphics.create so that you do not interfere with the original context.

通常要做的是使用Graphics2D.clip限制图形上下文中的剪切区域。您可能希望调用Graphics.create,以便不干扰原始上下文。

Graphics2D g = (Graphics2D)gOrig.create();
try {
    g.clip(clip);
    ...
} finally {
    g.dispose();
}

#4


Well, I ended up doing it myself.

好吧,我最终自己做了。

For those intereseted, I ended up solving it by turning the line into a rectangle (with getBounds), then using Rectangle.intersect(clipRect,lineRect,intersectLineRect) to create the intersection, then turning the intersection back into a line.

对于那些相互关联的人,我最终通过将线条变为矩形(使用getBounds)来解决它,然后使用Rectangle.intersect(clipRect,lineRect,intersectLineRect)创建交集,然后将交叉点转回一条线。

#1


The source code for Rectangle2D.intersectLine() might be helpful:

Rectangle2D.intersectLine()的源代码可能会有所帮助:

public boolean intersectsLine(double x1, double y1, double x2, double y2) {
    int out1, out2;
    if ((out2 = outcode(x2, y2)) == 0) {
        return true;
    }
    while ((out1 = outcode(x1, y1)) != 0) {
        if ((out1 & out2) != 0) {
            return false;
        }
        if ((out1 & (OUT_LEFT | OUT_RIGHT)) != 0) {
            double x = getX();
            if ((out1 & OUT_RIGHT) != 0) {
                x += getWidth();
            }
            y1 = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
            x1 = x;
        } else {
            double y = getY();
            if ((out1 & OUT_BOTTOM) != 0) {
                y += getHeight();
            }
            x1 = x1 + (y - y1) * (x2 - x1) / (y2 - y1);
            y1 = y;
        }
    }
    return true;
}

where outcode() is defined as:

其中outcode()定义为:

public int outcode(double x, double y) {
    int out = 0;
    if (this.width <= 0) {
        out |= OUT_LEFT | OUT_RIGHT;
    } else if (x < this.x) {
        out |= OUT_LEFT;
    } else if (x > this.x + this.width) {
        out |= OUT_RIGHT;
    }
    if (this.height <= 0) {
        out |= OUT_TOP | OUT_BOTTOM;
    } else if (y < this.y) {
        out |= OUT_TOP;
    } else if (y > this.y + this.height) {
        out |= OUT_BOTTOM;
    }
    return out;
}

(from OpenJDK)

It shouldn't be extremely difficult to change this to clip instead of returning true or false.

将其更改为剪辑而不是返回true或false应该不是非常困难。

#2


There's no pretty way to do it with AWT. Your best bet is something like the Cohen-Sutherland algorithm. Here's a link with example Java code (lern2indent, amirite?) to show you how it's done.

使用AWT没有很好的办法。你最好的选择就是Cohen-Sutherland算法。这里有一个示例Java代码(lern2indent,amirite?)的链接,向您展示它是如何完成的。

#3


The usual thing to do is restrict the clipping region in the graphics context with Graphics2D.clip. You might want to call Graphics.create so that you do not interfere with the original context.

通常要做的是使用Graphics2D.clip限制图形上下文中的剪切区域。您可能希望调用Graphics.create,以便不干扰原始上下文。

Graphics2D g = (Graphics2D)gOrig.create();
try {
    g.clip(clip);
    ...
} finally {
    g.dispose();
}

#4


Well, I ended up doing it myself.

好吧,我最终自己做了。

For those intereseted, I ended up solving it by turning the line into a rectangle (with getBounds), then using Rectangle.intersect(clipRect,lineRect,intersectLineRect) to create the intersection, then turning the intersection back into a line.

对于那些相互关联的人,我最终通过将线条变为矩形(使用getBounds)来解决它,然后使用Rectangle.intersect(clipRect,lineRect,intersectLineRect)创建交集,然后将交叉点转回一条线。