17 #include "agg_curves.h" 24 const double curve_distance_epsilon = 1e-30;
25 const double curve_collinearity_epsilon = 1e-30;
26 const double curve_angle_tolerance_epsilon = 0.01;
27 enum curve_recursion_limit_e { curve_recursion_limit = 32 };
32 void curve3_inc::approximation_scale(
double s)
38 double curve3_inc::approximation_scale()
const 44 void curve3_inc::init(
double x1,
double y1,
58 double len = std::sqrt(dx1 * dx1 + dy1 * dy1) + std::sqrt(dx2 * dx2 + dy2 * dy2);
60 m_num_steps = uround(len * 0.25 * m_scale);
67 double subdivide_step = 1.0 / m_num_steps;
68 double subdivide_step2 = subdivide_step * subdivide_step;
70 double tmpx = (x1 - x2 * 2.0 + x3) * subdivide_step2;
71 double tmpy = (y1 - y2 * 2.0 + y3) * subdivide_step2;
73 m_saved_fx = m_fx = x1;
74 m_saved_fy = m_fy = y1;
76 m_saved_dfx = m_dfx = tmpx + (x2 - x1) * (2.0 * subdivide_step);
77 m_saved_dfy = m_dfy = tmpy + (y2 - y1) * (2.0 * subdivide_step);
86 void curve3_inc::rewind(
unsigned)
101 unsigned curve3_inc::vertex(
double* x,
double* y)
103 if(m_step < 0)
return path_cmd_stop;
104 if(m_step == m_num_steps)
109 return path_cmd_move_to;
116 return path_cmd_line_to;
125 return path_cmd_line_to;
129 void curve3_div::init(
double x1,
double y1,
130 double x2,
double y2,
131 double x3,
double y3)
133 m_points.remove_all();
134 m_distance_tolerance_square = 0.5 / m_approximation_scale;
135 m_distance_tolerance_square *= m_distance_tolerance_square;
136 bezier(x1, y1, x2, y2, x3, y3);
141 void curve3_div::recursive_bezier(
double x1,
double y1,
142 double x2,
double y2,
143 double x3,
double y3,
146 if(level > curve_recursion_limit)
153 double x12 = (x1 + x2) / 2;
154 double y12 = (y1 + y2) / 2;
155 double x23 = (x2 + x3) / 2;
156 double y23 = (y2 + y3) / 2;
157 double x123 = (x12 + x23) / 2;
158 double y123 = (y12 + y23) / 2;
162 double d = std::fabs(((x2 - x3) * dy - (y2 - y3) * dx));
165 if(d > curve_collinearity_epsilon)
169 if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy))
174 if(m_angle_tolerance < curve_angle_tolerance_epsilon)
176 m_points.add(point_d(x123, y123));
182 da = std::fabs(std::atan2(y3 - y2, x3 - x2) - std::atan2(y2 - y1, x2 - x1));
183 if(da >= pi) da = 2*pi - da;
185 if(da < m_angle_tolerance)
189 m_points.add(point_d(x123, y123));
201 d = calc_sq_distance(x1, y1, x2, y2);
205 d = ((x2 - x1)*dx + (y2 - y1)*dy) / da;
212 if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1);
213 else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3);
214 else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy);
216 if(d < m_distance_tolerance_square)
218 m_points.add(point_d(x2, y2));
225 recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1);
226 recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1);
230 void curve3_div::bezier(
double x1,
double y1,
231 double x2,
double y2,
232 double x3,
double y3)
234 m_points.add(point_d(x1, y1));
235 recursive_bezier(x1, y1, x2, y2, x3, y3, 0);
236 m_points.add(point_d(x3, y3));
244 void curve4_inc::approximation_scale(
double s)
250 double curve4_inc::approximation_scale()
const 255 #if defined(_MSC_VER) && _MSC_VER <= 1200 257 static double MSC60_fix_ICE(
double v) {
return v; }
261 void curve4_inc::init(
double x1,
double y1,
262 double x2,
double y2,
263 double x3,
double y3,
264 double x4,
double y4)
271 double dx1 = x2 - x1;
272 double dy1 = y2 - y1;
273 double dx2 = x3 - x2;
274 double dy2 = y3 - y2;
275 double dx3 = x4 - x3;
276 double dy3 = y4 - y3;
278 double len = (std::sqrt(dx1 * dx1 + dy1 * dy1) +
279 std::sqrt(dx2 * dx2 + dy2 * dy2) +
280 std::sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale;
282 #if defined(_MSC_VER) && _MSC_VER <= 1200 283 m_num_steps = uround(MSC60_fix_ICE(len));
285 m_num_steps = uround(len);
293 double subdivide_step = 1.0 / m_num_steps;
294 double subdivide_step2 = subdivide_step * subdivide_step;
295 double subdivide_step3 = subdivide_step * subdivide_step * subdivide_step;
297 double pre1 = 3.0 * subdivide_step;
298 double pre2 = 3.0 * subdivide_step2;
299 double pre4 = 6.0 * subdivide_step2;
300 double pre5 = 6.0 * subdivide_step3;
302 double tmp1x = x1 - x2 * 2.0 + x3;
303 double tmp1y = y1 - y2 * 2.0 + y3;
305 double tmp2x = (x2 - x3) * 3.0 - x1 + x4;
306 double tmp2y = (y2 - y3) * 3.0 - y1 + y4;
308 m_saved_fx = m_fx = x1;
309 m_saved_fy = m_fy = y1;
311 m_saved_dfx = m_dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3;
312 m_saved_dfy = m_dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3;
314 m_saved_ddfx = m_ddfx = tmp1x * pre4 + tmp2x * pre5;
315 m_saved_ddfy = m_ddfy = tmp1y * pre4 + tmp2y * pre5;
317 m_dddfx = tmp2x * pre5;
318 m_dddfy = tmp2y * pre5;
320 m_step = m_num_steps;
324 void curve4_inc::rewind(
unsigned)
331 m_step = m_num_steps;
336 m_ddfx = m_saved_ddfx;
337 m_ddfy = m_saved_ddfy;
341 unsigned curve4_inc::vertex(
double* x,
double* y)
343 if(m_step < 0)
return path_cmd_stop;
344 if(m_step == m_num_steps)
349 return path_cmd_move_to;
357 return path_cmd_line_to;
370 return path_cmd_line_to;
377 void curve4_div::init(
double x1,
double y1,
378 double x2,
double y2,
379 double x3,
double y3,
380 double x4,
double y4)
382 m_points.remove_all();
383 m_distance_tolerance_square = 0.5 / m_approximation_scale;
384 m_distance_tolerance_square *= m_distance_tolerance_square;
385 bezier(x1, y1, x2, y2, x3, y3, x4, y4);
390 void curve4_div::recursive_bezier(
double x1,
double y1,
391 double x2,
double y2,
392 double x3,
double y3,
393 double x4,
double y4,
396 if(level > curve_recursion_limit)
403 double x12 = (x1 + x2) / 2;
404 double y12 = (y1 + y2) / 2;
405 double x23 = (x2 + x3) / 2;
406 double y23 = (y2 + y3) / 2;
407 double x34 = (x3 + x4) / 2;
408 double y34 = (y3 + y4) / 2;
409 double x123 = (x12 + x23) / 2;
410 double y123 = (y12 + y23) / 2;
411 double x234 = (x23 + x34) / 2;
412 double y234 = (y23 + y34) / 2;
413 double x1234 = (x123 + x234) / 2;
414 double y1234 = (y123 + y234) / 2;
422 double d2 = std::fabs(((x2 - x4) * dy - (y2 - y4) * dx));
423 double d3 = std::fabs(((x3 - x4) * dy - (y3 - y4) * dx));
426 switch((
int(d2 > curve_collinearity_epsilon) << 1) +
427 int(d3 > curve_collinearity_epsilon))
435 d2 = calc_sq_distance(x1, y1, x2, y2);
436 d3 = calc_sq_distance(x4, y4, x3, y3);
443 d2 = k * (da1*dx + da2*dy);
446 d3 = k * (da1*dx + da2*dy);
447 if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1)
453 if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1);
454 else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4);
455 else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy);
457 if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1);
458 else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4);
459 else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy);
463 if(d2 < m_distance_tolerance_square)
465 m_points.add(point_d(x2, y2));
471 if(d3 < m_distance_tolerance_square)
473 m_points.add(point_d(x3, y3));
482 if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy))
484 if(m_angle_tolerance < curve_angle_tolerance_epsilon)
486 m_points.add(point_d(x23, y23));
492 da1 = std::fabs(std::atan2(y4 - y3, x4 - x3) - std::atan2(y3 - y2, x3 - x2));
493 if(da1 >= pi) da1 = 2*pi - da1;
495 if(da1 < m_angle_tolerance)
497 m_points.add(point_d(x2, y2));
498 m_points.add(point_d(x3, y3));
502 if(m_cusp_limit != 0.0)
504 if(da1 > m_cusp_limit)
506 m_points.add(point_d(x3, y3));
516 if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy))
518 if(m_angle_tolerance < curve_angle_tolerance_epsilon)
520 m_points.add(point_d(x23, y23));
526 da1 = std::fabs(std::atan2(y3 - y2, x3 - x2) - std::atan2(y2 - y1, x2 - x1));
527 if(da1 >= pi) da1 = 2*pi - da1;
529 if(da1 < m_angle_tolerance)
531 m_points.add(point_d(x2, y2));
532 m_points.add(point_d(x3, y3));
536 if(m_cusp_limit != 0.0)
538 if(da1 > m_cusp_limit)
540 m_points.add(point_d(x2, y2));
550 if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy))
555 if(m_angle_tolerance < curve_angle_tolerance_epsilon)
557 m_points.add(point_d(x23, y23));
563 k = std::atan2(y3 - y2, x3 - x2);
564 da1 = std::fabs(k - std::atan2(y2 - y1, x2 - x1));
565 da2 = std::fabs(std::atan2(y4 - y3, x4 - x3) - k);
566 if(da1 >= pi) da1 = 2*pi - da1;
567 if(da2 >= pi) da2 = 2*pi - da2;
569 if(da1 + da2 < m_angle_tolerance)
573 m_points.add(point_d(x23, y23));
577 if(m_cusp_limit != 0.0)
579 if(da1 > m_cusp_limit)
581 m_points.add(point_d(x2, y2));
585 if(da2 > m_cusp_limit)
587 m_points.add(point_d(x3, y3));
597 recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
598 recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
602 void curve4_div::bezier(
double x1,
double y1,
603 double x2,
double y2,
604 double x3,
double y3,
605 double x4,
double y4)
607 m_points.add(point_d(x1, y1));
608 recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0);
609 m_points.add(point_d(x4, y4));