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_VERTEX_SEQUENCE_INCLUDED 00026 #define AGG_VERTEX_SEQUENCE_INCLUDED 00027 00028 #include "agg_basics.h" 00029 #include "agg_array.h" 00030 #include "agg_math.h" 00031 00032 namespace agg 00033 { 00034 00035 //----------------------------------------------------------vertex_sequence 00036 // Modified agg::pod_bvector. The data is interpreted as a sequence 00037 // of vertices. It means that the type T must expose: 00038 // 00039 // bool T::operator() (const T& val) 00040 // 00041 // that is called every time new vertex is being added. The main purpose 00042 // of this operator is the possibility to calculate some values during 00043 // adding and to return true if the vertex fits some criteria or false if 00044 // it doesn't. In the last case the new vertex is not added. 00045 // 00046 // The simple example is filtering coinciding vertices with calculation 00047 // of the distance between the current and previous ones: 00048 // 00049 // struct vertex_dist 00050 // { 00051 // double x; 00052 // double y; 00053 // double dist; 00054 // 00055 // vertex_dist() {} 00056 // vertex_dist(double x_, double y_) : 00057 // x(x_), 00058 // y(y_), 00059 // dist(0.0) 00060 // { 00061 // } 00062 // 00063 // bool operator () (const vertex_dist& val) 00064 // { 00065 // return (dist = calc_distance(x, y, val.x, val.y)) > EPSILON; 00066 // } 00067 // }; 00068 // 00069 // Function close() calls this operator and removes the last vertex if 00070 // necessary. 00071 //------------------------------------------------------------------------ 00072 template<class T, unsigned S=6> 00073 class vertex_sequence : public pod_bvector<T, S> 00074 { 00075 public: 00076 typedef pod_bvector<T, S> base_type; 00077 00078 void add(const T& val); 00079 void modify_last(const T& val); 00080 void close(bool remove_flag); 00081 }; 00082 00083 00084 00085 //------------------------------------------------------------------------ 00086 template<class T, unsigned S> 00087 void vertex_sequence<T, S>::add(const T& val) 00088 { 00089 if(base_type::size() > 1) 00090 { 00091 if(!(*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) 00092 { 00093 base_type::remove_last(); 00094 } 00095 } 00096 base_type::add(val); 00097 } 00098 00099 00100 //------------------------------------------------------------------------ 00101 template<class T, unsigned S> 00102 void vertex_sequence<T, S>::modify_last(const T& val) 00103 { 00104 base_type::remove_last(); 00105 add(val); 00106 } 00107 00108 00109 00110 //------------------------------------------------------------------------ 00111 template<class T, unsigned S> 00112 void vertex_sequence<T, S>::close(bool closed) 00113 { 00114 while(base_type::size() > 1) 00115 { 00116 if((*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) break; 00117 T t = (*this)[base_type::size() - 1]; 00118 base_type::remove_last(); 00119 modify_last(t); 00120 } 00121 00122 if(closed) 00123 { 00124 while(base_type::size() > 1) 00125 { 00126 if((*this)[base_type::size() - 1]((*this)[0])) break; 00127 base_type::remove_last(); 00128 } 00129 } 00130 } 00131 00132 00133 //-------------------------------------------------------------vertex_dist 00134 // Vertex (x, y) with the distance to the next one. The last vertex has 00135 // distance between the last and the first points if the polygon is closed 00136 // and 0.0 if it's a polyline. 00137 struct vertex_dist 00138 { 00139 double x; 00140 double y; 00141 double dist; 00142 00143 vertex_dist() {} 00144 vertex_dist(double x_, double y_) : 00145 x(x_), 00146 y(y_), 00147 dist(0.0) 00148 { 00149 } 00150 00151 bool operator () (const vertex_dist& val) 00152 { 00153 bool ret = (dist = calc_distance(x, y, val.x, val.y)) > vertex_dist_epsilon; 00154 if(!ret) dist = 1.0 / vertex_dist_epsilon; 00155 return ret; 00156 } 00157 }; 00158 00159 00160 00161 //--------------------------------------------------------vertex_dist_cmd 00162 // Save as the above but with additional "command" value 00163 struct vertex_dist_cmd : public vertex_dist 00164 { 00165 unsigned cmd; 00166 00167 vertex_dist_cmd() {} 00168 vertex_dist_cmd(double x_, double y_, unsigned cmd_) : 00169 vertex_dist(x_, y_), 00170 cmd(cmd_) 00171 { 00172 } 00173 }; 00174 00175 00176 } 00177 00178 #endif