1

我想从 ARC 中获取所有顶点。我有用于绘制弧线的所有数据(例如:起点、终点、起点角度、终点角度、半径),但我需要从弧线数据中生成所有顶点。

我已经尝试过一种或两种算法,但我未能从弧数据中获得确切的顶点。

我使用了 Bresenham 的算法,但我失败了。

现在我正在使用下面的代码,但它不起作用..

            double theta = 2 * 3.1415926 / 100; 
            double c = Math.cos(theta);
            double s = Math.sin(theta);
            double t;

            double x = ((ArcTo) element).getRadius();//we start at angle = 0 
            double y = 0; 

            for(int ii = 0; ii < 100; ii++) { 
              coordinates.add(new Coordinate(x + element.getCenterPoint().getX(), y + element.getCenterPoint().getY()));//output vertex 

              //apply the rotation matrix
              t = x;
              x = c * x - s * y;
              y = s * t + c * y;
            }

请帮我。谢谢你。

4

1 回答 1

0
  1. 首先做一些澄清

    我假设顶点是指像素,ARC是标准的二维圆弧(不是椭圆弧!!!),您的输入数据是:

    int (x0,y0),(x1,y1) // star/end points on curve !!!
    float a0,a1         // start end angles [rad]
    int (xc,yc)         // center of circle
    int r               // radius
    
  2. 不要使用布雷森汉姆

    因为您需要从零角度开始计算所有像素,直到到达起点。然后翻转绘制标志,以便您从该点开始填充像素并在端点命中时停止。您还需要处理绕组以匹配ARC方向。

  3. 您可以使用圆参数方程

    // just some arc data to test with
    float r=25.0;
    float a0= 45.0*M_PI/180.0;
    float a1=270.0*M_PI/180.0;
    int xc=100,x0=xc+floor(r*cos(a0)),x1=xc+floor(r*cos(a1));
    int yc=100,y0=yc+floor(r*sin(a0)),y1=yc+floor(r*sin(a1));
    // arc rasterize code
    int x,y;
    float a,da;
    // here draw pixels x0,y0 and x1,y1 to avoid rounding holes ...
    if (r) da=0.75/float(r); else da=0.1; // step slightly less then pixel to avoid holes
    for (a=a0;;a+=da)
     {
     x=xc+int(floor(r*cos(a)));
     y=yc+int(floor(r*sin(a)));
     // here draw pixel x,y
     if ((x==x1)&&(y==y1)) // stop if endpoint reach
      if (fabs(a-a1)<da)   // but ignore stop if not at end angle (full or empty circle arc)
       break;
     }
    

    可能roundfloor减少像素位置误差。如果您的端点不匹配,那么这将无限循环。如果你稍微调整一下结束条件,你甚至可以避免这种情况,或者像我一样重新x1,y1计算a1......

  4. 你可以使用方程(x-xc)^2+(y-yc)^2=r^2

    您需要将ARC划分为象限,并将每个象限作为单独的弧循环处理xy计算另一个坐标。循环通过变化更多的坐标

    dx,dy 象限

    所以在蓝色区域循环y和红色循环x。例如,红色区号可能如下所示:

    int x,y;
    for (x=_x0;;x++)
     {
     y=sqrt((r*r)-((x-xc)*(x-xc)));
     // here draw pixel x,y
     if (x==_x1) // stop if endpoint reach
      break;
     }
    

    您需要计算象限内ARC(_x0,_y0),(_x1,_y1)的切割部分的起点并制作._x0<=_x1


    _x循环起点/终点坐标的值为xc +/- sqrt(r)orx0或循环起点/终点坐标x1
    的值为or或_yyc +/- sqrt(r)y0y1

    蓝色部分以类似的方式完成(只是交换/替换xy)。由于切割,这种方法有点复杂,但只能在整数上完成。可以通过LUT(限制最大半径)sqrt加速,也可以进一步优化。^2

[笔记]

所以如果我概括一下参数方程是最容易实现但最慢的。然后是可以像 Bresenham 一样快的方法(使用LUTsqrt可能更快),但需要将ARC切割成象限的代码,在渲染之前需要几秒。if

所有代码都在C++中,并且可以进一步改进,例如避免一些int/float转换,在循环之前预先计算一些值等......

最后一个去布雷森纳姆,但你需要改变里面的一些东西,当你不知道你在做什么时,你很容易迷路。它还需要削减到八分圆,因此变化的复杂性远大于sqrt接近

于 2015-04-26T08:28:43.623 回答