ToolMap
Loading...
Searching...
No Matches
agg_curves.h
1//----------------------------------------------------------------------------
2// Anti-Grain Geometry (AGG) - Version 2.5
3// A high quality rendering engine for C++
4// Copyright (C) 2002-2006 Maxim Shemanarev
5// Contact: mcseem@antigrain.com
6// mcseemagg@yahoo.com
7// http://antigrain.com
8//
9// AGG is free software; you can redistribute it and/or
10// modify it under the terms of the GNU General Public License
11// as published by the Free Software Foundation; either version 2
12// of the License, or (at your option) any later version.
13//
14// AGG is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with AGG; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22// MA 02110-1301, USA.
23//----------------------------------------------------------------------------
24
25#ifndef AGG_CURVES_INCLUDED
26#define AGG_CURVES_INCLUDED
27
28#include "agg_array.h"
29
30namespace agg {
31AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2) {
32 double dx = x2 - x1;
33 double dy = y2 - y1;
34 return dx * dx + dy * dy;
35}
36
37// See Implementation agg_curves.cpp
38
39//--------------------------------------------curve_approximation_method_e
40enum curve_approximation_method_e {
41 curve_inc,
42 curve_div
43};
44
45//-------------------------------------------------------------curve4_points
47 double cp[8];
48
49 curve4_points() {}
50
51 curve4_points(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
52 cp[0] = x1;
53 cp[1] = y1;
54 cp[2] = x2;
55 cp[3] = y2;
56 cp[4] = x3;
57 cp[5] = y3;
58 cp[6] = x4;
59 cp[7] = y4;
60 }
61
62 void init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
63 cp[0] = x1;
64 cp[1] = y1;
65 cp[2] = x2;
66 cp[3] = y2;
67 cp[4] = x3;
68 cp[5] = y3;
69 cp[6] = x4;
70 cp[7] = y4;
71 }
72
73 double operator[](unsigned i) const {
74 return cp[i];
75 }
76
77 double& operator[](unsigned i) {
78 return cp[i];
79 }
80};
81
82//-------------------------------------------------------------curve4_inc
84 public:
86 : m_num_steps(0),
87 m_step(0),
88 m_scale(1.0),
89 m_start_x(0.0),
90 m_start_y(0.0),
91 m_end_x(0.0),
92 m_end_y(0.0),
93 m_fx(0.0),
94 m_fy(0.0),
95 m_dfx(0.0),
96 m_dfy(0.0),
97 m_ddfx(0.0),
98 m_ddfy(0.0),
99 m_dddfx(0.0),
100 m_dddfy(0.0),
101 m_saved_fx(0.0),
102 m_saved_fy(0.0),
103 m_saved_dfx(0.0),
104 m_saved_dfy(0.0),
105 m_saved_ddfx(0.0),
106 m_saved_ddfy(0.0) {}
107
108 curve4_inc(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
109 : m_num_steps(0),
110 m_step(0),
111 m_scale(1.0) {
112 init(x1, y1, x2, y2, x3, y3, x4, y4);
113 }
114
115 curve4_inc(const curve4_points& cp)
116 : m_num_steps(0),
117 m_step(0),
118 m_scale(1.0) {
119 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
120 }
121
122 void reset() {
123 m_num_steps = 0;
124 m_step = -1;
125 }
126
127 void init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4);
128
129 void init(const curve4_points& cp) {
130 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
131 }
132
133 void approximation_method(curve_approximation_method_e) {}
134
135 curve_approximation_method_e approximation_method() const {
136 return curve_inc;
137 }
138
139 void approximation_scale(double s);
140
141 double approximation_scale() const;
142
143 void angle_tolerance(double) {}
144
145 double angle_tolerance() const {
146 return 0.0;
147 }
148
149 void cusp_limit(double) {}
150
151 double cusp_limit() const {
152 return 0.0;
153 }
154
155 void rewind(unsigned path_id);
156
157 unsigned vertex(double* x, double* y);
158
159 private:
160 int m_num_steps;
161 int m_step;
162 double m_scale;
163 double m_start_x;
164 double m_start_y;
165 double m_end_x;
166 double m_end_y;
167 double m_fx;
168 double m_fy;
169 double m_dfx;
170 double m_dfy;
171 double m_ddfx;
172 double m_ddfy;
173 double m_dddfx;
174 double m_dddfy;
175 double m_saved_fx;
176 double m_saved_fy;
177 double m_saved_dfx;
178 double m_saved_dfy;
179 double m_saved_ddfx;
180 double m_saved_ddfy;
181};
182
183//-------------------------------------------------------catrom_to_bezier
184inline curve4_points catrom_to_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4,
185 double y4) {
186 // Trans. matrix Catmull-Rom to Bezier
187 //
188 // 0 1 0 0
189 // -1/6 1 1/6 0
190 // 0 1/6 1 -1/6
191 // 0 0 1 0
192 //
193 return curve4_points(x2, y2, (-x1 + 6 * x2 + x3) / 6, (-y1 + 6 * y2 + y3) / 6, (x2 + 6 * x3 - x4) / 6,
194 (y2 + 6 * y3 - y4) / 6, x3, y3);
195}
196
197//-----------------------------------------------------------------------
198inline curve4_points catrom_to_bezier(const curve4_points& cp) {
199 return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
200}
201
202//-----------------------------------------------------ubspline_to_bezier
203inline curve4_points ubspline_to_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4,
204 double y4) {
205 // Trans. matrix Uniform BSpline to Bezier
206 //
207 // 1/6 4/6 1/6 0
208 // 0 4/6 2/6 0
209 // 0 2/6 4/6 0
210 // 0 1/6 4/6 1/6
211 //
212 return curve4_points((x1 + 4 * x2 + x3) / 6, (y1 + 4 * y2 + y3) / 6, (4 * x2 + 2 * x3) / 6, (4 * y2 + 2 * y3) / 6,
213 (2 * x2 + 4 * x3) / 6, (2 * y2 + 4 * y3) / 6, (x2 + 4 * x3 + x4) / 6, (y2 + 4 * y3 + y4) / 6);
214}
215
216//-----------------------------------------------------------------------
217inline curve4_points ubspline_to_bezier(const curve4_points& cp) {
218 return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
219}
220
221//------------------------------------------------------hermite_to_bezier
222inline curve4_points hermite_to_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4,
223 double y4) {
224 // Trans. matrix Hermite to Bezier
225 //
226 // 1 0 0 0
227 // 1 0 1/3 0
228 // 0 1 0 -1/3
229 // 0 1 0 0
230 //
231 return curve4_points(x1, y1, (3 * x1 + x3) / 3, (3 * y1 + y3) / 3, (3 * x2 - x4) / 3, (3 * y2 - y4) / 3, x2, y2);
232}
233
234//-----------------------------------------------------------------------
235inline curve4_points hermite_to_bezier(const curve4_points& cp) {
236 return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
237}
238
239//-------------------------------------------------------------curve4_div
241 public:
242 curve4_div()
243 : m_approximation_scale(1.0),
244 m_distance_tolerance_square(0.0),
245 m_angle_tolerance(0.0),
246 m_cusp_limit(0.0),
247 m_count(0) {}
248
249 curve4_div(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
250 : m_approximation_scale(1.0),
251 m_distance_tolerance_square(0.0),
252 m_angle_tolerance(0.0),
253 m_cusp_limit(0.0),
254 m_count(0) {
255 init(x1, y1, x2, y2, x3, y3, x4, y4);
256 }
257
258 curve4_div(const curve4_points& cp)
259 : m_approximation_scale(1.0),
260 m_distance_tolerance_square(0.0),
261 m_angle_tolerance(0.0),
262 m_count(0) {
263 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
264 }
265
266 void reset() {
267 m_points.remove_all();
268 m_count = 0;
269 }
270
271 void init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4);
272
273 void init(const curve4_points& cp) {
274 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
275 }
276
277 void approximation_method(curve_approximation_method_e) {}
278
279 curve_approximation_method_e approximation_method() const {
280 return curve_div;
281 }
282
283 void approximation_scale(double s) {
284 m_approximation_scale = s;
285 }
286
287 double approximation_scale() const {
288 return m_approximation_scale;
289 }
290
291 void angle_tolerance(double a) {
292 m_angle_tolerance = a;
293 }
294
295 double angle_tolerance() const {
296 return m_angle_tolerance;
297 }
298
299 void cusp_limit(double v) {
300 m_cusp_limit = (v == 0.0) ? 0.0 : pi - v;
301 }
302
303 double cusp_limit() const {
304 return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit;
305 }
306
307 void rewind(unsigned) {
308 m_count = 0;
309 }
310
311 unsigned vertex(double* x, double* y) {
312 if (m_count >= m_points.size()) return path_cmd_stop;
313 const point_d& p = m_points[m_count++];
314 *x = p.x;
315 *y = p.y;
316 return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
317 }
318
319 private:
320 void bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4);
321
322 void recursive_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4,
323 unsigned level);
324
325 double m_approximation_scale;
326 double m_distance_tolerance_square;
327 double m_angle_tolerance;
328 double m_cusp_limit;
329 unsigned m_count;
330 pod_bvector<point_d> m_points;
331};
332
333//-----------------------------------------------------------------curve4
334class curve4 {
335 public:
336 curve4()
337 : m_approximation_method(curve_div) {}
338
339 curve4(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
340 : m_approximation_method(curve_div) {
341 init(x1, y1, x2, y2, x3, y3, x4, y4);
342 }
343
344 curve4(const curve4_points& cp)
345 : m_approximation_method(curve_div) {
346 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
347 }
348
349 void reset() {
350 m_curve_inc.reset();
351 m_curve_div.reset();
352 }
353
354 void init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
355 if (m_approximation_method == curve_inc) {
356 m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4);
357 } else {
358 m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4);
359 }
360 }
361
362 void init(const curve4_points& cp) {
363 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
364 }
365
366 void approximation_method(curve_approximation_method_e v) {
367 m_approximation_method = v;
368 }
369
370 curve_approximation_method_e approximation_method() const {
371 return m_approximation_method;
372 }
373
374 void approximation_scale(double s) {
375 m_curve_inc.approximation_scale(s);
376 m_curve_div.approximation_scale(s);
377 }
378
379 double approximation_scale() const {
380 return m_curve_inc.approximation_scale();
381 }
382
383 void angle_tolerance(double v) {
384 m_curve_div.angle_tolerance(v);
385 }
386
387 double angle_tolerance() const {
388 return m_curve_div.angle_tolerance();
389 }
390
391 void cusp_limit(double v) {
392 m_curve_div.cusp_limit(v);
393 }
394
395 double cusp_limit() const {
396 return m_curve_div.cusp_limit();
397 }
398
399 void rewind(unsigned path_id) {
400 if (m_approximation_method == curve_inc) {
401 m_curve_inc.rewind(path_id);
402 } else {
403 m_curve_div.rewind(path_id);
404 }
405 }
406
407 unsigned vertex(double* x, double* y) {
408 if (m_approximation_method == curve_inc) {
409 return m_curve_inc.vertex(x, y);
410 }
411 return m_curve_div.vertex(x, y);
412 }
413
414 private:
415 curve4_inc m_curve_inc;
416 curve4_div m_curve_div;
417 curve_approximation_method_e m_approximation_method;
418};
419} // namespace agg
420
421#endif
Definition agg_curves.h:240
Definition agg_curves.h:83
Definition agg_curves.h:334
Definition agg_array.h:259
Definition agg_curves.h:46