contourLine.h

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