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)创建交集,然后将交叉点转回一条线。