agg_curves.cpp

来自「这是VCF框架的代码」· C++ 代码 · 共 572 行 · 第 1/2 页

CPP
572
字号
//----------------------------------------------------------------------------// Anti-Grain Geometry - Version 2.4// 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//----------------------------------------------------------------------------#include <math.h>#include "agg_curves.h"#include "agg_math.h"namespace agg{    //------------------------------------------------------------------------    const double curve_distance_epsilon                  = 1e-30;    const double curve_collinearity_epsilon              = 1e-30;    const double curve_angle_tolerance_epsilon           = 0.01;    enum curve_recursion_limit_e { curve_recursion_limit = 32 };    //------------------------------------------------------------------------    void curve3_inc::approximation_scale(double s)     {         m_scale = s;    }    //------------------------------------------------------------------------    double curve3_inc::approximation_scale() const     {         return m_scale;    }    //------------------------------------------------------------------------    void curve3_inc::init(double x1, double y1,                           double x2, double y2,                           double x3, double y3)    {        m_start_x = x1;        m_start_y = y1;        m_end_x   = x3;        m_end_y   = y3;        double dx1 = x2 - x1;        double dy1 = y2 - y1;        double dx2 = x3 - x2;        double dy2 = y3 - y2;        double len = sqrt(dx1 * dx1 + dy1 * dy1) + sqrt(dx2 * dx2 + dy2 * dy2);         m_num_steps = uround(len * 0.25 * m_scale);        if(m_num_steps < 4)        {            m_num_steps = 4;           }        double subdivide_step  = 1.0 / m_num_steps;        double subdivide_step2 = subdivide_step * subdivide_step;        double tmpx = (x1 - x2 * 2.0 + x3) * subdivide_step2;        double tmpy = (y1 - y2 * 2.0 + y3) * subdivide_step2;        m_saved_fx = m_fx = x1;        m_saved_fy = m_fy = y1;                m_saved_dfx = m_dfx = tmpx + (x2 - x1) * (2.0 * subdivide_step);        m_saved_dfy = m_dfy = tmpy + (y2 - y1) * (2.0 * subdivide_step);        m_ddfx = tmpx * 2.0;        m_ddfy = tmpy * 2.0;        m_step = m_num_steps;    }    //------------------------------------------------------------------------    void curve3_inc::rewind(unsigned)    {        if(m_num_steps == 0)        {            m_step = -1;            return;        }        m_step = m_num_steps;        m_fx   = m_saved_fx;        m_fy   = m_saved_fy;        m_dfx  = m_saved_dfx;        m_dfy  = m_saved_dfy;    }    //------------------------------------------------------------------------    unsigned curve3_inc::vertex(double* x, double* y)    {        if(m_step < 0) return path_cmd_stop;        if(m_step == m_num_steps)        {            *x = m_start_x;            *y = m_start_y;            --m_step;            return path_cmd_move_to;        }        if(m_step == 0)        {            *x = m_end_x;            *y = m_end_y;            --m_step;            return path_cmd_line_to;        }        m_fx  += m_dfx;         m_fy  += m_dfy;        m_dfx += m_ddfx;         m_dfy += m_ddfy;         *x = m_fx;        *y = m_fy;        --m_step;        return path_cmd_line_to;    }    //------------------------------------------------------------------------    void curve3_div::init(double x1, double y1,                           double x2, double y2,                           double x3, double y3)    {        m_points.remove_all();        m_distance_tolerance_square = 0.5 / m_approximation_scale;        m_distance_tolerance_square *= m_distance_tolerance_square;        m_distance_tolerance_manhattan = 4.0 / m_approximation_scale;        bezier(x1, y1, x2, y2, x3, y3);        m_count = 0;    }    //------------------------------------------------------------------------    void curve3_div::recursive_bezier(double x1, double y1,                                       double x2, double y2,                                       double x3, double y3,                                      unsigned level)    {        if(level > curve_recursion_limit)         {            return;        }        // Calculate all the mid-points of the line segments        //----------------------        double x12   = (x1 + x2) / 2;                        double y12   = (y1 + y2) / 2;        double x23   = (x2 + x3) / 2;        double y23   = (y2 + y3) / 2;        double x123  = (x12 + x23) / 2;        double y123  = (y12 + y23) / 2;        double dx = x3-x1;        double dy = y3-y1;        double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx));        if(d > curve_collinearity_epsilon)        {             // Regular care            //-----------------            if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy))            {                // If the curvature doesn't exceed the distance_tolerance value                // we tend to finish subdivisions.                //----------------------                if(m_angle_tolerance < curve_angle_tolerance_epsilon)                {                    m_points.add(point_d(x123, y123));                    return;                }                // Angle & Cusp Condition                //----------------------                double da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));                if(da >= pi) da = 2*pi - da;                if(da < m_angle_tolerance)                {                    // Finally we can stop the recursion                    //----------------------                    m_points.add(point_d(x123, y123));                    return;                                 }            }        }        else        {            if(fabs(x1 + x3 - x2 - x2) +               fabs(y1 + y3 - y2 - y2) <= m_distance_tolerance_manhattan)            {                m_points.add(point_d(x123, y123));                return;            }            }        // Continue subdivision        //----------------------        recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1);         recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1);     }    //------------------------------------------------------------------------    void curve3_div::bezier(double x1, double y1,                             double x2, double y2,                             double x3, double y3)    {        m_points.add(point_d(x1, y1));        recursive_bezier(x1, y1, x2, y2, x3, y3, 0);        m_points.add(point_d(x3, y3));    }    //------------------------------------------------------------------------    void curve4_inc::approximation_scale(double s)     {         m_scale = s;    }    //------------------------------------------------------------------------    double curve4_inc::approximation_scale() const     {         return m_scale;    }    //------------------------------------------------------------------------    static double MSC60_fix_ICE(double v) { return v; }    //------------------------------------------------------------------------    void curve4_inc::init(double x1, double y1,                           double x2, double y2,                           double x3, double y3,                          double x4, double y4)    {        m_start_x = x1;        m_start_y = y1;        m_end_x   = x4;        m_end_y   = y4;        double dx1 = x2 - x1;        double dy1 = y2 - y1;        double dx2 = x3 - x2;        double dy2 = y3 - y2;        double dx3 = x4 - x3;        double dy3 = y4 - y3;        double len = (sqrt(dx1 * dx1 + dy1 * dy1) +                       sqrt(dx2 * dx2 + dy2 * dy2) +                       sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale;#if defined(_MSC_VER) && _MSC_VER <= 1200        m_num_steps = uround(MSC60_fix_ICE(len));#else        m_num_steps = uround(len);#endif        if(m_num_steps < 4)        {            m_num_steps = 4;           }        double subdivide_step  = 1.0 / m_num_steps;        double subdivide_step2 = subdivide_step * subdivide_step;        double subdivide_step3 = subdivide_step * subdivide_step * subdivide_step;        double pre1 = 3.0 * subdivide_step;        double pre2 = 3.0 * subdivide_step2;        double pre4 = 6.0 * subdivide_step2;

⌨️ 快捷键说明

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