[SVG] JavaScript Functions used to calculate the center point coordinates, start angles, and end Angles Based on SVG Elliptical Arc path parameters

Source: Internet
Author: User
Tags acos x2 y2

In SVG spec 1.2 and earlier versions, there is only one way to draw an elliptical arc, that is, an arc is determined by starting point, ending point, long half axis, short half axis, large and small Arc Mark, clockwise marking, and inclination. This method is powerful and flexible, and can draw any elliptical arc. Sometimes we need to calculate the center of the arc, the starting angle, and the ending angle. Although the standard official documentation provides a description of the calculation formula, it does not provide direct code. I wrote a JavaScript function based on standard documents and online materials to do this.

    // svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+    /* x1 y1 x2 y2 fA fS rx ry φ */    function  radian( ux, uy, vx, vy ) {        var  dot = ux * vx + uy * vy;        var  mod = Math.sqrt( ( ux * ux + uy * uy ) * ( vx * vx + vy * vy ) );        var  rad = Math.acos( dot / mod );        if( ux * vy - uy * vx < 0.0 ) rad = -rad;        return  rad;    }    //conversion_from_endpoint_to_center_parameterization    //sample :  convert(200,200,300,200,1,1,50,50,0,{})    function convert(x1, y1, x2, y2, fA, fS, rx, ry, phi) {            var cx,cy,theta1,delta_theta;            if( rx == 0.0 || ry == 0.0 ) return -1;  // invalid arguments            var  s_phi = Math.sin( phi );            var  c_phi = Math.cos( phi );            var  hd_x = ( x1 - x2 ) / 2.0;   // half diff of x            var  hd_y = ( y1 - y2 ) / 2.0;   // half diff of y            var  hs_x = ( x1 + x2 ) / 2.0;   // half sum of x            var  hs_y = ( y1 + y2 ) / 2.0;   // half sum of y            // F6.5.1            var  x1_ = c_phi * hd_x + s_phi * hd_y;            var  y1_ = c_phi * hd_y - s_phi * hd_x;            var  rxry = rx * ry;            var  rxy1_ = rx * y1_;            var  ryx1_ = ry * x1_;            var  sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_;   // sum of square            var  coe = Math.sqrt( ( rxry * rxry - sum_of_sq ) / sum_of_sq );            if( fA == fS ) coe = -coe;            // F6.5.2            var  cx_ = coe * rxy1_ / ry;            var  cy_ = -coe * ryx1_ / rx;            // F6.5.3            cx = c_phi * cx_ - s_phi * cy_ + hs_x;            cy = s_phi * cx_ + c_phi * cy_ + hs_y;            var  xcr1 = ( x1_ - cx_ ) / rx;            var  xcr2 = ( x1_ + cx_ ) / rx;            var  ycr1 = ( y1_ - cy_ ) / ry;            var  ycr2 = ( y1_ + cy_ ) / ry;            // F6.5.5            theta1 = radian( 1.0, 0.0, xcr1, ycr1 );            // F6.5.6            delta_theta = radian( xcr1, ycr1, -xcr2, -ycr2 );            var  PIx2 = Math.PI * 2.0;            while( delta_theta > PIx2 ) delta_theta -= PIx2;            while( delta_theta < 0.0 ) delta_theta += PIx2;            if( fS == false ) delta_theta -= PIx2;            var outputObj = { /* cx, cy, theta1, delta_theta */                 cx : cx,                cy : cy,                theta1 : theta1,                delta_theta : delta_theta            }            console.dir(outputObj);            return outputObj;    }

In SVG spec 1.2 and earlier versions, there is only one way to draw an elliptical arc, that is, an arc is determined by starting point, ending point, long half axis, short half axis, large and small Arc Mark, clockwise marking, and inclination. This method is powerful and flexible, and can draw any elliptical arc. Sometimes we need to calculate the center of the arc, the starting angle, and the ending angle. Although the standard official documentation provides a description of the calculation formula, it does not provide direct code. I wrote a JavaScript function based on standard documents and online materials to do this.

    // svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+    /* x1 y1 x2 y2 fA fS rx ry φ */    function  radian( ux, uy, vx, vy ) {        var  dot = ux * vx + uy * vy;        var  mod = Math.sqrt( ( ux * ux + uy * uy ) * ( vx * vx + vy * vy ) );        var  rad = Math.acos( dot / mod );        if( ux * vy - uy * vx < 0.0 ) rad = -rad;        return  rad;    }    //conversion_from_endpoint_to_center_parameterization    //sample :  convert(200,200,300,200,1,1,50,50,0,{})    function convert(x1, y1, x2, y2, fA, fS, rx, ry, phi) {            var cx,cy,theta1,delta_theta;            if( rx == 0.0 || ry == 0.0 ) return -1;  // invalid arguments            var  s_phi = Math.sin( phi );            var  c_phi = Math.cos( phi );            var  hd_x = ( x1 - x2 ) / 2.0;   // half diff of x            var  hd_y = ( y1 - y2 ) / 2.0;   // half diff of y            var  hs_x = ( x1 + x2 ) / 2.0;   // half sum of x            var  hs_y = ( y1 + y2 ) / 2.0;   // half sum of y            // F6.5.1            var  x1_ = c_phi * hd_x + s_phi * hd_y;            var  y1_ = c_phi * hd_y - s_phi * hd_x;            var  rxry = rx * ry;            var  rxy1_ = rx * y1_;            var  ryx1_ = ry * x1_;            var  sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_;   // sum of square            var  coe = Math.sqrt( ( rxry * rxry - sum_of_sq ) / sum_of_sq );            if( fA == fS ) coe = -coe;            // F6.5.2            var  cx_ = coe * rxy1_ / ry;            var  cy_ = -coe * ryx1_ / rx;            // F6.5.3            cx = c_phi * cx_ - s_phi * cy_ + hs_x;            cy = s_phi * cx_ + c_phi * cy_ + hs_y;            var  xcr1 = ( x1_ - cx_ ) / rx;            var  xcr2 = ( x1_ + cx_ ) / rx;            var  ycr1 = ( y1_ - cy_ ) / ry;            var  ycr2 = ( y1_ + cy_ ) / ry;            // F6.5.5            theta1 = radian( 1.0, 0.0, xcr1, ycr1 );            // F6.5.6            delta_theta = radian( xcr1, ycr1, -xcr2, -ycr2 );            var  PIx2 = Math.PI * 2.0;            while( delta_theta > PIx2 ) delta_theta -= PIx2;            while( delta_theta < 0.0 ) delta_theta += PIx2;            if( fS == false ) delta_theta -= PIx2;            var outputObj = { /* cx, cy, theta1, delta_theta */                 cx : cx,                cy : cy,                theta1 : theta1,                delta_theta : delta_theta            }            console.dir(outputObj);            return outputObj;    }

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.