BALL  1.4.1
contourLine.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines