Circle equal division coordinate calculation program (calculation optimization without floating point calculation)

Circle equal division coordinate calculation program

  • mathematical principles
  • programming
    • Make a table of trigonometric functions
    • Calculate coordinates
    • demo program

Principles of mathematics

Assume that the circle N with a radius of R is equally divided. The index k starts at 12 o’clock and is arranged clockwise, then each coordinate point The general calculation formula is:

x

[

k

]

=

R

?

sin

?

(

k

?

2

π

N

)

the y

[

k

]

=

R

?

cos

?

(

k

?

2

π

N

)

x[k] = R\cdot \sin (\frac{k\cdot 2\pi}{N})\ y[k] = R\cdot \cos(\frac{k\cdot 2\pi}{N })

x[k]=R?sin(Nk?2π?)y[k]=R?cos(Nk?2π?)

Assumptions:

  • The center of the circle is the origin of coordinates
  • k is always less than N.
  • The k variable counts from zero

Programming

Using the look-up table method can greatly speed up computers that are not equipped with hardware floating-point operations

Make a trigonometric function table

const unsigned char RH_UTIL__SINE_FUNC[256] = {<!-- -->
    0,2,3,5,6,8,9,11,13,14,16,17,19,20,22,23,25,27,28,30,31,33,34,36,37, 39,\
    41,42,44,45,47,48,50,51,53,54,56,57,59,60,62,63,65,67,68,70,71,73,74,76,\
    77,79,80,81,83,84,86,87,89,90,92,93,95,96,98,99,100,102,103,105,106,108,\
    109,110,112,113,115,116,117,119,120,122,123,124,126,127,128,130,131,132,\
    134,135,136,138,139,140,142,143,144,146,147,148,149,151,152,153,154,156,\
    157,158,159,161,162,163,164,165,167,168,169,170,171,172,174,175,176,177,\
    178,179,180,181,183,184,185,186,187,188,189,190,191,192,193,194,195,196,\
    197,198,199,200,201,202,203,204,205,206,207,208,208,209,210,211,212,213,\
    214,215,215,216,217,218,219,220,220,221,222,223,223,224,225,226,226,227,\
    228,228,229,230,231,231,232,232,233,234,234,235,236,236,237,237,238,238,\
    239,240,240,241,241,242,242,243,243,244,244,244,245,245,246,246,247,247,\
    247,248,248,248,249,249,249,250,250,250,251,251,251,252,252,252,252,252,\
    253,253,253,253,253,254,254,254,254,254,254,254,255,255,255,255,255,255,\
    255,255,255,255
};
  • Angle interval

    deg

    ?

    [

    0

    ,

    90

    )

    ?

    rad

    [

    0

    ,

    π

    2

    )

    \deg \in [0, 90) \Leftrightarrow \text{rad} \in [0, \frac{\pi}{2})

    deg∈[0,90)?rad∈[0,2π?)

  • Sampling accuracy A total of 256 uniform sampling points

It can be converted into arbitrary sine and cosine values by using the trigonometric induction formula, and the derivation process is omitted, see notes for details.

Calculate coordinates

typedef uint8_t u8;
typedef int16_t i16;

/**
 * @brief This function is to calculate widget position in a CW direction
 * @cond - Assume the clock panel size is 240x240
 * - Assume ranking in clockwise diesel
 * - Assume (120,120) as original point
 * @param rank Item ranking in the list
 * @param totalNum Total number of items in the list
 * @param radius Radius of the circle
 * @return posX X position offset in pixel. If null, do nothing
 * @return posY Y position offset in pixel. If null, do nothing
 * @retval Return 0 if success
 * Return 1 if null pointer was given
 * Return 2 if parameters are wrong
*/
int rh_util__posCw( u8 rank, u8 totalNum, u8 radius, i16* posX, i16*posY){<!-- -->
    if( !posX & amp; & amp; !posY ) return 1;
    if( totalNum==0 ) return 2;
    
    u32 angle = (rank<<10)/totalNum;
    
    switch( angle>>8){<!-- -->
        case 0:{<!-- --> // sin(x) = sin(x); cos(x) = sin(pi/2-x)
            if(posX) *posX = (radius*RH_UTIL__SINE_FUNC[angle]>>8);
            if(posY) *posY = (radius*RH_UTIL__SINE_FUNC[0xff-angle]>>8);
            break;
        }
        case 1:{<!-- --> // sin(x + pi/2) = sin(pi/2-x); cos(x + pi/2) = -sin(x)
            angle & amp;= 0xff;
            if(posX) *posX = (radius*RH_UTIL__SINE_FUNC[0xff-angle]>>8);
            if(posY) *posY = -(radius*RH_UTIL__SINE_FUNC[angle]>>8);
            break;
        }
        case 2:{<!-- --> // sin(x + pi) = -sin(x); cos(x + pi) = -sin(pi/2-x)
            angle & amp;= 0xff;
            if(posX) *posX = -(radius*RH_UTIL__SINE_FUNC[angle]>>8);
            if(posY) *posY = -(radius*RH_UTIL__SINE_FUNC[0xff-angle]>>8);
            break;
        }
        case 3:{<!-- --> // sin(x + 2pi/3) = -sin(pi/2-x); cos(x + 2pi/3) = sin(x)
            angle & amp;= 0xff;
            if(posX) *posX = -(radius*RH_UTIL__SINE_FUNC[0xff-angle]>>8);
            if(posY) *posY = (radius*RH_UTIL__SINE_FUNC[angle]>>8);
            break;
        }
        default:{<!-- --> /* Error. rank is bigger than totalNum */
            return 2;
        }
            
    }
    
    return 0;
}

Demo program

int main(int argc, const char * argv[]) {<!-- -->
    
    i16 posX=0, posY=0;
    u8 totalPoints = 16;
    u8 radius = 120;
    for(int i=0; i<totalPoints; + + i){<!-- -->
        rh_util__posCw( i, totalPoints, radius, &posX, &posY);
        printf( "[%d]: (%d,%d)\
", i, posX, posY);
    }
    
    
    return 0;
}
[0]: (0,119)
[1]: (45,110)
[2]: (84,83)
[3]: (110,45)
[4]: (119,0)
[5]: (110,-45)
[6]: (83,-84)
[7]: (45,-110)
[8]: (0,-119)
[9]: (-45,-110)
[10]: (-84,-83)
[11]: (-110,-45)
[12]: (-119,0)
[13]: (-110,45)
[14]: (-83,84)
[15]: (-45,110)
Program ended with exit code: 0