【问题标题】:Fill triangle with 3 color gradient in Java在Java中用3种颜色渐变填充三角形
【发布时间】:2017-01-01 10:30:50
【问题描述】:

我无法找到解决此问题的方法。 我想在 Java 中绘制一个带有渐变的填充三角形,其中每个角都有不同的颜色。像这样:

我在网上找到了一些帖子,但我无法弄清楚如何在 Java 中进行渐变。问题是在 Java 中你只能从一种颜色到另一种颜色进行 GradientPaint,这不适合填充三角形。

到目前为止,我想出的代码不能按预期工作:

triangle.p1().getValue();
Color color1 = calculateColor(triangle.p1().getValue());
Color color2 = calculateColor(triangle.p2().getValue());
Color color3 = calculateColor(triangle.p3().getValue());
Color transparent = new Color(0, 0, 0, 0);
Polygon polygon = new Polygon(
        new int[]{(int) triangle.p1().x(), (int) triangle.p2().x(), (int) triangle.p3().x()},
        new int[]{(int) triangle.p1().y(), (int) triangle.p2().y(), (int) triangle.p3().y()},
        3);
GradientPaint gradient1 = new GradientPaint(
        (float) triangle.p1().x(), (float) triangle.p1().y(), color1,
        (float) triangle.p2().x(), (float) triangle.p2().y(), transparent);
GradientPaint gradient2 = new GradientPaint(
        (float) triangle.p2().x(), (float) triangle.p2().y(), color2,
        (float) triangle.p3().x(), (float) triangle.p3().y(), transparent);
GradientPaint gradient3 = new GradientPaint(
        (float) triangle.p3().x(), (float) triangle.p3().y(), color3,
        (float) triangle.p1().x(), (float) triangle.p1().y(), transparent);
graphics2d.setPaint(gradient1);
graphics2d.fill(polygon);
graphics2d.setPaint(gradient2);
graphics2d.fill(polygon);
graphics2d.setPaint(gradient3);
graphics2d.fill(polygon);

这是我得到的结果:

一些提到类似事情的线程: Triangle Gradient With Core GraphicsJava 3 Color Gradient

【问题讨论】:

  • 你有什么问题?你有一个很好的解释,甚至是一些示例代码。有没有错误?您的代码(请发布一些)不起作用吗?还是你停留在一个特定的细节上?请具体一点。
  • 我更新了问题描述并添加了一些代码。
  • 你用这段代码得到的结果是什么,你能添加一个当前结果的截图吗? (我的猜测是它在三角形中间插入白色?)
  • 无论如何,感谢陌生人对完全合理的问题投反对票。你是最棒的!
  • 好吧,首先我认为你所有的颜色都是绿色的。这意味着如果您想要多种颜色(蓝色和红色),您需要修复第一部分(您调用calculateColor(triangle.p1().getValue());。其次,您的渐变矢量/方向不正确。现在每个渐变都从一个角指向下一个角三角形边界的方向,而不是指向沿着中值的对边线的中心。它仍然会产生很好的效果,尽管我认为不是你想要的。

标签: java graphics gradient


【解决方案1】:

这是基于这样的想法,即如果您在三角形内选择任何颜色,它将从三角形的三个点创建三个区域。因此我们扩展了线性插值的原理

color=(distance to p1)/(distance p1, p2)*c1+(distance to p2)/distance(p1, p2)*c2;

到二维平面。因此,加权系数将是面积:

public int areaTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {
  return (int)(0.5*Math.abs((x1-x3)*(y2-y1)-(x1-x2)*(y3-y1)));
}

BufferedImage b=new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
Polygon pl=new Polygon();
pl.addPoint(100, 100); pl.addPoint(200, 150); pl.addPoint(150, 200);
Rectangle r=pl.getBounds();
int a=areaTriangle(pl.xpoints[0], pl.ypoints[0], pl.xpoints[1], pl.ypoints[1], pl.xpoints[2], pl.ypoints[2]);
int[] c1={255, 0, 0}, c2={0, 255, 0}, c3={0, 0, 255};
for(i=0; i<r.width; i++)
for(j=0; j<r.height; j++)
  if(pl.contains(r.x+i, r.y+j)) {
    int ix=r.x+i, jy=r.y+j;
    int a1=areaTriangle(ix, jy, pl.xpoints[0], pl.ypoints[0], pl.xpoints[1], pl.ypoints[1]);
    int a2=areaTriangle(ix, jy, pl.xpoints[0], pl.ypoints[0], pl.xpoints[2], pl.ypoints[2]);
    int a3=areaTriangle(ix, jy, pl.xpoints[1], pl.ypoints[1], pl.xpoints[2], pl.ypoints[2]);

    int[] c=new int[3];
//      for(l=0; l<3; l++) c[l]=(int)((1-1.0*a1/a)*c1[l]+(1-1.0*a2/a)*c2[l]+(1-1.0*a3/a)*c3[l]);
    for(l=0; l<3; l++) c[l]=(int)((1.0*a1/a)*c3[l]+(1.0*a2/a)*c2[l]+(1.0*a3/a)*c1[l]);
    b.setRGB(ix, jy, 0xff000000|(c[0]<<16)|(c[1]<<8)|c[2]);
  }

如果您尝试注释行,您将获得三种互补色。

【讨论】:

    【解决方案2】:

    我意识到这是一个老问题,但问题仍然没有得到满意的回答。

    问题在于没有合适的java.awt.Paint 实现支持在三角形内插值颜色,其中颜色在三角形顶点处给出。这在计算机图形学(光栅化)中很常见,其中重心坐标用于确定三角形内某个点的混合权重(参见https://www.khronos.org/registry/OpenGL/specs/gl/glspec14.pdf 第 3.5.1 节)。

    由于我也无法在网络上为java.awt.Graphics2D 找到任何此类 Paint 实现的实现,因此我自己实现了它。你可以在这里找到它(标题为BarycentricGradientPaint):https://gist.github.com/hageldave/391bacc787f31d2fb2c7a10d1446c5f6

    作为参考的屏幕截图,注意第二个三角形是如何部分透明的并且边缘是抗锯齿的。 AA 是通过 4x MSAA 方法实现的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-01
      • 1970-01-01
      • 2020-07-17
      • 2016-03-13
      • 2012-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多