BALL
1.4.1
|
00001 // -*- Mode: C++; tab-width: 2; -*- 00002 // vi: set ts=2: 00003 // 00004 00005 #ifndef BALL_DATATYPE_CONTOURLINE_H 00006 #define BALL_DATATYPE_CONTOURLINE_H 00007 00008 #ifndef BALL_COMMON_H 00009 # include <BALL/common.h> 00010 #endif 00011 00012 #ifndef BALL_DATATYPE_REGULARDATA2D_H 00013 # include <BALL/DATATYPE/regularData2D.h> 00014 #endif 00015 00016 #include <vector> 00017 00018 namespace BALL 00019 { 00020 // First I define some macros needed for the marching cube-algorithm. 00021 // The names come from the number associated with the different corners of the square. 00022 #define INTERPOL12 { \ 00023 vec = from.getCoordinates(from.getClosestIndex(Vector2(act_cell_x, act_cell_y)));\ 00024 d1 = from[act_cell_x + act_cell_y*(number_of_cells_x+1)];\ 00025 d2 = from[act_cell_x + 1 + act_cell_y*(number_of_cells_x+1)];\ 00026 vec2 = from.getCoordinates(from.getClosestIndex(Vector2(act_cell_x + 1, act_cell_y + 1)));\ 00027 slope = (d2 - d1) / (vec2.x - vec.x);\ 00028 vec.x += (threshold - d1)/slope;\ 00029 data_.push_back(vec);\ 00030 } 00031 00032 #define INTERPOL18 { \ 00033 vec = from.getCoordinates(from.getClosestIndex(Vector2(act_cell_x, act_cell_y)));\ 00034 d1 = from[act_cell_x + act_cell_y*(number_of_cells_x+1)];\ 00035 d2 = from[act_cell_x + (act_cell_y+1)*(number_of_cells_x+1)];\ 00036 vec2 = from.getCoordinates(from.getClosestIndex(Vector2(act_cell_x, act_cell_y+1)));\ 00037 slope = (d2 - d1) / (vec2.y - vec.y);\ 00038 vec.y += (threshold - d1)/slope;\ 00039 data_.push_back(vec);\ 00040 } 00041 00042 #define INTERPOL24 { \ 00043 vec = from.getCoordinates(from.getClosestIndex(Vector2(act_cell_x+1, act_cell_y)));\ 00044 d1 = from[act_cell_x+1 + act_cell_y*(number_of_cells_x+1)];\ 00045 d2 = from[act_cell_x+1 + (act_cell_y+1)*(number_of_cells_x+1)];\ 00046 vec2 = from.getCoordinates(from.getClosestIndex(Vector2(act_cell_x+1, act_cell_y+1)));\ 00047 slope = (d2 - d1) / (vec2.y - vec.y);\ 00048 vec.y += (threshold - d1)/slope;\ 00049 data_.push_back(vec);\ 00050 } 00051 00052 // is it vec.x += or vec.y += ...? 00053 #define INTERPOL48 { \ 00054 vec = from.getCoordinates(from.getClosestIndex(Vector2(act_cell_x+1, act_cell_y+1)));\ 00055 d1 = from[act_cell_x+1 + (act_cell_y+2)*(number_of_cells_x+1)];\ 00056 d2 = from[act_cell_x + (act_cell_y+1)*(number_of_cells_x+1)];\ 00057 vec2 = from.getCoordinates(from.getClosestIndex(Vector2(act_cell_x, act_cell_y+1)));\ 00058 slope = (d2 - d1) / (vec2.x - vec.x);\ 00059 vec.x += (threshold - d1)/slope;\ 00060 data_.push_back(vec);\ 00061 } 00062 00063 00067 template <typename T> 00068 class TContourLine 00069 { 00070 public: 00071 00075 00079 typedef Vector2 PointType; 00080 00084 typedef std::vector<PointType> VectorType; 00086 00090 00092 TContourLine(T height = 0); 00093 00095 TContourLine(const TContourLine& copyTContourLine); 00096 00098 virtual ~TContourLine(); 00100 00102 void createContourLine(TRegularData2D<T>& from); 00103 00105 void interpol12(); 00106 void interpol18(); 00107 void interpol24(); 00108 void interpol48(); 00109 00113 00115 const TContourLine& operator = (const TContourLine& assigTContourLine); 00116 00118 virtual void clear(); 00120 00124 00126 bool operator == (const TContourLine& compTContourLine) const; 00127 00129 00133 00136 bool getNextPoint(PointType &p); 00137 00140 void resetCounter(); 00141 00143 00144 // private: 00145 T height_; 00146 VectorType data_; 00147 typename VectorType::iterator it_; 00148 Position index_; 00149 }; 00150 00153 typedef TContourLine<float> ContourLine; 00154 00155 template <typename T> 00156 TContourLine<T>::TContourLine(T height) 00157 : height_(height), 00158 index_(0) 00159 { 00160 } 00161 00162 template <typename T> 00163 TContourLine<T>::~TContourLine() 00164 { 00165 } 00166 00167 template <typename T> 00168 TContourLine<T>::TContourLine(const TContourLine<T>& from) 00169 : height_(from.height_), 00170 data_(from.data_), 00171 it_(from.it_), 00172 index_(from.index_) 00173 { 00174 } 00175 00176 template <typename T> 00177 void TContourLine<T>::clear() 00178 { 00179 data_.clear(); 00180 it_=data_.begin(); 00181 index_ = 0; 00182 } 00183 00184 template <typename T> 00185 const TContourLine<T>& TContourLine<T>::operator = (const TContourLine<T>& data) 00186 { 00187 data_ = data.data_; 00188 height_ = data.height_; 00189 it_ = data.it_; 00190 index_ = data.index_; 00191 00192 return *this; 00193 } 00194 00195 template <typename T> 00196 bool TContourLine<T>:: operator == (const TContourLine<T>& data) const 00197 { 00198 return ((height_ == data.height_) 00199 && (data_ == data.data_) 00200 && (it_ == data.it_) 00201 && (index_ == data.index_)); 00202 } 00203 00204 template <typename T> 00205 void TContourLine<T>::createContourLine(TRegularData2D<T>& from) 00206 { 00207 // This function uses a "marching cubes"-style algorithm to determine the contour-lines. 00208 //Size number_of_cells; 00209 Size number_of_cells_x; 00210 Size number_of_cells_y; 00211 Position act_cell_x; 00212 Position act_cell_y; 00213 PointType vec, vec2; 00214 double d1, d2, slope; 00215 double threshold = height_; 00216 00217 number_of_cells_x = (Size) from.getSize().x - 1; 00218 number_of_cells_y = (Size) from.getSize().y - 1; 00219 00220 for (act_cell_y = 0; act_cell_y < number_of_cells_y; act_cell_y++) 00221 { 00222 for (act_cell_x = 0; act_cell_x < number_of_cells_x; act_cell_x++) 00223 { 00224 // First we have to find out the topology of the actual square. 00225 int topology = 0; 00226 00227 if (from[act_cell_x + act_cell_y * (number_of_cells_x+1)] > threshold) 00228 { 00229 topology |= 1; 00230 } 00231 if (from[act_cell_x + 1 + act_cell_y * (number_of_cells_x+1)] > threshold) 00232 { 00233 topology |= 2; 00234 } 00235 if (from[act_cell_x + 1 + (act_cell_y + 1)*(number_of_cells_x + 1)] > threshold) 00236 { 00237 topology |= 4; 00238 } 00239 if (from[act_cell_x + (act_cell_y + 1) * (number_of_cells_x + 1)] > threshold) 00240 { 00241 topology |= 8; 00242 } 00243 // now we can use this information to compute the contour-line. 00244 switch (topology) 00245 { 00246 // no cut of contour-line here 00247 case 0 : 00248 case 15 : break; 00249 00250 // Line from upper left to lower right 00251 case 1 : 00252 case 14 : INTERPOL18 00253 INTERPOL12 00254 break; 00255 00256 case 4 : 00257 case 11 : INTERPOL48 00258 INTERPOL24 00259 break; 00260 00261 // Line from upper right to lower left 00262 case 2 : 00263 case 13 : INTERPOL12 00264 INTERPOL24 00265 break; 00266 00267 case 8 : 00268 case 7 : INTERPOL18 00269 INTERPOL48 00270 break; 00271 00272 // Line through the middle (upwards) 00273 case 9 : 00274 case 6 : INTERPOL12 00275 INTERPOL48 00276 break; 00277 00278 // Line through the middle (left to right) 00279 case 3 : 00280 case 12 : INTERPOL18 00281 INTERPOL24 00282 break; 00283 00284 // Two lines from upper right to lower left 00285 case 10 : INTERPOL18 00286 INTERPOL12 00287 INTERPOL48 00288 INTERPOL24 00289 break; 00290 00291 // Two lines from upper left to lower right 00292 case 5 : INTERPOL12 00293 INTERPOL24 00294 INTERPOL18 00295 INTERPOL48 00296 break; 00297 }; 00298 } 00299 } 00300 index_ = 0; 00301 it_ = data_.begin(); 00302 } 00303 00304 template <typename T> 00305 bool TContourLine<T>::getNextPoint(typename TContourLine<T>::PointType &p) 00306 { 00307 if (index_ < data_.size()) 00308 { 00309 p = *it_; 00310 index_++; 00311 it_++; 00312 return true; 00313 } 00314 else 00315 { 00316 return false; 00317 } 00318 } 00319 00320 template <typename T> 00321 void TContourLine<T>::resetCounter() 00322 { 00323 it_ = data_.begin(); 00324 index_ = 0; 00325 } 00326 } 00327 #endif