Anti-Grain Geometry - AGG (libagg)
2.5
|
00001 //---------------------------------------------------------------------------- 00002 // Anti-Grain Geometry (AGG) - Version 2.5 00003 // A high quality rendering engine for C++ 00004 // Copyright (C) 2002-2006 Maxim Shemanarev 00005 // Contact: mcseem@antigrain.com 00006 // mcseemagg@yahoo.com 00007 // http://antigrain.com 00008 // 00009 // AGG is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // AGG is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AGG; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00022 // MA 02110-1301, USA. 00023 //---------------------------------------------------------------------------- 00024 00025 #ifndef AGG_CURVES_INCLUDED 00026 #define AGG_CURVES_INCLUDED 00027 00028 #include "agg_array.h" 00029 00030 namespace agg 00031 { 00032 00033 // See Implementation agg_curves.cpp 00034 00035 //--------------------------------------------curve_approximation_method_e 00036 enum curve_approximation_method_e 00037 { 00038 curve_inc, 00039 curve_div 00040 }; 00041 00042 //--------------------------------------------------------------curve3_inc 00043 class curve3_inc 00044 { 00045 public: 00046 curve3_inc() : 00047 m_num_steps(0), m_step(0), m_scale(1.0) { } 00048 00049 curve3_inc(double x1, double y1, 00050 double x2, double y2, 00051 double x3, double y3) : 00052 m_num_steps(0), m_step(0), m_scale(1.0) 00053 { 00054 init(x1, y1, x2, y2, x3, y3); 00055 } 00056 00057 void reset() { m_num_steps = 0; m_step = -1; } 00058 void init(double x1, double y1, 00059 double x2, double y2, 00060 double x3, double y3); 00061 00062 void approximation_method(curve_approximation_method_e) {} 00063 curve_approximation_method_e approximation_method() const { return curve_inc; } 00064 00065 void approximation_scale(double s); 00066 double approximation_scale() const; 00067 00068 void angle_tolerance(double) {} 00069 double angle_tolerance() const { return 0.0; } 00070 00071 void cusp_limit(double) {} 00072 double cusp_limit() const { return 0.0; } 00073 00074 void rewind(unsigned path_id); 00075 unsigned vertex(double* x, double* y); 00076 00077 private: 00078 int m_num_steps; 00079 int m_step; 00080 double m_scale; 00081 double m_start_x; 00082 double m_start_y; 00083 double m_end_x; 00084 double m_end_y; 00085 double m_fx; 00086 double m_fy; 00087 double m_dfx; 00088 double m_dfy; 00089 double m_ddfx; 00090 double m_ddfy; 00091 double m_saved_fx; 00092 double m_saved_fy; 00093 double m_saved_dfx; 00094 double m_saved_dfy; 00095 }; 00096 00097 00098 00099 00100 00101 //-------------------------------------------------------------curve3_div 00102 class curve3_div 00103 { 00104 public: 00105 curve3_div() : 00106 m_approximation_scale(1.0), 00107 m_angle_tolerance(0.0), 00108 m_count(0) 00109 {} 00110 00111 curve3_div(double x1, double y1, 00112 double x2, double y2, 00113 double x3, double y3) : 00114 m_approximation_scale(1.0), 00115 m_angle_tolerance(0.0), 00116 m_count(0) 00117 { 00118 init(x1, y1, x2, y2, x3, y3); 00119 } 00120 00121 void reset() { m_points.remove_all(); m_count = 0; } 00122 void init(double x1, double y1, 00123 double x2, double y2, 00124 double x3, double y3); 00125 00126 void approximation_method(curve_approximation_method_e) {} 00127 curve_approximation_method_e approximation_method() const { return curve_div; } 00128 00129 void approximation_scale(double s) { m_approximation_scale = s; } 00130 double approximation_scale() const { return m_approximation_scale; } 00131 00132 void angle_tolerance(double a) { m_angle_tolerance = a; } 00133 double angle_tolerance() const { return m_angle_tolerance; } 00134 00135 void cusp_limit(double) {} 00136 double cusp_limit() const { return 0.0; } 00137 00138 void rewind(unsigned) 00139 { 00140 m_count = 0; 00141 } 00142 00143 unsigned vertex(double* x, double* y) 00144 { 00145 if(m_count >= m_points.size()) return path_cmd_stop; 00146 const point_d& p = m_points[m_count++]; 00147 *x = p.x; 00148 *y = p.y; 00149 return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; 00150 } 00151 00152 private: 00153 void bezier(double x1, double y1, 00154 double x2, double y2, 00155 double x3, double y3); 00156 void recursive_bezier(double x1, double y1, 00157 double x2, double y2, 00158 double x3, double y3, 00159 unsigned level); 00160 00161 double m_approximation_scale; 00162 double m_distance_tolerance_square; 00163 double m_angle_tolerance; 00164 unsigned m_count; 00165 pod_bvector<point_d> m_points; 00166 }; 00167 00168 00169 00170 00171 00172 00173 00174 //-------------------------------------------------------------curve4_points 00175 struct curve4_points 00176 { 00177 double cp[8]; 00178 curve4_points() {} 00179 curve4_points(double x1, double y1, 00180 double x2, double y2, 00181 double x3, double y3, 00182 double x4, double y4) 00183 { 00184 cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; 00185 cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; 00186 } 00187 void init(double x1, double y1, 00188 double x2, double y2, 00189 double x3, double y3, 00190 double x4, double y4) 00191 { 00192 cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; 00193 cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; 00194 } 00195 double operator [] (unsigned i) const { return cp[i]; } 00196 double& operator [] (unsigned i) { return cp[i]; } 00197 }; 00198 00199 00200 00201 //-------------------------------------------------------------curve4_inc 00202 class curve4_inc 00203 { 00204 public: 00205 curve4_inc() : 00206 m_num_steps(0), m_step(0), m_scale(1.0) { } 00207 00208 curve4_inc(double x1, double y1, 00209 double x2, double y2, 00210 double x3, double y3, 00211 double x4, double y4) : 00212 m_num_steps(0), m_step(0), m_scale(1.0) 00213 { 00214 init(x1, y1, x2, y2, x3, y3, x4, y4); 00215 } 00216 00217 curve4_inc(const curve4_points& cp) : 00218 m_num_steps(0), m_step(0), m_scale(1.0) 00219 { 00220 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); 00221 } 00222 00223 void reset() { m_num_steps = 0; m_step = -1; } 00224 void init(double x1, double y1, 00225 double x2, double y2, 00226 double x3, double y3, 00227 double x4, double y4); 00228 00229 void init(const curve4_points& cp) 00230 { 00231 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); 00232 } 00233 00234 void approximation_method(curve_approximation_method_e) {} 00235 curve_approximation_method_e approximation_method() const { return curve_inc; } 00236 00237 void approximation_scale(double s); 00238 double approximation_scale() const; 00239 00240 void angle_tolerance(double) {} 00241 double angle_tolerance() const { return 0.0; } 00242 00243 void cusp_limit(double) {} 00244 double cusp_limit() const { return 0.0; } 00245 00246 void rewind(unsigned path_id); 00247 unsigned vertex(double* x, double* y); 00248 00249 private: 00250 int m_num_steps; 00251 int m_step; 00252 double m_scale; 00253 double m_start_x; 00254 double m_start_y; 00255 double m_end_x; 00256 double m_end_y; 00257 double m_fx; 00258 double m_fy; 00259 double m_dfx; 00260 double m_dfy; 00261 double m_ddfx; 00262 double m_ddfy; 00263 double m_dddfx; 00264 double m_dddfy; 00265 double m_saved_fx; 00266 double m_saved_fy; 00267 double m_saved_dfx; 00268 double m_saved_dfy; 00269 double m_saved_ddfx; 00270 double m_saved_ddfy; 00271 }; 00272 00273 00274 00275 //-------------------------------------------------------catrom_to_bezier 00276 inline curve4_points catrom_to_bezier(double x1, double y1, 00277 double x2, double y2, 00278 double x3, double y3, 00279 double x4, double y4) 00280 { 00281 // Trans. matrix Catmull-Rom to Bezier 00282 // 00283 // 0 1 0 0 00284 // -1/6 1 1/6 0 00285 // 0 1/6 1 -1/6 00286 // 0 0 1 0 00287 // 00288 return curve4_points( 00289 x2, 00290 y2, 00291 (-x1 + 6*x2 + x3) / 6, 00292 (-y1 + 6*y2 + y3) / 6, 00293 ( x2 + 6*x3 - x4) / 6, 00294 ( y2 + 6*y3 - y4) / 6, 00295 x3, 00296 y3); 00297 } 00298 00299 00300 //----------------------------------------------------------------------- 00301 inline curve4_points 00302 catrom_to_bezier(const curve4_points& cp) 00303 { 00304 return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3], 00305 cp[4], cp[5], cp[6], cp[7]); 00306 } 00307 00308 00309 00310 //-----------------------------------------------------ubspline_to_bezier 00311 inline curve4_points ubspline_to_bezier(double x1, double y1, 00312 double x2, double y2, 00313 double x3, double y3, 00314 double x4, double y4) 00315 { 00316 // Trans. matrix Uniform BSpline to Bezier 00317 // 00318 // 1/6 4/6 1/6 0 00319 // 0 4/6 2/6 0 00320 // 0 2/6 4/6 0 00321 // 0 1/6 4/6 1/6 00322 // 00323 return curve4_points( 00324 (x1 + 4*x2 + x3) / 6, 00325 (y1 + 4*y2 + y3) / 6, 00326 (4*x2 + 2*x3) / 6, 00327 (4*y2 + 2*y3) / 6, 00328 (2*x2 + 4*x3) / 6, 00329 (2*y2 + 4*y3) / 6, 00330 (x2 + 4*x3 + x4) / 6, 00331 (y2 + 4*y3 + y4) / 6); 00332 } 00333 00334 00335 //----------------------------------------------------------------------- 00336 inline curve4_points 00337 ubspline_to_bezier(const curve4_points& cp) 00338 { 00339 return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3], 00340 cp[4], cp[5], cp[6], cp[7]); 00341 } 00342 00343 00344 00345 00346 //------------------------------------------------------hermite_to_bezier 00347 inline curve4_points hermite_to_bezier(double x1, double y1, 00348 double x2, double y2, 00349 double x3, double y3, 00350 double x4, double y4) 00351 { 00352 // Trans. matrix Hermite to Bezier 00353 // 00354 // 1 0 0 0 00355 // 1 0 1/3 0 00356 // 0 1 0 -1/3 00357 // 0 1 0 0 00358 // 00359 return curve4_points( 00360 x1, 00361 y1, 00362 (3*x1 + x3) / 3, 00363 (3*y1 + y3) / 3, 00364 (3*x2 - x4) / 3, 00365 (3*y2 - y4) / 3, 00366 x2, 00367 y2); 00368 } 00369 00370 00371 00372 //----------------------------------------------------------------------- 00373 inline curve4_points 00374 hermite_to_bezier(const curve4_points& cp) 00375 { 00376 return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3], 00377 cp[4], cp[5], cp[6], cp[7]); 00378 } 00379 00380 00381 //-------------------------------------------------------------curve4_div 00382 class curve4_div 00383 { 00384 public: 00385 curve4_div() : 00386 m_approximation_scale(1.0), 00387 m_angle_tolerance(0.0), 00388 m_cusp_limit(0.0), 00389 m_count(0) 00390 {} 00391 00392 curve4_div(double x1, double y1, 00393 double x2, double y2, 00394 double x3, double y3, 00395 double x4, double y4) : 00396 m_approximation_scale(1.0), 00397 m_angle_tolerance(0.0), 00398 m_cusp_limit(0.0), 00399 m_count(0) 00400 { 00401 init(x1, y1, x2, y2, x3, y3, x4, y4); 00402 } 00403 00404 curve4_div(const curve4_points& cp) : 00405 m_approximation_scale(1.0), 00406 m_angle_tolerance(0.0), 00407 m_count(0) 00408 { 00409 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); 00410 } 00411 00412 void reset() { m_points.remove_all(); m_count = 0; } 00413 void init(double x1, double y1, 00414 double x2, double y2, 00415 double x3, double y3, 00416 double x4, double y4); 00417 00418 void init(const curve4_points& cp) 00419 { 00420 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); 00421 } 00422 00423 void approximation_method(curve_approximation_method_e) {} 00424 00425 curve_approximation_method_e approximation_method() const 00426 { 00427 return curve_div; 00428 } 00429 00430 void approximation_scale(double s) { m_approximation_scale = s; } 00431 double approximation_scale() const { return m_approximation_scale; } 00432 00433 void angle_tolerance(double a) { m_angle_tolerance = a; } 00434 double angle_tolerance() const { return m_angle_tolerance; } 00435 00436 void cusp_limit(double v) 00437 { 00438 m_cusp_limit = (v == 0.0) ? 0.0 : pi - v; 00439 } 00440 00441 double cusp_limit() const 00442 { 00443 return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit; 00444 } 00445 00446 void rewind(unsigned) 00447 { 00448 m_count = 0; 00449 } 00450 00451 unsigned vertex(double* x, double* y) 00452 { 00453 if(m_count >= m_points.size()) return path_cmd_stop; 00454 const point_d& p = m_points[m_count++]; 00455 *x = p.x; 00456 *y = p.y; 00457 return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; 00458 } 00459 00460 private: 00461 void bezier(double x1, double y1, 00462 double x2, double y2, 00463 double x3, double y3, 00464 double x4, double y4); 00465 00466 void recursive_bezier(double x1, double y1, 00467 double x2, double y2, 00468 double x3, double y3, 00469 double x4, double y4, 00470 unsigned level); 00471 00472 double m_approximation_scale; 00473 double m_distance_tolerance_square; 00474 double m_angle_tolerance; 00475 double m_cusp_limit; 00476 unsigned m_count; 00477 pod_bvector<point_d> m_points; 00478 }; 00479 00480 00481 //-----------------------------------------------------------------curve3 00482 class curve3 00483 { 00484 public: 00485 curve3() : m_approximation_method(curve_div) {} 00486 curve3(double x1, double y1, 00487 double x2, double y2, 00488 double x3, double y3) : 00489 m_approximation_method(curve_div) 00490 { 00491 init(x1, y1, x2, y2, x3, y3); 00492 } 00493 00494 void reset() 00495 { 00496 m_curve_inc.reset(); 00497 m_curve_div.reset(); 00498 } 00499 00500 void init(double x1, double y1, 00501 double x2, double y2, 00502 double x3, double y3) 00503 { 00504 if(m_approximation_method == curve_inc) 00505 { 00506 m_curve_inc.init(x1, y1, x2, y2, x3, y3); 00507 } 00508 else 00509 { 00510 m_curve_div.init(x1, y1, x2, y2, x3, y3); 00511 } 00512 } 00513 00514 void approximation_method(curve_approximation_method_e v) 00515 { 00516 m_approximation_method = v; 00517 } 00518 00519 curve_approximation_method_e approximation_method() const 00520 { 00521 return m_approximation_method; 00522 } 00523 00524 void approximation_scale(double s) 00525 { 00526 m_curve_inc.approximation_scale(s); 00527 m_curve_div.approximation_scale(s); 00528 } 00529 00530 double approximation_scale() const 00531 { 00532 return m_curve_inc.approximation_scale(); 00533 } 00534 00535 void angle_tolerance(double a) 00536 { 00537 m_curve_div.angle_tolerance(a); 00538 } 00539 00540 double angle_tolerance() const 00541 { 00542 return m_curve_div.angle_tolerance(); 00543 } 00544 00545 void cusp_limit(double v) 00546 { 00547 m_curve_div.cusp_limit(v); 00548 } 00549 00550 double cusp_limit() const 00551 { 00552 return m_curve_div.cusp_limit(); 00553 } 00554 00555 void rewind(unsigned path_id) 00556 { 00557 if(m_approximation_method == curve_inc) 00558 { 00559 m_curve_inc.rewind(path_id); 00560 } 00561 else 00562 { 00563 m_curve_div.rewind(path_id); 00564 } 00565 } 00566 00567 unsigned vertex(double* x, double* y) 00568 { 00569 if(m_approximation_method == curve_inc) 00570 { 00571 return m_curve_inc.vertex(x, y); 00572 } 00573 return m_curve_div.vertex(x, y); 00574 } 00575 00576 private: 00577 curve3_inc m_curve_inc; 00578 curve3_div m_curve_div; 00579 curve_approximation_method_e m_approximation_method; 00580 }; 00581 00582 00583 00584 00585 00586 //-----------------------------------------------------------------curve4 00587 class curve4 00588 { 00589 public: 00590 curve4() : m_approximation_method(curve_div) {} 00591 curve4(double x1, double y1, 00592 double x2, double y2, 00593 double x3, double y3, 00594 double x4, double y4) : 00595 m_approximation_method(curve_div) 00596 { 00597 init(x1, y1, x2, y2, x3, y3, x4, y4); 00598 } 00599 00600 curve4(const curve4_points& cp) : 00601 m_approximation_method(curve_div) 00602 { 00603 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); 00604 } 00605 00606 void reset() 00607 { 00608 m_curve_inc.reset(); 00609 m_curve_div.reset(); 00610 } 00611 00612 void init(double x1, double y1, 00613 double x2, double y2, 00614 double x3, double y3, 00615 double x4, double y4) 00616 { 00617 if(m_approximation_method == curve_inc) 00618 { 00619 m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4); 00620 } 00621 else 00622 { 00623 m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4); 00624 } 00625 } 00626 00627 void init(const curve4_points& cp) 00628 { 00629 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); 00630 } 00631 00632 void approximation_method(curve_approximation_method_e v) 00633 { 00634 m_approximation_method = v; 00635 } 00636 00637 curve_approximation_method_e approximation_method() const 00638 { 00639 return m_approximation_method; 00640 } 00641 00642 void approximation_scale(double s) 00643 { 00644 m_curve_inc.approximation_scale(s); 00645 m_curve_div.approximation_scale(s); 00646 } 00647 double approximation_scale() const { return m_curve_inc.approximation_scale(); } 00648 00649 void angle_tolerance(double v) 00650 { 00651 m_curve_div.angle_tolerance(v); 00652 } 00653 00654 double angle_tolerance() const 00655 { 00656 return m_curve_div.angle_tolerance(); 00657 } 00658 00659 void cusp_limit(double v) 00660 { 00661 m_curve_div.cusp_limit(v); 00662 } 00663 00664 double cusp_limit() const 00665 { 00666 return m_curve_div.cusp_limit(); 00667 } 00668 00669 void rewind(unsigned path_id) 00670 { 00671 if(m_approximation_method == curve_inc) 00672 { 00673 m_curve_inc.rewind(path_id); 00674 } 00675 else 00676 { 00677 m_curve_div.rewind(path_id); 00678 } 00679 } 00680 00681 unsigned vertex(double* x, double* y) 00682 { 00683 if(m_approximation_method == curve_inc) 00684 { 00685 return m_curve_inc.vertex(x, y); 00686 } 00687 return m_curve_div.vertex(x, y); 00688 } 00689 00690 private: 00691 curve4_inc m_curve_inc; 00692 curve4_div m_curve_div; 00693 curve_approximation_method_e m_approximation_method; 00694 }; 00695 00696 00697 00698 00699 } 00700 00701 #endif