Java2D:用线剪切 Graphics 对象

发布于 2024-07-06 23:41:52 字数 563 浏览 6 评论 0原文

有没有办法使用 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);

它几乎可以工作,但线的宽度根据其斜率而变化。

我无法使用 BrushStroke 和 drawLine() 方法,因为线条一旦通过任意参考线就会改变颜色。 是否有一些我忽略的 Shape 实现,或者我可以创建一个简单的实现,可以让我更轻松地完成此操作?

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:

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

撩动你心 2024-07-13 23:41:52

好的,我在不使用 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();

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:

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();
强者自强 2024-07-13 23:41:52

如果有更好的方法,我从来没有遇到过。 我能想到的最好的方法是使用一些三角函数来使线宽更加一致。

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.

洒一地阳光 2024-07-13 23:41:52

也许您可以使用 Stroke.createClippedShape 来执行此操作? (可能需要使用一个区域来从原始形状中添加减去描边形状,具体取决于您到底想要做什么。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文