Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_curves.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines