/[libvob]/libvob/include/vob/poly/Dicer.hxx
ViewVC logotype

Diff of /libvob/include/vob/poly/Dicer.hxx

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.4 by tjl, Wed May 14 22:03:30 2003 UTC revision 1.5 by tjl, Mon Jun 9 15:04:36 2003 UTC
# Line 110  namespace Dicer { Line 110  namespace Dicer {
110                  tris.insert(tris.begin(), t);                  tris.insert(tris.begin(), t);
111          }          }
112    
113          template <class F> void dice(F criterion) {          template <class F> bool diceRound(F criterion) {
             DBG(dbg) << "Triangler: dice\n";  
114              typedef std::pair<int, int> Edge;              typedef std::pair<int, int> Edge;
115              vector<Edge> tosplit;              vector<Edge> tosplit;
116                DBG(dbg) << "Triangler: dice round\n";
117                for(Titer t = tris.begin(); t != tris.end(); t++) {
118                    Tri &tri = *t;
119                    int spl = criterion(tri.v[0], tri.v[1], tri.v[2]);
120                    if(spl >= 0) {
121                        tosplit.push_back( Edge( tri.v[spl], tri.v[(spl+1) % 3]));
122                    }
123                }
124                if(!tosplit.size()) return false;
125                for(unsigned i=0; i<tosplit.size(); i++)
126                    splitEdge(tosplit[i].first, tosplit[i].second);
127                return true;
128            }
129    
130            template <class F> void dice(F criterion) {
131                DBG(dbg) << "Triangler: dice\n";
132              int round = 0;              int round = 0;
133              while(1) {              while(1) {
134                  DBG(dbg) << "Triangler: dice round\n";                  if(!diceRound(criterion)) return;
                 for(Titer t = tris.begin(); t != tris.end(); t++) {  
                     Tri &tri = *t;  
                     int spl = criterion(tri.v[0], tri.v[1], tri.v[2]);  
                     if(spl >= 0) {  
                         tosplit.push_back( Edge( tri.v[spl], tri.v[(spl+1) % 3]));  
                     }  
                 }  
                 if(!tosplit.size()) return;  
                 for(unsigned i=0; i<tosplit.size(); i++)  
                     splitEdge(tosplit[i].first, tosplit[i].second);  
                 tosplit.clear();  
135                  round ++;                  round ++;
136                  if(round > 20) {                  if(round > 20) {
137                      DBG(dbg) << "OVER ROUND LIMIT! ABORTING!\n";                      DBG(dbg) << "OVER ROUND LIMIT! ABORTING!\n";
# Line 135  namespace Dicer { Line 139  namespace Dicer {
139                  }                  }
140              }              }
141          }          }
142            template <class F> void iterateTriangles(F func) {
143                for(Titer x = tris.begin(); x != tris.end(); x++)
144                    func( (*x).v[0], (*x).v[1], (*x).v[2]);
145            }
146          void draw() {          void draw() {
147              glBegin(GL_TRIANGLES);              glBegin(GL_TRIANGLES);
148              for(Titer x = tris.begin(); x != tris.end(); x++) {              for(Titer x = tris.begin(); x != tris.end(); x++) {
# Line 146  namespace Dicer { Line 154  namespace Dicer {
154          }          }
155          Triangles(Verts &v) : verts(v) {          Triangles(Verts &v) : verts(v) {
156          }          }
     };  
   
     /** Dice a line to pieces satisfying Criterion.  
      * This is a generic method to dice a given edge recursively.  
      * The edge is stored in an slist object containing the abstract  
      * vertices. New vertices are created by a functor.  
      *  
      * @param verts An object supporting (*iter, *iter, float fract)  
      * @param edge The slist object. It is required that insertion won't affect iterators,  
      *                  and that insert_after(Iter, &T) is supported.  
      * @param begin Iterator pointing to the first of the two vertices to dice.  
      * @param last Iterator pointing to the second of the two vertices to dice.  
      *                  Assumed to be right after begin by the algorithm.  
      * @param split A binary predicate: whether an edge between two vertices still needs splitting.  
      *          May also return a float as an approximation of how many split points there  
      *          should be, but is not currently used that way.  
      * @param maxdepth The maximum number of splits to do recursively  
      * @param depth INTERNAL.  
      * @return Number of new vertices added to the edge.  
      */  
     template<class Verts, class Edge, class Criterion>  
             int dice_line2(Verts &verts, Edge &edge,  
                         typename Edge::iterator begin, typename Edge::iterator last,  
                             Criterion split, int maxdepth, int depth=0) {  
         DBG(dbg) << "dice_line "<<depth<<"\n";  
         float nspl = split(*begin, *last);  
         DBG(dbg) << "dice_line split "<<nspl<<"\n";  
         if(depth >= maxdepth || nspl <= 0) {  
             DBG(dbg) << "dice_line STOP "<<nspl<<"\n";  
             return 0;  
         }  
         nspl = (int) nspl;  
         if(nspl > 1) nspl = 1;  
         int ret = 0;  
         typename Edge::iterator prev = begin;  
         for(int i=0; i<nspl; i++) {  
             DBG(dbg) << "dice_line vert "<<i<<"\n";  
             ret ++;  
             int v = verts(*begin, *last, (i+1.0) / (nspl + 1.0));  
             typename Edge::iterator n = edge.insert_after(prev, v);  
             ret += dice_line(verts, edge, prev, n, split, maxdepth, depth+1);  
             prev = n;  
         }  
   
         ret += dice_line(verts, edge, prev, last, split, maxdepth, depth+1);  
         DBG(dbg) << "RET dice_line "<<depth<<" "<<ret << "\n";  
         return ret;  
     }  
   
     template<class Verts, class Edge, class Criterion>  
             int dice_line3_h(Verts &verts, Edge &edge,  
                         typename Edge::iterator begin,  
                         typename Edge::iterator half,  
                         typename Edge::iterator last,  
                             Criterion split, int maxdepth, int depth) {  
         if(depth >= maxdepth) {  
             DBG(dbg) << "dice_line3_h STOPDEPTH\n";  
             return 0;  
         }  
         int splitflag = split(*begin, *half, *last);  
         int ret = 0;  
         if(splitflag == 1) {  
             int spv = verts(*begin, *half, .5);  
             ret ++;  
             typename Edge::iterator sp = edge.insert_after(begin, spv);  
             ret += dice_line3_h(verts, edge, begin, sp, half, split, maxdepth, depth+1);  
         }  
         int esplitflag = split(*last, *half, *begin);  
         if(esplitflag == 1) {  
             int espv = verts(*half, *last, .5);  
             ret ++;  
             typename Edge::iterator esp = edge.insert_after(half, espv);  
             ret += dice_line3_h(verts, edge, half, esp, last, split, maxdepth, depth+1);  
         }  
         return ret;  
           
     }  
   
     template<class Verts, class Edge, class Criterion>  
             int dice_line3(Verts &verts, Edge &edge,  
                         typename Edge::iterator begin, typename Edge::iterator last,  
                             Criterion split, int maxdepth, int depth=0) {  
         DBG(dbg) << "dice_line "<<depth<<"\n";  
         if(depth >= maxdepth) {  
             DBG(dbg) << "dice_line STOPDEPTH\n";  
             return 0;  
         }  
         int halfv = verts(*begin, *last, .5);  
   
   
         int splitflag = split(*begin, halfv, *last);  
         if(splitflag == -1) {  
             DBG(dbg) << "dice_line STOP FLAG\n";  
             return 0;  
         }  
         typename Edge::iterator half = edge.insert_after(begin, halfv);  
         int ret = 1;  
         ret += dice_line3_h(verts, edge, begin, half, last, split, maxdepth, depth + 1);  
   
         DBG(dbg) << "RET dice_line "<<depth<<" "<<ret << "\n";  
         return ret;  
     }  
   
   
     /** A triangle whose edges have been diced.  
      */  
     template<class Edge> struct DicedTriangle {  
         typedef typename Edge::iterator Iter;  
         Iter ebegins[3];  
         Iter elasts[3];  
         /** Numbers of vertices between begin and last.  
          */  
         int n[3];  
   
         template<class Verts, class Criterion, class Triangler>  
             void dice(Verts &verts, Triangler &t, Criterion &split, int maxdepth, int depth = 0) {  
                 DBG(dbg) << "Dice start "<<depth<<" "<<n[0]<<" "<<n[1]<<" "<<n[2]<<"\n"  
                     << "with triangle "  
                         << *ebegins[0] << " " << *elasts[0] << " "  
                         << *ebegins[1] << " " << *elasts[1] << " "  
                         << *ebegins[2] << " "<< *elasts[2] << "\n";  
                 int maxind ;  
                 // Can't use max_element easily, as we need the *LAST*  
                 // greatest element, otherwise recurses really badly.  
                 if(n[2] >= n[0] && n[2] >= n[1]) {  
                     maxind = 2;  
                 } else if(n[1] >= n[2] && n[1] >= n[0]) {  
                     maxind = 1;  
                 } else {  
                     maxind = 0;  
                 }  
                 DBG(dbg) << "Maxind "<<maxind<<"\n";  
   
                 if(n[maxind] == 0) {  
                     DBG(dbg) << "Do triangle "  
                         << *ebegins[0] << " " << *ebegins[1] << " " << *ebegins[2] << "\n";  
                     t(*ebegins[0], *ebegins[1], *ebegins[2]);  
                     return;  
                 }  
   
                 int otherEdge = (maxind + 1) % 3;  
                 int thirdEdge = (maxind + 2) % 3;  
                 // Hope this is the right direction ;)  
                 Iter mid = ebegins[maxind];  
                 int nin = -1;  
                 for(int i=0; i<(n[maxind]+1)/2; i++) {  
                     mid++;  
                     nin ++;  
                 }  
                 DBG(dbg) << "Middle: "<<*mid<<"\n";  
                 Edge newEdge;  
   
                 DBG(dbg) << "Creating edges "<<maxind<<" "<<otherEdge<<" "<<  
                         thirdEdge<<"\n";  
                 newEdge.push_front(*elasts[otherEdge]);  
                 newEdge.push_front(*mid);  
   
                 DicedTriangle start;  
                 start.ebegins[0] = newEdge.begin();  
                 start.elasts[0] = newEdge.begin(); start.elasts[0] ++;  
                 start.n[0] = dice_line3(verts, newEdge, start.ebegins[0], start.elasts[0], split, maxdepth, depth);  
   
                 start.ebegins[1] = ebegins[thirdEdge];  
                 start.elasts[1] = elasts[thirdEdge];  
                 start.n[1] = n[thirdEdge];  
   
                 start.ebegins[2] = ebegins[maxind];  
                 start.elasts[2] = mid;  
                 start.n[2] = nin;  
   
                 DicedTriangle end;  
   
                 DBG(dbg) << "Second edge!\n";  
                 // newEdge runs in opposite direction now.  
                 Edge newEdge2;  
                 Iter i = newEdge.begin();  
                 newEdge2.push_front(*i);  
                 end.elasts[0] = newEdge2.begin();  
                 for(; i!=newEdge2.end(); i++)  
                     newEdge2.push_front(*i);  
   
                 DBG(dbg) << "Second edge done!\n";  
   
                 end.ebegins[0] = newEdge2.begin();  
                 // elasts set earlier  
                 end.n[0] = start.n[0];  
   
                 end.ebegins[1] = mid;  
                 end.elasts[1] = elasts[maxind];  
                 end.n[1] = n[maxind] - nin - 1;  
   
                 end.ebegins[2] = ebegins[otherEdge];  
                 end.elasts[2] = elasts[otherEdge];  
                 end.n[2] = n[otherEdge];  
   
                 DBG(dbg) << "Recursing!\n";  
                 start.dice(verts, t, split, maxdepth, depth + 1);  
                 end.dice(verts, t, split, maxdepth, depth + 1);  
         }  
     };  
   
     template<class Edge> struct InitialDicedTriangle : public DicedTriangle<Edge> {  
         Edge e[3];  
157    
         template<class Vert, class Verts, class Criterion>  
             void set_and_initial_dice(Verts &verts, Vert v0, Vert v1, Vert v2,  
                             Criterion split, int maxdepth) {  
             e[0].push_front(v1);  
             e[0].push_front(v0);  
             e[1].push_front(v2);  
             e[1].push_front(v1);  
             e[2].push_front(v0);  
             e[2].push_front(v2);  
               
             for(int i=0; i<3; i++) {  
                 ebegins[i] = e[i].begin();  
                 elasts[i] = ebegins[i]; elasts[i] ++;  
                 n[i] = dice_line3(verts, e[i], ebegins[i], elasts[i], split, maxdepth);  
             }  
         }  
158      };      };
159    
160    
   
   
161  }  }
162  }  }
163    

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26