20 #ifndef AGG_STROKE_MATH_INCLUDED 21 #define AGG_STROKE_MATH_INCLUDED 24 #include "agg_vertex_sequence.h" 40 miter_join_revert = 1,
60 typedef typename VertexConsumer::value_type coord_type;
64 void line_cap(line_cap_e lc) { m_line_cap = lc; }
65 void line_join(line_join_e lj) { m_line_join = lj; }
66 void inner_join(inner_join_e ij) { m_inner_join = ij; }
68 line_cap_e line_cap()
const {
return m_line_cap; }
69 line_join_e line_join()
const {
return m_line_join; }
70 inner_join_e inner_join()
const {
return m_inner_join; }
73 void miter_limit(
double ml) { m_miter_limit = ml; }
74 void miter_limit_theta(
double t);
75 void inner_miter_limit(
double ml) { m_inner_miter_limit = ml; }
76 void approximation_scale(
double as) { m_approx_scale = as; }
78 double width()
const {
return m_width * 2.0; }
79 double miter_limit()
const {
return m_miter_limit; }
80 double inner_miter_limit()
const {
return m_inner_miter_limit; }
81 double approximation_scale()
const {
return m_approx_scale; }
83 void calc_cap(VertexConsumer& vc,
88 void calc_join(VertexConsumer& vc,
96 AGG_INLINE
void add_vertex(VertexConsumer& vc,
double x,
double y)
98 vc.add(coord_type(x, y));
101 void calc_arc(VertexConsumer& vc,
103 double dx1,
double dy1,
104 double dx2,
double dy2);
106 void calc_miter(VertexConsumer& vc,
110 double dx1,
double dy1,
111 double dx2,
double dy2,
120 double m_miter_limit;
121 double m_inner_miter_limit;
122 double m_approx_scale;
123 line_cap_e m_line_cap;
124 line_join_e m_line_join;
125 inner_join_e m_inner_join;
132 m_width_eps(0.5/1024.0),
135 m_inner_miter_limit(1.01),
137 m_line_cap(butt_cap),
138 m_line_join(miter_join),
139 m_inner_join(inner_miter)
149 m_width_abs = -m_width;
154 m_width_abs = m_width;
157 m_width_eps = m_width / 1024.0;
163 m_miter_limit = 1.0 / std::sin(t * 0.5) ;
170 double dx1,
double dy1,
171 double dx2,
double dy2)
173 double a1 = std::atan2(dy1 * m_width_sign, dx1 * m_width_sign);
174 double a2 = std::atan2(dy2 * m_width_sign, dx2 * m_width_sign);
178 da = std::acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
180 add_vertex(vc, x + dx1, y + dy1);
183 if(a1 > a2) a2 += 2 * pi;
184 n = int((a2 - a1) / da);
185 da = (a2 - a1) / (n + 1);
187 for(i = 0; i < n; i++)
189 add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
195 if(a1 < a2) a2 -= 2 * pi;
196 n = int((a1 - a2) / da);
197 da = (a1 - a2) / (n + 1);
199 for(i = 0; i < n; i++)
201 add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
205 add_vertex(vc, x + dx2, y + dy2);
214 double dx1,
double dy1,
215 double dx2,
double dy2,
223 double lim = m_width_abs * mlimit;
224 bool miter_limit_exceeded =
true;
225 bool intersection_failed =
true;
227 if(calc_intersection(v0.x + dx1, v0.y - dy1,
228 v1.x + dx1, v1.y - dy1,
229 v1.x + dx2, v1.y - dy2,
230 v2.x + dx2, v2.y - dy2,
235 di = calc_distance(v1.x, v1.y, xi, yi);
240 add_vertex(vc, xi, yi);
241 miter_limit_exceeded =
false;
243 intersection_failed =
false;
255 double x2 = v1.x + dx1;
256 double y2 = v1.y - dy1;
257 if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
258 (cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
263 add_vertex(vc, v1.x + dx1, v1.y - dy1);
264 miter_limit_exceeded =
false;
268 if(miter_limit_exceeded)
274 case miter_join_revert:
279 add_vertex(vc, v1.x + dx1, v1.y - dy1);
280 add_vertex(vc, v1.x + dx2, v1.y - dy2);
283 case miter_join_round:
284 calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
290 if(intersection_failed)
292 mlimit *= m_width_sign;
293 add_vertex(vc, v1.x + dx1 + dy1 * mlimit,
294 v1.y - dy1 + dx1 * mlimit);
295 add_vertex(vc, v1.x + dx2 - dy2 * mlimit,
296 v1.y - dy2 - dx2 * mlimit);
300 double x1 = v1.x + dx1;
301 double y1 = v1.y - dy1;
302 double x2 = v1.x + dx2;
303 double y2 = v1.y - dy2;
304 di = (lim - dbevel) / (di - dbevel);
305 add_vertex(vc, x1 + (xi - x1) * di,
306 y1 + (yi - y1) * di);
307 add_vertex(vc, x2 + (xi - x2) * di,
308 y2 + (yi - y2) * di);
324 double dx1 = (v1.y - v0.y) / len;
325 double dy1 = (v1.x - v0.x) / len;
332 if(m_line_cap != round_cap)
334 if(m_line_cap == square_cap)
336 dx2 = dy1 * m_width_sign;
337 dy2 = dx1 * m_width_sign;
339 add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2);
340 add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2);
344 double da = std::acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
347 int n = int(pi / da);
350 add_vertex(vc, v0.x - dx1, v0.y + dy1);
353 a1 = std::atan2(dy1, -dx1);
355 for(i = 0; i < n; i++)
357 add_vertex(vc, v0.x + std::cos(a1) * m_width,
358 v0.y + std::sin(a1) * m_width);
364 a1 = std::atan2(-dy1, dx1);
366 for(i = 0; i < n; i++)
368 add_vertex(vc, v0.x + std::cos(a1) * m_width,
369 v0.y + std::sin(a1) * m_width);
373 add_vertex(vc, v0.x + dx1, v0.y - dy1);
386 double dx1 = m_width * (v1.y - v0.y) / len1;
387 double dy1 = m_width * (v1.x - v0.x) / len1;
388 double dx2 = m_width * (v2.y - v1.y) / len2;
389 double dy2 = m_width * (v2.x - v1.x) / len2;
393 double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
394 if(cp != 0 && (cp > 0) == (m_width > 0))
398 double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
399 if(limit < m_inner_miter_limit)
401 limit = m_inner_miter_limit;
407 add_vertex(vc, v1.x + dx1, v1.y - dy1);
408 add_vertex(vc, v1.x + dx2, v1.y - dy2);
413 v0, v1, v2, dx1, dy1, dx2, dy2,
420 cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
421 if(cp < len1 * len1 && cp < len2 * len2)
424 v0, v1, v2, dx1, dy1, dx2, dy2,
430 if(m_inner_join == inner_jag)
432 add_vertex(vc, v1.x + dx1, v1.y - dy1);
433 add_vertex(vc, v1.x, v1.y );
434 add_vertex(vc, v1.x + dx2, v1.y - dy2);
438 add_vertex(vc, v1.x + dx1, v1.y - dy1);
439 add_vertex(vc, v1.x, v1.y );
440 calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1);
441 add_vertex(vc, v1.x, v1.y );
442 add_vertex(vc, v1.x + dx2, v1.y - dy2);
456 double dx = (dx1 + dx2) / 2;
457 double dy = (dy1 + dy2) / 2;
458 double dbevel = std::sqrt(dx * dx + dy * dy);
460 if(m_line_join == round_join || m_line_join == bevel_join)
479 if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
481 if(calc_intersection(v0.x + dx1, v0.y - dy1,
482 v1.x + dx1, v1.y - dy1,
483 v1.x + dx2, v1.y - dy2,
484 v2.x + dx2, v2.y - dy2,
487 add_vertex(vc, dx, dy);
491 add_vertex(vc, v1.x + dx1, v1.y - dy1);
500 case miter_join_revert:
501 case miter_join_round:
503 v0, v1, v2, dx1, dy1, dx2, dy2,
510 calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
514 add_vertex(vc, v1.x + dx1, v1.y - dy1);
515 add_vertex(vc, v1.x + dx2, v1.y - dy2);