23 #include "agg_bezier_arc.h" 35 const double bezier_arc_angle_epsilon = 0.01;
38 void arc_to_bezier(
double cx,
double cy,
double rx,
double ry,
39 double start_angle,
double sweep_angle,
42 double x0 = std::cos(sweep_angle / 2.0);
43 double y0 = std::sin(sweep_angle / 2.0);
44 double tx = (1.0 - x0) * 4.0 / 3.0;
45 double ty = y0 - tx * x0 / y0;
57 double sn = std::sin(start_angle + sweep_angle / 2.0);
58 double cs = std::cos(start_angle + sweep_angle / 2.0);
61 for(i = 0; i < 4; i++)
63 curve[i * 2] = cx + rx * (px[i] * cs - py[i] * sn);
64 curve[i * 2 + 1] = cy + ry * (px[i] * sn + py[i] * cs);
71 void bezier_arc::init(
double x,
double y,
76 start_angle = std::fmod(start_angle, 2.0 * pi);
77 if(sweep_angle >= 2.0 * pi) sweep_angle = 2.0 * pi;
78 if(sweep_angle <= -2.0 * pi) sweep_angle = -2.0 * pi;
80 if(std::fabs(sweep_angle) < 1e-10)
83 m_cmd = path_cmd_line_to;
84 m_vertices[0] = x + rx * std::cos(start_angle);
85 m_vertices[1] = y + ry * std::sin(start_angle);
86 m_vertices[2] = x + rx * std::cos(start_angle + sweep_angle);
87 m_vertices[3] = y + ry * std::sin(start_angle + sweep_angle);
91 double total_sweep = 0.0;
92 double local_sweep = 0.0;
95 m_cmd = path_cmd_curve4;
101 prev_sweep = total_sweep;
102 local_sweep = -pi * 0.5;
103 total_sweep -= pi * 0.5;
104 if(total_sweep <= sweep_angle + bezier_arc_angle_epsilon)
106 local_sweep = sweep_angle - prev_sweep;
112 prev_sweep = total_sweep;
113 local_sweep = pi * 0.5;
114 total_sweep += pi * 0.5;
115 if(total_sweep >= sweep_angle - bezier_arc_angle_epsilon)
117 local_sweep = sweep_angle - prev_sweep;
122 arc_to_bezier(x, y, rx, ry,
125 m_vertices + m_num_vertices - 2);
128 start_angle += local_sweep;
130 while(!done && m_num_vertices < 26);
137 void bezier_arc_svg::init(
double x0,
double y0,
138 double rx,
double ry,
142 double x2,
double y2)
146 if(rx < 0.0) rx = -rx;
147 if(ry < 0.0) ry = -rx;
152 double dx2 = (x0 - x2) / 2.0;
153 double dy2 = (y0 - y2) / 2.0;
155 double cos_a = std::cos(angle);
156 double sin_a = std::sin(angle);
160 double x1 = cos_a * dx2 + sin_a * dy2;
161 double y1 = -sin_a * dx2 + cos_a * dy2;
165 double prx = rx * rx;
166 double pry = ry * ry;
167 double px1 = x1 * x1;
168 double py1 = y1 * y1;
172 double radii_check = px1/prx + py1/pry;
173 if(radii_check > 1.0)
175 rx = std::sqrt(radii_check) * rx;
176 ry = std::sqrt(radii_check) * ry;
179 if(radii_check > 10.0) m_radii_ok =
false;
184 double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0;
185 double sq = (prx*pry - prx*py1 - pry*px1) / (prx*py1 + pry*px1);
186 double coef = sign * std::sqrt((sq < 0) ? 0 : sq);
187 double cx1 = coef * ((rx * y1) / ry);
188 double cy1 = coef * -((ry * x1) / rx);
193 double sx2 = (x0 + x2) / 2.0;
194 double sy2 = (y0 + y2) / 2.0;
195 double cx = sx2 + (cos_a * cx1 - sin_a * cy1);
196 double cy = sy2 + (sin_a * cx1 + cos_a * cy1);
200 double ux = (x1 - cx1) / rx;
201 double uy = (y1 - cy1) / ry;
202 double vx = (-x1 - cx1) / rx;
203 double vy = (-y1 - cy1) / ry;
208 n = std::sqrt(ux*ux + uy*uy);
210 sign = (uy < 0) ? -1.0 : 1.0;
212 if(v < -1.0) v = -1.0;
214 double start_angle = sign * std::acos(v);
218 n = std::sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy));
219 p = ux * vx + uy * vy;
220 sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0;
222 if(v < -1.0) v = -1.0;
224 double sweep_angle = sign * std::acos(v);
225 if(!sweep_flag && sweep_angle > 0)
227 sweep_angle -= pi * 2.0;
230 if (sweep_flag && sweep_angle < 0)
232 sweep_angle += pi * 2.0;
237 m_arc.init(0.0, 0.0, rx, ry, start_angle, sweep_angle);
238 trans_affine mtx = trans_affine_rotation(angle);
239 mtx *= trans_affine_translation(cx, cy);
241 for(
unsigned i = 2; i < m_arc.num_vertices()-2; i += 2)
243 mtx.transform(m_arc.vertices() + i, m_arc.vertices() + i + 1);
248 m_arc.vertices()[0] = x0;
249 m_arc.vertices()[1] = y0;
250 if(m_arc.num_vertices() > 2)
252 m_arc.vertices()[m_arc.num_vertices() - 2] = x2;
253 m_arc.vertices()[m_arc.num_vertices() - 1] = y2;