1

I want to get all the vertices from an ARC. I have all the data (for ex : start point, end point, start angle, end angle, radius) which will used to draw an arc but my need is I have to generate all the vertices from the arc data.

I have already tried with one or two algorithm but I failed to get the exact vertices from an arc data.

I used Bresenham's algorithm but I failed.

Right now I am using below code but its not working ..

            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;
            }

Please help me. Thank you.

Spektre
  • 49,595
  • 11
  • 110
  • 380

1 Answers1

0
  1. First some clarifications

    I assume that by vertices you mean the pixels and ARC is standard 2D circular arc (not elliptic arc !!!) and your input data are:

    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. Do not use Bresenham

    because you would need to start from zero angle and compute all pixels until start point is hit. Then flip draw flag so you start filling the pixel from that point and stop on end point hit. Also you would need to handle the winding to match ARC direction.

  3. You can use circle parametric equation

    // 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;
     }
    

    may be round instead of floor will have less pixel position error. If your endpoint does not match then this will loop infinitely. If you tweak a bit the end conditions you can avoid even that or recompute x1,y1 from a1 as I have ...

  4. You can use equation (x-xc)^2+(y-yc)^2=r^2

    you need to divide ARC to quadrants and handle each as separate arc looping through x or y and computing the other coordinate. Loop through coordinate that is changing more

    dx,dy quadrants

    so in blue areas loop y and in the red loop x. For example red area code can look like this:

    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;
     }
    

    you need to compute (_x0,_y0),(_x1,_y1) start end points of cut part of ARC inside the quadrant and make _x0<=_x1.


    The value for _x looped start/end point coordinate will be xc +/- sqrt(r) or x0 or x1
    the value for _y looped start/end point coordinate will be yc +/- sqrt(r) or y0 or y1

    The blue parts are done in analogically manner (just swap/replace x and y). This approach is a bit more complicated due to cutting but can be done solely on integers. sqrt can be speed up by LUT (limiting the max radius) and the ^2 can be also further optimized.

[Notes]

so if I recapitulate the parametric equation is the simplest to implement but slowest. Then is the sqrt approach which can be done as fast as Bresenham (and may be even faster with LUT) but need the code for cutting ARC to quadrants which need few ifs prior to rendering.

All codes are in C++ and can be further improved like avoiding some int/float conversions, pre-compute some values before loop, etc ...

The last goes the Bresenham but you need to change a few things inside and when you do not know what you are doing you can easily get lost. It also need to cut to octant's so the complexity of change is far bigger then sqrt approach

Spektre
  • 49,595
  • 11
  • 110
  • 380