agg_curves.cpp
来自「这是VCF框架的代码」· C++ 代码 · 共 572 行 · 第 1/2 页
CPP
572 行
double pre5 = 6.0 * subdivide_step3; double tmp1x = x1 - x2 * 2.0 + x3; double tmp1y = y1 - y2 * 2.0 + y3; double tmp2x = (x2 - x3) * 3.0 - x1 + x4; double tmp2y = (y2 - y3) * 3.0 - y1 + y4; m_saved_fx = m_fx = x1; m_saved_fy = m_fy = y1; m_saved_dfx = m_dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3; m_saved_dfy = m_dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3; m_saved_ddfx = m_ddfx = tmp1x * pre4 + tmp2x * pre5; m_saved_ddfy = m_ddfy = tmp1y * pre4 + tmp2y * pre5; m_dddfx = tmp2x * pre5; m_dddfy = tmp2y * pre5; m_step = m_num_steps; } //------------------------------------------------------------------------ void curve4_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; m_ddfx = m_saved_ddfx; m_ddfy = m_saved_ddfy; } //------------------------------------------------------------------------ unsigned curve4_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; m_ddfx += m_dddfx; m_ddfy += m_dddfy; *x = m_fx; *y = m_fy; --m_step; return path_cmd_line_to; } //------------------------------------------------------------------------ void curve4_div::init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { 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, x4, y4); m_count = 0; } //------------------------------------------------------------------------ void curve4_div::recursive_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, 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 x34 = (x3 + x4) / 2; double y34 = (y3 + y4) / 2; double x123 = (x12 + x23) / 2; double y123 = (y12 + y23) / 2; double x234 = (x23 + x34) / 2; double y234 = (y23 + y34) / 2; double x1234 = (x123 + x234) / 2; double y1234 = (y123 + y234) / 2; // Try to approximate the full cubic curve by a single straight line //------------------ double dx = x4-x1; double dy = y4-y1; double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx)); double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx)); double da1, da2; switch((int(d2 > curve_collinearity_epsilon) << 1) + int(d3 > curve_collinearity_epsilon)) { case 0: // All collinear OR p1==p4 //---------------------- if(fabs(x1 + x3 - x2 - x2) + fabs(y1 + y3 - y2 - y2) + fabs(x2 + x4 - x3 - x3) + fabs(y2 + y4 - y3 - y3) <= m_distance_tolerance_manhattan) { m_points.add(point_d(x1234, y1234)); return; } break; case 1: // p1,p2,p4 are collinear, p3 is considerable //---------------------- if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) { if(m_angle_tolerance < curve_angle_tolerance_epsilon) { m_points.add(point_d(x23, y23)); return; } // Angle Condition //---------------------- da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2)); if(da1 >= pi) da1 = 2*pi - da1; if(da1 < m_angle_tolerance) { m_points.add(point_d(x2, y2)); m_points.add(point_d(x3, y3)); return; } if(m_cusp_limit != 0.0) { if(da1 > m_cusp_limit) { m_points.add(point_d(x3, y3)); return; } } } break; case 2: // p1,p3,p4 are collinear, p2 is considerable //---------------------- if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) { if(m_angle_tolerance < curve_angle_tolerance_epsilon) { m_points.add(point_d(x23, y23)); return; } // Angle Condition //---------------------- da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); if(da1 >= pi) da1 = 2*pi - da1; if(da1 < m_angle_tolerance) { m_points.add(point_d(x2, y2)); m_points.add(point_d(x3, y3)); return; } if(m_cusp_limit != 0.0) { if(da1 > m_cusp_limit) { m_points.add(point_d(x2, y2)); return; } } } break; case 3: // Regular care //----------------- if((d2 + d3)*(d2 + d3) <= 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(x23, y23)); return; } // Angle & Cusp Condition //---------------------- double a23 = atan2(y3 - y2, x3 - x2); da1 = fabs(a23 - atan2(y2 - y1, x2 - x1)); da2 = fabs(atan2(y4 - y3, x4 - x3) - a23); if(da1 >= pi) da1 = 2*pi - da1; if(da2 >= pi) da2 = 2*pi - da2; if(da1 + da2 < m_angle_tolerance) { // Finally we can stop the recursion //---------------------- m_points.add(point_d(x23, y23)); return; } if(m_cusp_limit != 0.0) { if(da1 > m_cusp_limit) { m_points.add(point_d(x2, y2)); return; } if(da2 > m_cusp_limit) { m_points.add(point_d(x3, y3)); return; } } } break; } // Continue subdivision //---------------------- recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1); recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1); } //------------------------------------------------------------------------ void curve4_div::bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { m_points.add(point_d(x1, y1)); recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0); m_points.add(point_d(x4, y4)); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?