⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 agg_bezier_arc.cpp

📁 okular
💻 CPP
字号:
//----------------------------------------------------------------------------// Anti-Grain Geometry - Version 2.3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)//// Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied// warranty, and with no claim as to its suitability for any purpose.////----------------------------------------------------------------------------// Contact: mcseem@antigrain.com//          mcseemagg@yahoo.com//          http://www.antigrain.com//----------------------------------------------------------------------------//// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e., // 4, 7, 10, or 13 vertices.////----------------------------------------------------------------------------#include <math.h>#include "agg_bezier_arc.h"namespace agg{    //------------------------------------------------------------arc_to_bezier    void arc_to_bezier(double cx, double cy, double rx, double ry,                        double start_angle, double sweep_angle,                       double* curve)    {        double x0 = cos(sweep_angle / 2.0);        double y0 = sin(sweep_angle / 2.0);        double tx = (1.0 - x0) * 4.0 / 3.0;        double ty = y0 - tx * x0 / y0;        double px[4];        double py[4];        px[0] =  x0;        py[0] = -y0;        px[1] =  x0 + tx;        py[1] = -ty;        px[2] =  x0 + tx;        py[2] =  ty;        px[3] =  x0;        py[3] =  y0;        double sn = sin(start_angle + sweep_angle / 2.0);        double cs = cos(start_angle + sweep_angle / 2.0);        unsigned i;        for(i = 0; i < 4; i++)        {            curve[i * 2]     = cx + rx * (px[i] * cs - py[i] * sn);            curve[i * 2 + 1] = cy + ry * (px[i] * sn + py[i] * cs);        }    }    //------------------------------------------------------------------------    void bezier_arc::init(double x,  double y,                           double rx, double ry,                           double start_angle,                           double sweep_angle)    {        start_angle = fmod(start_angle, 2.0 * pi);        if(sweep_angle >=  2.0 * pi) sweep_angle =  2.0 * pi;        if(sweep_angle <= -2.0 * pi) sweep_angle = -2.0 * pi;        double total_sweep = 0.0;        double local_sweep = 0.0;        m_num_vertices = 2;        bool done = false;        do        {            if(sweep_angle < 0.0)            {                local_sweep = -pi * 0.5;                total_sweep -= pi * 0.5;                if(total_sweep <= sweep_angle)                {                    local_sweep = sweep_angle - (total_sweep + pi * 0.5);                    done = true;                }            }            else            {                local_sweep =  pi * 0.5;                total_sweep += pi * 0.5;                if(total_sweep >= sweep_angle)                {                    local_sweep = sweep_angle - (total_sweep - pi * 0.5);                    done = true;                }            }            arc_to_bezier(x, y, rx, ry,                           start_angle,                           local_sweep,                           m_vertices + m_num_vertices - 2);            m_num_vertices += 6;            start_angle += local_sweep;        }        while(!done && m_num_vertices < 26);    }    //--------------------------------------------------------------------    void bezier_arc_svg::init(double x0, double y0,                               double rx, double ry,                               double angle,                              bool large_arc_flag,                              bool sweep_flag,                              double x2, double y2)    {        m_radii_ok = true;        if(rx < 0.0) rx = -rx;        if(ry < 0.0) ry = -rx;        // Calculate the middle point between         // the current and the final points        //------------------------        double dx2 = (x0 - x2) / 2.0;        double dy2 = (y0 - y2) / 2.0;        // Convert angle from degrees to radians        //------------------------        double cos_a = cos(angle);        double sin_a = sin(angle);        // Calculate (x1, y1)        //------------------------        double x1 =  cos_a * dx2 + sin_a * dy2;        double y1 = -sin_a * dx2 + cos_a * dy2;        // Ensure radii are large enough        //------------------------        double prx = rx * rx;        double pry = ry * ry;        double px1 = x1 * x1;        double py1 = y1 * y1;        // Check that radii are large enough        //------------------------        double radii_check = px1/prx + py1/pry;        if(radii_check > 1.0)         {            rx = sqrt(radii_check) * rx;            ry = sqrt(radii_check) * ry;            prx = rx * rx;            pry = ry * ry;            if(radii_check > 10.0) m_radii_ok = false;        }        // Calculate (cx1, cy1)        //------------------------        double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0;        double sq   = (prx*pry - prx*py1 - pry*px1) / (prx*py1 + pry*px1);        double coef = sign * sqrt((sq < 0) ? 0 : sq);        double cx1  = coef *  ((rx * y1) / ry);        double cy1  = coef * -((ry * x1) / rx);        //        // Calculate (cx, cy) from (cx1, cy1)        //------------------------        double sx2 = (x0 + x2) / 2.0;        double sy2 = (y0 + y2) / 2.0;        double cx = sx2 + (cos_a * cx1 - sin_a * cy1);        double cy = sy2 + (sin_a * cx1 + cos_a * cy1);        // Calculate the start_angle (angle1) and the sweep_angle (dangle)        //------------------------        double ux =  (x1 - cx1) / rx;        double uy =  (y1 - cy1) / ry;        double vx = (-x1 - cx1) / rx;        double vy = (-y1 - cy1) / ry;        double p, n;        // Calculate the angle start        //------------------------        n = sqrt(ux*ux + uy*uy);        p = ux; // (1 * ux) + (0 * uy)        sign = (uy < 0) ? -1.0 : 1.0;        double v = p / n;        if(v < -1.0) v = -1.0;        if(v >  1.0) v =  1.0;        double start_angle = sign * 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.0 : 1.0;        v = p / n;        if(v < -1.0) v = -1.0;        if(v >  1.0) v =  1.0;        double sweep_angle = sign * acos(v);        if(!sweep_flag && sweep_angle > 0)         {            sweep_angle -= pi * 2.0;        }         else         if (sweep_flag && sweep_angle < 0)         {            sweep_angle += pi * 2.0;        }        // We can now build and transform the resulting arc        //------------------------        m_arc.init(0.0, 0.0, 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;        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -