Is there a way to use a Graphics object's 'setClip()' method to clip using a Line-ish shape? Right now I'm trying to use a Polygon shape but I'm having problems simulating the "width" of the line. I basically draw the line, and when I reach the end, I redraw it but this time subtract the line width from y-coordinate:
有没有办法使用Graphics对象的'setClip()'方法来使用Line-ish形状进行剪辑?现在我正在尝试使用多边形,但我在模拟线条的“宽度”时遇到了问题。我基本上绘制了这条线,当我到达终点时,我重绘它但是这次从y坐标中减去线宽:
Polygon poly = new Polygon();
for(int i = 0; i < points.length; i++)
poly.addPoint(points.[i].x, points.[i].y);
// Retrace line to add 'width'
for(int i = points.length - 1; i >=0; i--)
poly.addPoint(points[i].x, points[i].y - lineHeight);
It almost works but the width of the line varies based upon its slope.
它几乎可以工作,但线的宽度根据其斜率而变化。
I can't use the BrushStroke and drawLine() methods because the line can change color once it passes some arbitrary reference line. Is there some implementation of Shape that I overlooked, or an easy one I can create, that will let me do this more easily?
我不能使用BrushStroke和drawLine()方法,因为一旦它通过一些任意参考线,该线就可以改变颜色。是否有一些我忽略的Shape实现,或者我可以创建的一个简单的实现,这将让我更容易做到这一点?
3 个解决方案
#1
1
If there is a better way, I've never run across it. The best I can think of is to use some trigonometry to make the line width more consistent.
如果有更好的方法,我从来没有碰过它。我能想到的最好的是使用一些三角法来使线宽更加一致。
#2
1
OK, I managed to come up with a pretty nice solution without using the setClip() method. It involves drawing my background to an intermediate Graphics2D object, using setComposite() to specify how I want to mask the pixels, THEN drawing my line using drawLine() on top. Once I have this line, I draw it back on top of my original Graphics object via drawImage. Here's an example:
好的,我设法提出了一个非常好的解决方案,而不使用setClip()方法。它涉及将我的背景绘制到一个中间的Graphics2D对象,使用setComposite()指定我想要如何掩盖像素,然后使用drawLine()在顶部绘制我的线。一旦我有了这一行,我就通过drawImage将它绘制在我原来的Graphics对象之上。这是一个例子:
BufferedImage mask = g2d.getDeviceConfiguration().createCompatibleImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D maskGraphics = (Graphics2D) mask.getGraphics();
maskGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
maskGraphics.setStroke(new BasicStroke(lineWidth));
maskGraphics.setPaint(Color.BLACK);
// Draw line onto mask surface first.
Point prev = line.get(0);
for(int i = 1; i < line.size(); i++)
{
Point current = line.get(i);
maskGraphics.drawLine(prev.x, prev.y, current.x, current.y);
prev = current;
}
// AlphaComposite.SrcIn: "If pixels in the source and the destination overlap, only the source pixels
// in the overlapping area are rendered."
maskGraphics.setComposite(AlphaComposite.SrcIn);
maskGraphics.setPaint(top);
maskGraphics.fillRect(0, 0, width, referenceY);
maskGraphics.setPaint(bottom);
maskGraphics.fillRect(0, referenceY, width, height);
g2d.drawImage(mask, null, 0, 0);
maskGraphics.dispose();
#3
0
Maybe you could use a Stroke.createClippedShape to do this? (May need to use an Area to add subtract the stroked shape from/to your original shape depending on what exactly you are trying to do.
也许你可以使用Stroke.createClippedShape来做到这一点? (可能需要使用“区域”添加从原始形状中减去描边形状,具体取决于您要执行的操作。
#1
1
If there is a better way, I've never run across it. The best I can think of is to use some trigonometry to make the line width more consistent.
如果有更好的方法,我从来没有碰过它。我能想到的最好的是使用一些三角法来使线宽更加一致。
#2
1
OK, I managed to come up with a pretty nice solution without using the setClip() method. It involves drawing my background to an intermediate Graphics2D object, using setComposite() to specify how I want to mask the pixels, THEN drawing my line using drawLine() on top. Once I have this line, I draw it back on top of my original Graphics object via drawImage. Here's an example:
好的,我设法提出了一个非常好的解决方案,而不使用setClip()方法。它涉及将我的背景绘制到一个中间的Graphics2D对象,使用setComposite()指定我想要如何掩盖像素,然后使用drawLine()在顶部绘制我的线。一旦我有了这一行,我就通过drawImage将它绘制在我原来的Graphics对象之上。这是一个例子:
BufferedImage mask = g2d.getDeviceConfiguration().createCompatibleImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D maskGraphics = (Graphics2D) mask.getGraphics();
maskGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
maskGraphics.setStroke(new BasicStroke(lineWidth));
maskGraphics.setPaint(Color.BLACK);
// Draw line onto mask surface first.
Point prev = line.get(0);
for(int i = 1; i < line.size(); i++)
{
Point current = line.get(i);
maskGraphics.drawLine(prev.x, prev.y, current.x, current.y);
prev = current;
}
// AlphaComposite.SrcIn: "If pixels in the source and the destination overlap, only the source pixels
// in the overlapping area are rendered."
maskGraphics.setComposite(AlphaComposite.SrcIn);
maskGraphics.setPaint(top);
maskGraphics.fillRect(0, 0, width, referenceY);
maskGraphics.setPaint(bottom);
maskGraphics.fillRect(0, referenceY, width, height);
g2d.drawImage(mask, null, 0, 0);
maskGraphics.dispose();
#3
0
Maybe you could use a Stroke.createClippedShape to do this? (May need to use an Area to add subtract the stroked shape from/to your original shape depending on what exactly you are trying to do.
也许你可以使用Stroke.createClippedShape来做到这一点? (可能需要使用“区域”添加从原始形状中减去描边形状,具体取决于您要执行的操作。