示例#1
0
 //-------------------------------------------------------------------
 trans_affine to_affine() const
 {
     trans_affine mtx = trans_affine_translation(-m_wx1, -m_wy1);
     mtx *= trans_affine_scaling(m_kx, m_ky);
     mtx *= trans_affine_translation(m_dx1, m_dy1);
     return mtx;
 }
    //--------------------------------------------------------------------
    void bezier_arc_svg::init(real x0, real y0, 
                              real rx, real ry, 
                              real angle,
                              bool large_arc_flag,
                              bool sweep_flag,
                              real x2, real y2)
    {
        m_radii_ok = true;

        if(rx < 0.0f) rx = -rx;
        if(ry < 0.0f) ry = -rx;

        // Calculate the middle point between 
        // the current and the final points
        //------------------------
        real dx2 = (x0 - x2) / 2.0f;
        real dy2 = (y0 - y2) / 2.0f;

        real cos_a = (real)cos(angle);
        real sin_a = (real)sin(angle);

        // Calculate (x1, y1)
        //------------------------
        real x1 =  cos_a * dx2 + sin_a * dy2;
        real y1 = -sin_a * dx2 + cos_a * dy2;

        // Ensure radii are large enough
        //------------------------
        real prx = rx * rx;
        real pry = ry * ry;
        real px1 = x1 * x1;
        real py1 = y1 * y1;

        // Check that radii are large enough
        //------------------------
        real radii_check = px1/prx + py1/pry;
        if(radii_check > 1.0f) 
        {
            rx = SQRT(radii_check) * rx;
            ry = SQRT(radii_check) * ry;
            prx = rx * rx;
            pry = ry * ry;
            if(radii_check > 10.0f) m_radii_ok = false;
        }

        // Calculate (cx1, cy1)
        //------------------------
        real sign = (large_arc_flag == sweep_flag) ? -1.0f : 1.0f;
        real sq   = (prx*pry - prx*py1 - pry*px1) / (prx*py1 + pry*px1);
        real coef = sign * SQRT((sq < 0) ? 0 : sq);
        real cx1  = coef *  ((rx * y1) / ry);
        real cy1  = coef * -((ry * x1) / rx);

        //
        // Calculate (cx, cy) from (cx1, cy1)
        //------------------------
        real sx2 = (x0 + x2) / 2.0f;
        real sy2 = (y0 + y2) / 2.0f;
        real cx = sx2 + (cos_a * cx1 - sin_a * cy1);
        real cy = sy2 + (sin_a * cx1 + cos_a * cy1);

        // Calculate the start_angle (angle1) and the sweep_angle (dangle)
        //------------------------
        real ux =  (x1 - cx1) / rx;
        real uy =  (y1 - cy1) / ry;
        real vx = (-x1 - cx1) / rx;
        real vy = (-y1 - cy1) / ry;
        real p, n;

        // Calculate the angle start
        //------------------------
        n = SQRT(ux*ux + uy*uy);
        p = ux; // (1 * ux) + (0 * uy)
        sign = (uy < 0) ? -1.0f : 1.0f;
        real v = p / n;
        if(v < -1.0f) v = -1.0f;
        if(v >  1.0f) v =  1.0f;
        real start_angle = sign * (real)acos(v);

        // Calculate the sweep angle
        //------------------------
        n = SQRT((ux*ux + uy*uy) * (vx*vx + vy*vy));
        p = ux * vx + uy * vy;
        sign = (ux * vy - uy * vx < 0) ? -1.0f : 1.0f;
        v = p / n;
        if(v < -1.0f) v = -1.0f;
        if(v >  1.0f) v =  1.0f;
        real sweep_angle = sign * (real)acos(v);
        if(!sweep_flag && sweep_angle > 0) 
        {
            sweep_angle -= pi * 2.0f;
        } 
        else 
        if (sweep_flag && sweep_angle < 0) 
        {
            sweep_angle += pi * 2.0f;
        }

        // We can now build and transform the resulting arc
        //------------------------
        m_arc.init(0.0f, 0.0f, rx, ry, start_angle, sweep_angle);
        trans_affine mtx = trans_affine_rotation(angle);
        mtx *= trans_affine_translation(cx, cy);
        
        for(unsigned i = 2; i < m_arc.num_vertices()-2; i += 2)
        {
            mtx.transform(m_arc.vertices() + i, m_arc.vertices() + i + 1);
        }

        // We must make sure that the starting and ending points
        // exactly coincide with the initial (x0,y0) and (x2,y2)
        m_arc.vertices()[0] = x0;
        m_arc.vertices()[1] = y0;
        if(m_arc.num_vertices() > 2)
        {
            m_arc.vertices()[m_arc.num_vertices() - 2] = x2;
            m_arc.vertices()[m_arc.num_vertices() - 1] = y2;
        }
    }