1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 //          mcseemagg@yahoo.com
13 //          http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // vertex_sequence container and vertex_dist struct
17 //
18 //----------------------------------------------------------------------------
19 #ifndef AGG_VERTEX_SEQUENCE_INCLUDED
20 #define AGG_VERTEX_SEQUENCE_INCLUDED
21 
22 #include "agg_basics.h"
23 #include "agg_array.h"
24 #include "agg_math.h"
25 
26 namespace agg
27 {
28 
29     //----------------------------------------------------------vertex_sequence
30     // Modified agg::pod_bvector. The data is interpreted as a sequence
31     // of vertices. It means that the type T must expose:
32     //
33     // bool T::operator() (const T& val)
34     //
35     // that is called every time new vertex is being added. The main purpose
36     // of this operator is the possibility to calculate some values during
37     // adding and to return true if the vertex fits some criteria or false if
38     // it doesn't. In the last case the new vertex is not added.
39     //
40     // The simple example is filtering coinciding vertices with calculation
41     // of the distance between the current and previous ones:
42     //
43     //    struct vertex_dist
44     //    {
45     //        double   x;
46     //        double   y;
47     //        double   dist;
48     //
49     //        vertex_dist() {}
50     //        vertex_dist(double x_, double y_) :
51     //            x(x_),
52     //            y(y_),
53     //            dist(0.0)
54     //        {
55     //        }
56     //
57     //        bool operator () (const vertex_dist& val)
58     //        {
59     //            return (dist = calc_distance(x, y, val.x, val.y)) > EPSILON;
60     //        }
61     //    };
62     //
63     // Function close() calls this operator and removes the last vertex if
64     // necessary.
65     //------------------------------------------------------------------------
66     template<class T, unsigned S=6>
67     class vertex_sequence : public pod_bvector<T, S>
68     {
69     public:
70         typedef pod_bvector<T, S> base_type;
71 
72         void add(const T& val);
73         void modify_last(const T& val);
74         void close(bool remove_flag);
75     };
76 
77 
78 
79     //------------------------------------------------------------------------
80     template<class T, unsigned S>
add(const T & val)81     void vertex_sequence<T, S>::add(const T& val)
82     {
83         if(base_type::size() > 1)
84         {
85             if(!(*this)[base_type::size() - 2]((*this)[base_type::size() - 1]))
86             {
87                 base_type::remove_last();
88             }
89         }
90         base_type::add(val);
91     }
92 
93 
94     //------------------------------------------------------------------------
95     template<class T, unsigned S>
modify_last(const T & val)96     void vertex_sequence<T, S>::modify_last(const T& val)
97     {
98         base_type::remove_last();
99         add(val);
100     }
101 
102 
103 
104     //------------------------------------------------------------------------
105     template<class T, unsigned S>
close(bool closed)106     void vertex_sequence<T, S>::close(bool closed)
107     {
108         while(base_type::size() > 1)
109         {
110             if((*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) break;
111             T t = (*this)[base_type::size() - 1];
112             base_type::remove_last();
113             modify_last(t);
114         }
115 
116         if(closed)
117         {
118             while(base_type::size() > 1)
119             {
120                 if((*this)[base_type::size() - 1]((*this)[0])) break;
121                 base_type::remove_last();
122             }
123         }
124     }
125 
126 
127     //-------------------------------------------------------------vertex_dist
128     // Vertex (x, y) with the distance to the next one. The last vertex has
129     // distance between the last and the first points if the polygon is closed
130     // and 0.0 if it's a polyline.
131     struct vertex_dist
132     {
133         double   x;
134         double   y;
135         double   dist;
136 
vertex_distvertex_dist137         vertex_dist() {}
vertex_distvertex_dist138         vertex_dist(double x_, double y_) :
139             x(x_),
140             y(y_),
141             dist(0.0)
142         {
143         }
144 
operatorvertex_dist145         bool operator () (const vertex_dist& val)
146         {
147             bool ret = (dist = calc_distance(x, y, val.x, val.y)) > vertex_dist_epsilon;
148             if(!ret) dist = 1.0 / vertex_dist_epsilon;
149             return ret;
150         }
151     };
152 
153 
154 
155     //--------------------------------------------------------vertex_dist_cmd
156     // Save as the above but with additional "command" value
157     struct vertex_dist_cmd : public vertex_dist
158     {
159         unsigned cmd;
160 
vertex_dist_cmdvertex_dist_cmd161         vertex_dist_cmd() {}
vertex_dist_cmdvertex_dist_cmd162         vertex_dist_cmd(double x_, double y_, unsigned cmd_) :
163             vertex_dist(x_, y_),
164             cmd(cmd_)
165         {
166         }
167     };
168 
169 
170 }
171 
172 #endif
173