java - 折线轮廓构造/绘制粗折线

标签 java algorithm graphics libgdx graphics2d

我面临着一项任务,我必须使用多边形绘制折线。 作为输入参数,我有一个点数组和厚度值。见下图。 enter image description here

我有形成黑色折线和厚度的点,例如10 像素。现在我需要计算点并构造一条蓝色折线以形成多边形,然后渲染它。

有一些与此相关的文章:

但是我发现它们有点复杂并且难以理解。 没有任何现有的库或更简单的算法来实现这一点。不需要圆形接头。我正在使用 java 和 libGDX。

最佳答案

算法如下:

for each line:
  find the parallel line upwards:
    find the perpendicular: has a slope m2 in approximate
    check which side is right (compare angles)
    find the two points of the parallel line by solving a small equation problem (A, B, C)
  if this line is the first one keep it (l1)
  else find the intersection with the previous line (l1, l2): this will give the next articulation point

黄线就是你想要的线;红线是一般平行线。 关节点呈绿色。您可以在某些组件中打印此缓冲图像。

注意:多边形的宽度不能像您意识到的那样固定,因为在铰接点处距离会更大。保证的是线段之间的距离恒定。

int[] approximate(int[] p, int[] p2, double dr, int l) { // l is the distance, dr is 0 for the beginning of the segment and 1 for the end
          double d=Math.sqrt(Math.pow(p[0]-p2[0], 2)+Math.pow(p[1]-p2[1], 2));
          double ix=p[0]+dr*(p2[0]-p[0]), iy=p[1]+dr*(p2[1]-p[1]);
          double x1=0, x2=0, y1=0, y2=0;
          if(p2[0]==p[0]) {
            x1=ix+l; x2=ix-l; y1=iy; y2=iy;
          }
          else {
          double m=1.0*(p2[1]-p[1])/(p2[0]-p[0]);
          if(Math.abs(m)==0) {
            x1=ix; x2=ix; y1=iy+l; y2=iy-l;
          }
          else {
            double m2=-1/m;
            double c=iy-m2*ix;
            double A=1+m2*m2, B=-2*(ix-m2*c+m2*iy), C=ix*ix+iy*iy+c*c-2*c*iy-l*l;
            x1=(-B+Math.sqrt(B*B-4*A*C))/(2*A); x2=(-B-Math.sqrt(B*B-4*A*C))/(2*A); y1=m2*x1+c; y2=m2*x2+c;
          }
          }
          int[] cp1={p2[0]-p[0], p2[1]-p[1]}, cp2={(int)x1-p[0], (int)y1-p[1]}, xy=new int[2];
          int cpp=compareAngles(cp1, cp2);
          if(cpp>0) { xy[0]=(int)x1; xy[1]=(int)y1; } else { xy[0]=(int)x2; xy[1]=(int)y2; }
          return xy;
  }

  void poly() {
    int[][] p={{100, 400}, {110, 440}, {250, 300}, {350, 400}, {300, 310}};
    BufferedImage bim=new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
    Graphics2D g=(Graphics2D)bim.getGraphics();
    g.setColor(Color.white);
    g.fillRect(0, 0, 500, 500);
    g.setStroke(new BasicStroke(5f));
    g.setColor(Color.black);
    Line2D.Double l1=new Line2D.Double(), l2=new Line2D.Double();
    int[] currentp=new int[2], lastp=new int[2];
    for(int i=0; i<p.length-1; i++) {
      g.setColor(Color.black);
      g.drawLine(p[i][0], p[i][1], p[i+1][0], p[i+1][1]);
      int[] p1=approximate(p[i], p[i+1], 0, 10), p2=approximate(p[i], p[i+1], 1, 10);
      g.setColor(Color.red);
      g.drawLine(p1[0], p1[1], p2[0], p2[1]);
      if(i==0) { l1=new Line2D.Double(p1[0], p1[1], p2[0], p2[1]); currentp[0]=p1[0]; currentp[1]=p1[1]; }
      else {
        l2=new Line2D.Double(p1[0], p1[1], p2[0], p2[1]);
        int[] pi=intersectionPoint(l1, l2);
        g.setColor(Color.green);
        g.fillOval(pi[0], pi[1], 5, 5);
        g.setColor(Color.yellow);
        g.drawLine(currentp[0], currentp[1], pi[0], pi[1]);
        currentp[0]=pi[0]; currentp[1]=pi[1];
        l1.setLine(l2);
      }
      if(i==p.length-2) { lastp[0]=p2[0]; lastp[1]=p2[1]; }
    }
    g.setColor(Color.yellow);
    g.drawLine(currentp[0], currentp[1], lastp[0], lastp[1]);
  }

  public int[] intersectionPoint(Line2D.Double l1, Line2D.Double l2) {
    return intersectionPoint((int)l1.getX1(), (int)l1.getY1(), (int)l1.getX2(), (int)l1.getY2(), (int)l2.getX1(), (int)l2.getY1(), (int)l2.getX2(), (int)l2.getY2());
  }

  public int[] intersectionPoint(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
    int[] xy={(int)(1.0*((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4))),
                (int)(1.0*((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)))};
    return xy;
  }


  public int compareAngles(int[] a, int[] b) {
    int cp=a[0]*b[1]-a[1]*b[0];
    return -cp;
  }

关于java - 折线轮廓构造/绘制粗折线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36475254/

相关文章:

未调用 Java JPanel paintComponent(Graphics g)

Delphi 2010 访问 TIFF 内的帧

arrays - 查找未排序数组中的所有对

java - 无法加载 native 库。错误 : java. lang.UnsatisfiedLinkError

java - 更改第 3 方进程的已知内存地址中的值,Java

java - java中字节数组的循环位移

arrays - 查找排序数组中结束值和起始值之差至多为 k 的最长连续子数组的长度

algorithm - 汉明数和 double

C# KeyPress 事件方法未在 Visual Studio 中注册?还是代码?

java - 如何将 Mule ESB 中的数据映射器转换为多个连接器以使用社区运行时?