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 + -
显示快捷键?