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> 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> 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> 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 137 vertex_dist() {} 138 vertex_dist(double x_, double y_) : 139 x(x_), 140 y(y_), 141 dist(0.0) 142 { 143 } 144 145 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 161 vertex_dist_cmd() {} 162 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