complex.h

Go to the documentation of this file.
00001 #ifndef VVELIB_ALGORITHMS_COMPLEX_H
00002 #define VVELIB_ALGORITHMS_COMPLEX_H
00003 
00010 #include <config.h>
00011 #include <graph/vvgraph.h>
00012 #include <graph/vvbigraph.h>
00013 #include <algorithms/insert.h>
00014 #include <util/parms.h>
00015 #include <util/palette.h>
00016 #include <util/color.h>
00017 #include <util/leaf_class.h>
00018 #include <util/assert.h>
00019 #include <geometry/intersection.h>
00020 #include <geometry/area.h>
00021 #include <storage/fwd.h>
00022 
00023 #include <iostream>
00024 
00417 namespace vvcomplex
00418 {
00419   using util::norm;
00420   using util::normsq;
00421   using util::normalized;
00422 
00423   using std::cout;
00424   using std::cerr;
00425   using std::endl;
00426 
00427   using geometry::Point3d;
00428 
00442 #define EXPORT_COMPLEX_VERTICES(ComplexClass) \
00443   typedef ComplexClass::cell cell; \
00444   typedef ComplexClass::junction junction
00445 
00464 #define EXPORT_COMPLEX_EDGES(ComplexClass) \
00465   typedef ComplexClass::cell_edge cell_edge; \
00466   typedef ComplexClass::wall wall; \
00467   typedef ComplexClass::cell_junction_edge cell_junction_edge; \
00468   typedef ComplexClass::junction_cell_edge junction_cell_edge; \
00469   typedef ComplexClass::const_cell_edge const_cell_edge; \
00470   typedef ComplexClass::const_wall const_wall; \
00471   typedef ComplexClass::const_cell_junction_edge const_cell_junction_edge; \
00472   typedef ComplexClass::const_junction_cell_edge const_junction_cell_edge
00473 
00487 #define EXPORT_COMPLEX_GRAPHS(ComplexClass) \
00488   typedef ComplexClass::complex_graph complex_graph; \
00489   typedef ComplexClass::cell_graph cell_graph; \
00490   typedef ComplexClass::wall_graph wall_graph
00491 
00504 #define EXPORT_COMPLEX_TYPES(ComplexClass) \
00505   EXPORT_COMPLEX_VERTICES(ComplexClass); \
00506   EXPORT_COMPLEX_EDGES(ComplexClass); \
00507   EXPORT_COMPLEX_GRAPHS(ComplexClass)
00508 
00521 #define EXPORT_COMPLEX_VERTICES_PREFIX(ComplexClass, prefix) \
00522   typedef ComplexClass::cell prefix##_cell; \
00523   typedef ComplexClass::junction prefix##_junction
00524 
00543 #define EXPORT_COMPLEX_EDGES_PREFIX(ComplexClass, prefix) \
00544   typedef ComplexClass::cell_edge prefix##_cell_edge; \
00545   typedef ComplexClass::wall prefix##_wall; \
00546   typedef ComplexClass::cell_junction_edge prefix##_cell_junction_edge; \
00547   typedef ComplexClass::junction_cell_edge prefix##_junction_cell_edge; \
00548   typedef ComplexClass::const_cell_edge prefix##_const_cell_edge; \
00549   typedef ComplexClass::const_wall prefix##_const_wall; \
00550   typedef ComplexClass::const_cell_junction_edge prefix##_const_cell_junction_edge; \
00551   typedef ComplexClass::const_junction_cell_edge prefix##_const_junction_cell_edge
00552 
00566 #define EXPORT_COMPLEX_GRAPHS_PREFIX(ComplexClass, prefix) \
00567   typedef ComplexClass::complex_graph prefix##_complex_graph; \
00568   typedef ComplexClass::cell_graph prefix##_cell_graph; \
00569   typedef ComplexClass::wall_graph prefix##_wall_graph
00570 
00583 #define EXPORT_COMPLEX_TYPES_PREFIX(ComplexClass, prefix) \
00584   EXPORT_COMPLEX_VERTICES_PREFIX(ComplexClass, prefix); \
00585   EXPORT_COMPLEX_EDGES_PREFIX(ComplexClass, prefix); \
00586   EXPORT_COMPLEX_GRAPHS_PREFIX(ComplexClass, prefix)
00587 
00596 #define IMPORT_COMPLEX_VERTICES(ComplexClass) \
00597   typedef typename ComplexClass::cell cell; \
00598   typedef typename ComplexClass::junction junction
00599 
00608 #define IMPORT_COMPLEX_EDGES(ComplexClass) \
00609   typedef typename ComplexClass::cell_edge cell_edge; \
00610   typedef typename ComplexClass::wall wall; \
00611   typedef typename ComplexClass::cell_junction_edge cell_junction_edge; \
00612   typedef typename ComplexClass::junction_cell_edge junction_cell_edge; \
00613   typedef typename ComplexClass::const_cell_edge const_cell_edge; \
00614   typedef typename ComplexClass::const_wall const_wall; \
00615   typedef typename ComplexClass::const_cell_junction_edge const_cell_junction_edge; \
00616   typedef typename ComplexClass::const_junction_cell_edge const_junction_cell_edge
00617 
00626 #define IMPORT_COMPLEX_GRAPHS(ComplexClass) \
00627   typedef typename ComplexClass::complex_graph complex_graph; \
00628   typedef typename ComplexClass::cell_graph cell_graph; \
00629   typedef typename ComplexClass::wall_graph wall_graph
00630 
00640 #define IMPORT_COMPLEX_MODEL(ComplexClass, cplx) \
00641   typename ComplexClass::model_t &model = *(cplx).model;
00642 
00651 #define IMPORT_COMPLEX_TYPES(ComplexClass) \
00652   IMPORT_COMPLEX_VERTICES(ComplexClass); \
00653   IMPORT_COMPLEX_EDGES(ComplexClass); \
00654   IMPORT_COMPLEX_GRAPHS(ComplexClass)
00655 
00656   /*
00657    * Documentation for the types imported
00658    *
00659    * \typedef typename VVComplex::cell cell
00660    * \brief Type of a cell
00661    *
00662    * \typedef typename VVComplex::junction junction
00663    * \brief Type of a junction
00664    *
00665    * \typedef typename VVComplex::cell_edge cell_edge
00666    * \brief Type of an edge in the cell graph
00667    *
00668    * \typedef typename VVComplex::wall wall
00669    * \brief Type of a wall (i.e. an edge in the wall graph)
00670    *
00671    * \typedef typename VVComplex::cell_junction_edge cell_junction_edge
00672    * \brief Type of an edge from a cell to a junction
00673    *
00674    * \typedef typename VVComplex::junction_cell_edge junction_cell_edge
00675    * \brief Type of an edge from a junction to a cell
00676    *
00677    * \typedef typename VVComplex::complex_graph complex_graph;
00678    * \brief Type of the complex graph (i.e. linking cells to junctions and 
00679    * vice-versa)
00680    *
00681    * \typedef typename VVComplex::cell_graph cell_graph;
00682    * \brief Type of the cell graph
00683    *
00684    * \typedef typename VVComplex::wall_graph wall_graph
00685    * \brief Type of the wall graph
00686    */
00687 
00688 #ifdef JUST_FOR_DOXYGEN
00689 
00690 
00691 
00693   typedef VVComplex::cell cell;
00694 
00696   typedef VVComplex::junction junction;
00697 
00699   typedef VVComplex::cell_edge cell_edge;
00700 
00702   typedef VVComplex::const_cell_edge const_cell_edge;
00703 
00705   typedef VVComplex::wall wall;
00706 
00708   typedef VVComplex::const_wall const_wall;
00709 
00711   typedef VVComplex::cell_junction_edge cell_junction_edge;
00712 
00714   typedef VVComplex::const_cell_junction_edge const_cell_junction_edge;
00715 
00717   typedef VVComplex::junction_cell_edge junction_cell_edge;
00718 
00720   typedef VVComplex::const_junction_cell_edge const_junction_cell_edge;
00721 
00723   typedef VVComplex::complex_graph complex_graph;
00724 
00726   typedef VVComplex::cell_graph cell_graph;
00727 
00729   typedef VVComplex::wall_graph wall_graph;
00731 #endif
00732 
00745   template <typename JunctionContent>
00746     struct DivisionData
00747   {
00751     typedef graph::Vertex<JunctionContent> junction;
00752 
00756     DivisionData()
00757       : u1(0)
00758       , v1(0)
00759       , divide_at_u1(false)
00760       , divide_at_v1(false)
00761     { }
00762 
00766     DivisionData(Point3d _pu, Point3d _pv,
00767                  const junction& _u1,
00768                  const junction& _v1,
00769                  bool _du1 = false,
00770                  bool _dv1 = false)
00771       : pu(_pu)
00772       , pv(_pv)
00773       , u1(_u1)
00774       , v1(_v1)
00775       , divide_at_u1(_du1)
00776       , divide_at_v1(_dv1)
00777     { }
00778 
00782     DivisionData(const DivisionData& copy)
00783       : pu(copy.pu)
00784       , pv(copy.pv)
00785       , u1(copy.u1)
00786       , v1(copy.v1)
00787       , divide_at_u1(copy.divide_at_u1)
00788       , divide_at_v1(copy.divide_at_v1)
00789     { }
00790 
00798     operator bool()
00799     {
00800       return u1 and v1;
00801     }
00802 
00806     bool operator!() const
00807     {
00808       return !u1 or !v1;
00809     }
00810 
00837     Point3d pu, pv;
00838     junction u1, v1;
00839     bool divide_at_u1, divide_at_v1;
00840   };
00841 
00842 
00843 #ifdef USE_ALLOCATOR
00844 #   define COMPLEX_ARGS CellContent,JunctionContent,CellJunctionContent,JunctionCellContent,compact,Alloc
00845 #else // USE_ALLOCATOR
00846 #   define COMPLEX_ARGS CellContent,JunctionContent,CellJunctionContent,JunctionCellContent,compact
00847 #endif // USE_ALLOCATOR
00848 
00855   template <typename CellContent, typename JunctionContent, typename CellJunctionContent = graph::_EmptyEdgeContent, typename JunctionCellContent = graph::_EmptyEdgeContent, bool compact = false
00856 #ifdef USE_ALLOCATOR
00857     , typename Alloc = DEFAULT_ALLOC(CellContent)
00858 #endif
00859     >
00860   struct VVComplexGraph : public graph::VVBiGraph<COMPLEX_ARGS>
00861   {
00862     typedef graph::VVBiGraph<COMPLEX_ARGS> ParentClass;
00863     typedef typename ParentClass::iterator1 iterator1;
00864     typedef typename ParentClass::iterator2 iterator2;
00865     typedef typename ParentClass::const_iterator1 const_iterator1;
00866     typedef typename ParentClass::const_iterator2 const_iterator2;
00867     typedef typename ParentClass::vertex1_t cell;
00868     typedef typename ParentClass::vertex2_t junction;
00869     typedef typename ParentClass::edge1_t cell_junction_edge;
00870     typedef typename ParentClass::edge2_t junction_cell_edge;
00871     typedef typename ParentClass::const_edge1_t const_cell_junction_edge;
00872     typedef typename ParentClass::const_edge2_t const_junction_cell_edge;
00873     typedef typename ParentClass::size_type size_type;
00874     typedef typename ParentClass::range_vertex1 range_cell;
00875     typedef typename ParentClass::range_vertex2 range_junction;
00876     typedef typename ParentClass::const_range_vertex1 const_range_cell;
00877     typedef typename ParentClass::const_range_vertex2 const_range_junction;
00878 
00879     VVComplexGraph()
00880       : ParentClass()
00881     {}
00882 
00883     VVComplexGraph(const ParentClass& other)
00884       : ParentClass(other)
00885     {}
00886 
00890     const cell& any_cell() const { return this->any_vertex1(); }
00894     const junction& any_junction() const { return this->any_vertex2(); }
00895 
00898     iterator1 begin_cells() { return this->begin_vertex1(); }
00899     iterator1 end_cells() { return this->end_vertex1(); }
00900 
00901     iterator2 begin_junctions() { return this->begin_vertex2(); }
00902     iterator2 end_junctions() { return this->end_vertex2(); }
00903 
00904     const_iterator1 begin_cells() const { return this->begin_vertex1(); }
00905     const_iterator1 end_cells() const { return this->end_vertex1(); }
00906 
00907     const_iterator2 begin_junctions() const { return this->begin_vertex2(); }
00908     const_iterator2 end_junctions() const { return this->end_vertex2(); }
00909 
00910     range_cell cells() { return this->vertices1(); }
00911     range_junction junctions() { return this->vertices2(); }
00912 
00913     const_range_cell cells() const { return this->vertices1(); }
00914     const_range_junction junctions() const { return this->vertices2(); }
00916 
00920     size_t nb_cells() const { return this->nb_vertices1(); }
00924     size_t nb_junctions() const { return this->nb_vertices2(); }
00925 
00929     bool no_cell() const { return this->no_vertex1(); }
00933     bool no_junction() const { return this->no_vertex2(); }
00934 
00938     const cell& get_cell(size_type idx) const { return this->get_vertex1(idx); }
00942     const junction& get_junction(size_type idx) const { return this->get_vertex2(idx); }
00943 
00947     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3)
00948     {
00949       std::vector<junction> junctions(3, junction(0));
00950       junctions[0] = j1;
00951       junctions[1] = j2;
00952       junctions[2] = j3;
00953       return this->addCell(c, junctions);
00954     }
00955 
00959     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
00960                  const junction& j4)
00961     {
00962       std::vector<junction> junctions(4, junction(0));
00963       junctions[0] = j1;
00964       junctions[1] = j2;
00965       junctions[2] = j3;
00966       junctions[3] = j4;
00967       return this->addCell(c, junctions);
00968     }
00969 
00973     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
00974                  const junction& j4, const junction& j5)
00975     {
00976       std::vector<junction> junctions(5, junction(0));
00977       junctions[0] = j1;
00978       junctions[1] = j2;
00979       junctions[2] = j3;
00980       junctions[3] = j4;
00981       junctions[4] = j5;
00982       return this->addCell(c, junctions);
00983     }
00984 
00988     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
00989                  const junction& j4, const junction& j5, const junction& j6)
00990     {
00991       std::vector<junction> junctions(6, junction(0));
00992       junctions[0] = j1;
00993       junctions[1] = j2;
00994       junctions[2] = j3;
00995       junctions[3] = j4;
00996       junctions[4] = j5;
00997       junctions[5] = j6;
00998       return this->addCell(c, junctions);
00999     }
01000 
01004     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
01005                  const junction& j4, const junction& j5, const junction& j6, const junction& j7)
01006     {
01007       std::vector<junction> junctions(7, junction(0));
01008       junctions[0] = j1;
01009       junctions[1] = j2;
01010       junctions[2] = j3;
01011       junctions[3] = j4;
01012       junctions[4] = j5;
01013       junctions[5] = j6;
01014       junctions[6] = j7;
01015       return this->addCell(c, junctions);
01016     }
01017 
01021     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
01022                  const junction& j4, const junction& j5, const junction& j6, const junction& j7,
01023                  const junction& j8)
01024     {
01025       std::vector<junction> junctions(8, junction(0));
01026       junctions[0] = j1;
01027       junctions[1] = j2;
01028       junctions[2] = j3;
01029       junctions[3] = j4;
01030       junctions[4] = j5;
01031       junctions[5] = j6;
01032       junctions[6] = j7;
01033       junctions[7] = j8;
01034       return this->addCell(c, junctions);
01035     }
01036 
01040     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
01041                  const junction& j4, const junction& j5, const junction& j6, const junction& j7,
01042                  const junction& j8, const junction& j9)
01043     {
01044       std::vector<junction> junctions(9, junction(0));
01045       junctions[0] = j1;
01046       junctions[1] = j2;
01047       junctions[2] = j3;
01048       junctions[3] = j4;
01049       junctions[4] = j5;
01050       junctions[5] = j6;
01051       junctions[6] = j7;
01052       junctions[7] = j8;
01053       junctions[8] = j9;
01054       return this->addCell(c, junctions);
01055     }
01056 
01057     template <typename JunctionContainer>
01058     bool addCell(const cell& c, const JunctionContainer& junctions)
01059     {
01060       std::list<junction> inserted;
01061       insert(c);
01062       junction pj(0), fj(0);
01063       // First, create the outgoing edges and insert cell and junctions
01064       forall(const junction& j,junctions)
01065       {
01066         if(!contains(j))
01067         {
01068           inserted.push_back(j);
01069           insert(j);
01070         }
01071         if(pj.isNull())
01072         {
01073           fj = j;
01074           insertEdge(c, j);
01075         }
01076         else
01077         {
01078           spliceAfter(c, pj, j);
01079         }
01080         pj = j;
01081       }
01082       // Next, connect the junctions to the cells
01083       forall( const junction& j , neighbors(c))
01084       {
01085         if(valence(j) < 2)
01086           insertEdge(j, c);
01087         else
01088         {
01089           bool done = false;
01090           // First, try to connect with respect to the previous junction
01091           const junction& nj = this->nextTo(c, j);
01092           forall( const cell& nc , neighbors(j))
01093           {
01094             if(edge(nc, nj))
01095             {
01096               spliceAfter(j, nc, c);
01097               done = true;
01098               break;
01099             }
01100           }
01101           if(!done)
01102           {
01103             const junction& nj = prevTo(c, j);
01104             forall( const cell& nc , neighbors(j))
01105             {
01106               if(edge(nc, nj))
01107               {
01108                 spliceBefore(j, nc, c);
01109                 done = true;
01110                 break;
01111               }
01112             }
01113           }
01114           if(!done)
01115           {
01116             erase(c);
01117             forall(const junction& j, inserted)
01118             {
01119               erase(j);
01120             }
01121             return false;
01122           }
01123         }
01124       }
01125       return true;
01126     }
01127 
01132     bool border(const cell& c, const junction& j) const
01133     {
01134       const cell& c2 = this->prevTo(j, c);
01135       return this->nextTo(c, j) != this->prevTo(c2, j);
01136     }
01137 
01141     bool border(const junction& j) const
01142     {
01143       forall( const cell& c , this->neighbors(j))
01144       {
01145         if(border(c, j)) return true;
01146       }
01147       return false;
01148     }
01149 
01153     bool border(const cell& c) const
01154     {
01155       forall( const junction& j , neighbors(c))
01156       {
01157         if(border(c, j)) return true;
01158       }
01159       return false;
01160     }
01161 
01162     bool border(const junction& j1, const junction& j2) const
01163     {
01164       forall( const cell& c , neighbors(j1))
01165       {
01166         if(nextTo(c, j1) == j2)
01167           return prevTo(prevTo(j1, c), j1) != j2;
01168         else if(prevTo(c, j1) == j2)
01169           return nextTo(nextTo(j1, c), j1) != j2;
01170       }
01171       return false;
01172     }
01173 
01177     const cell& adjacentCell(const cell& c, const junction& j) const
01178     {
01179       const junction& nj = this->nextTo(c, j);
01180       const cell& adj = this->prevTo(j, c);
01181       if(this->prevTo(adj, j) == nj)
01182         return adj;
01183       return cell::null;
01184     }
01185 
01192     std::pair<cell,cell> adjacentCells(const junction& j1, const junction& j2) const
01193     {
01194       vvassert(j1 != j2);
01195       forall(const cell& c , neighbors(j1))
01196       {
01197         if(nextTo(c, j1) == j2)
01198         {
01199           const cell& c2 = prevTo(j1, c);
01200           if(prevTo(c2, j1) == j2)
01201             return std::make_pair(c,c2);
01202           return std::make_pair(c, cell::null);
01203         }
01204         else if(prevTo(c, j1) == j2)
01205         {
01206           const cell& c1 = nextTo(j1, c);
01207           if(nextTo(c1, j1) == j2)
01208             return std::make_pair(c1, c);
01209           return std::make_pair(cell::null, c);
01210         }
01211       }
01212       return std::make_pair(cell::null, cell::null);
01213     }
01214 
01215   private:
01216     const junction& startInterfaceWall(const junction& j, const cell& c1, const cell& c2, junction start = junction(0)) const
01217     {
01218       if(not start) start = j;
01219       const junction& pj = prevTo(c1, j);
01220       if(pj == nextTo(c2, j)) // We are not at the start of the interface
01221       {
01222         if(pj == start) // The whole interface is with c2, so there is no beginning
01223           return pj;
01224         return startInterfaceWall(pj, c1, c2, start);
01225       }
01226       return j;
01227     }
01228 
01232     const junction& endInterfaceWall(const junction& j, const cell& c1, const cell& c2, junction start = junction(0)) const
01233     {
01234       if(not start) start = j;
01235       const junction& nj = nextTo(c1, j);
01236       if(nj == prevTo(c2, j)) // We are not at the end of the interface
01237       {
01238         if(nj == start) // The interface is with c2 so there is no end
01239           return nj;
01240         return endInterfaceWall(nj, c1, c2, start);
01241       }
01242       return j;
01243     }
01244 
01245   public:
01246 
01251     const junction& interfaceWall(const cell& c1, const cell& c2) const
01252     {
01253       forall( const junction& j, neighbors(c1))
01254       {
01255         if(prevTo(j, c1) == c2)
01256         {
01257           if(nextTo(c1, j) == prevTo(c2, j))
01258           {
01259             return startInterfaceWall(j, c1, c2);
01260           }
01261         }
01262       }
01263       return junction::null;
01264     }
01265 
01272     std::pair<junction, junction> interfaceWallSpan(const cell& c1, const cell& c2) const
01273     {
01274       forall(const junction& j, neighbors(c1))
01275       {
01276         if(prevTo(j, c1) == c2)
01277         {
01278           if(nextTo(c1, j) == prevTo(c2, j))
01279           {
01280             return std::make_pair(startInterfaceWall(j, c1, c2),
01281                                   endInterfaceWall(j, c1, c2));
01282           }
01283         }
01284       }
01285       return std::make_pair(junction::null, junction::null);
01286     }
01287 
01293     std::vector<junction> deleteCell(const cell& c)
01294     {
01295       typename ParentClass::neighbor_iterator1_range p = neighbors(c);
01296       std::vector<junction> js(p.begin(), p.end());
01297       std::vector<junction> deleted;
01298       erase(c);
01299       forall(const junction& j,js) if(empty(j))
01300       {
01301         erase(j);
01302         deleted.push_back(j);
01303       }
01304       return deleted;
01305     }
01306 
01310     const junction& splitWall(const junction& j1, const junction& j2, const junction& x = junction(0))
01311     {
01312       const junction& j = *insert(x?x:junction());
01313       forall(const cell& c, neighbors(j1))
01314       {
01315         if(nextTo(c, j1) == j2)
01316         {
01317           spliceAfter(c, j1, j);
01318           insertEdge(j, c);
01319         }
01320         else if(prevTo(c, j1) == j2)
01321         {
01322           spliceBefore(c, j1, j);
01323           insertEdge(j, c);
01324         }
01325       }
01326       return j;
01327     }
01328 
01332     const junction& splitWall(const cell& c, const junction& j1, const junction& x = junction(0))
01333     {
01334       const cell& c2 = adjacentCell(c, j1);
01335       const junction& j = *insert(x?x:junction());
01336       spliceAfter(c, j1, j);
01337       insertEdge(j, c);
01338       if(c2)
01339       {
01340         spliceBefore(c2, j1, j);
01341         insertEdge(j, c2);
01342       }
01343       return j;
01344     }
01345 
01349     typedef DivisionData<JunctionContent> division_data;
01350 
01359     struct division_result_t
01360     {
01361       division_result_t()
01362         : cl(0)
01363         , cr(0)
01364         , u1(0)
01365         , u2(0)
01366         , u(0)
01367         , v1(0)
01368         , v2(0)
01369         , v(0)
01370       {}
01371 
01372       division_result_t(cell cl, cell cr,
01373                         junction u1, junction u2, junction u,
01374                         junction v1, junction v2, junction v)
01375         : cl(cl)
01376         , cr(cr)
01377         , u1(u1)
01378         , u2(u2)
01379         , u(u)
01380         , v1(v1)
01381         , v2(v2)
01382         , v(v)
01383       {}
01384 
01385       division_result_t(const division_result_t& copy)
01386         : cl(copy.cl)
01387         , cr(copy.cr)
01388         , u1(copy.u1)
01389         , u2(copy.u2)
01390         , u(copy.u)
01391         , v1(copy.v1)
01392         , v2(copy.v2)
01393         , v(copy.v)
01394       {}
01395 
01396       cell cl, cr;
01397       junction u1, u2, u, v1, v2, v;
01398       operator bool() { return cl and cr; }
01399     };
01400 
01401 
01405     division_result_t divideCell( const cell& c,
01406                                   const division_data& ddata )
01407     {
01408       //Point3d pu = ddata.pu, pv = ddata.pv;
01409       junction u1 = ddata.u1, v1 = ddata.v1;
01410       junction u2 = this->nextTo(c, u1), v2 = this->nextTo(c, v1);
01411 
01412       junction u(0), v(0);
01413 
01414       // First, find the neighbor cells
01415       const cell& nu = adjacentCell(c, u1);
01416       const cell& nv = adjacentCell(c, v1);
01417 
01418       // Insert a new vertex on the new wall
01419       if(ddata.divide_at_u1)
01420         u = u1;
01421       else
01422       {
01423         u = junction();
01424         this->insert(u);
01425         this->spliceAfter(c, u1, u);
01426         this->insertEdge(u, c);
01427       }
01428 
01429       // Insert a new vertex on the other side
01430       if(ddata.divide_at_v1)
01431         v = v1;
01432       else
01433       {
01434         v = junction();
01435         this->insert(v);
01436         this->spliceAfter(c, v1, v);
01437         this->insertEdge(v, c);
01438       }
01439 
01440       // If necessary, adjust the connectivity of the adjacent cells
01441       // Then compute the position of the new vertices and adjust the one of 
01442       // the cells around
01443       if(!ddata.divide_at_u1)
01444       {
01445         if(nu)
01446         {
01447           this->spliceBefore(nu, u1, u);
01448           this->insertEdge(u, nu);
01449         }
01450       }
01451 
01452       if(!ddata.divide_at_v1)
01453       {
01454         if(nv)
01455         {
01456           this->spliceBefore(nv, v1, v);
01457           this->insertEdge(v, nv);
01458         }
01459       }
01460 
01461       // Create the two new cell centers
01462       cell cl, cr;
01463       this->insert(cl);
01464       this->insert(cr);
01465 
01466       // Connect new junctions
01467       this->insertEdge(cl, u);
01468       this->insertEdge(cl, v);
01469       this->insertEdge(cr, u);
01470       this->insertEdge(cr, v);
01471 
01472       this->spliceAfter(u, c, cl);
01473       this->replace(u, c, cr);
01474       this->spliceBefore(v, c, cl);
01475       this->replace(v, c, cr);
01476 
01477       // Connect the new centers
01478       forall( const junction& x , this->neighbors(c, this->nextTo(c, u)))
01479       {
01480         if(x == v) break;
01481         this->spliceBefore(cr, v, x);
01482         this->replace(x, c, cr);
01483       }
01484 
01485       forall( const junction& y , this->neighbors(c, this->nextTo(c, v)))
01486       {
01487         if(y == u) break;
01488         this->spliceBefore(cl, u, y);
01489         this->replace(y, c, cl);
01490       }
01491 
01492       // Remove c
01493       this->erase(c);
01494 
01495       return division_result_t(cl, cr, u1, u2, u, v1, v2, v);
01496     }
01497 
01506     std::pair<junction, junction> mergeCells(const cell& c1, const cell& c2, std::vector<junction>* deleted_junctions = 0)
01507     {
01508       std::pair<junction, junction> result = interfaceWallSpan(c1, c2);
01509       if(!result.first)
01510         return result;
01511       junction j1 = result.first;
01512       junction j2 = result.second;
01513       std::vector<junction> local_deleted_junctions;
01514       if(deleted_junctions == 0) deleted_junctions = &local_deleted_junctions;
01515       forall(const junction& j, neighbors(c1, nextTo(c1, j1)))
01516       {
01517         if(j == j2)
01518           break;
01519         deleted_junctions->push_back(j);
01520       }
01521 
01522       // Remove junctions from c1 and W
01523       forall(const junction& j, *deleted_junctions)
01524       {
01525         eraseEdge(c1, j);
01526       }
01527 
01528       // Update S
01529       forall(const junction& j, neighbors(c2, nextTo(c2, j1)))
01530       {
01531         if(j == j2) break;
01532         spliceBefore(c1, j2, j);
01533         replace(j, c2, c1);
01534       }
01535 
01536       // Erase c2 from C and S
01537       erase(c2);
01538 
01539       return result;
01540     }
01541 
01542     std::vector<junction> nextContourVertex(const junction& first, const cell& c,
01543                                             const junction& j,
01544                                             std::vector<junction> acc) const
01545     {
01546       const junction& n = nextTo(c, j);
01547       if(n == first)
01548         return acc;
01549       else if(acc.size() >= nb_junctions())
01550         return std::vector<junction>();
01551       int nb_common_cells = 0;
01552       forall( const cell& cn , neighbors(j))
01553       {
01554         if(edge(cn, n))
01555           nb_common_cells++;
01556       }
01557       if(nb_common_cells == 1)
01558       {
01559         acc.push_back(n);
01560         return nextContourVertex(first, c, n, acc);
01561       }
01562       const cell& cn = nextTo(j, c);
01563       const junction& jn = nextTo(cn, j);
01564       if(jn == first)
01565         return acc;
01566       acc.push_back(jn);
01567       return nextContourVertex(first, cn, jn, acc);
01568     }
01569 
01570     std::vector<junction> contour() const
01571     {
01572       std::vector<junction> result;
01573       switch(nb_cells())
01574       {
01575         case 0:
01576           return result; // No contour !
01577         case 1:
01578           {
01579             const cell& c = any_cell();
01580             const junction& j1 = anyIn(c);
01581             const junction& j2 = nextTo(c, j1);
01582             const junction& j3 = nextTo(c, j2);
01583             result.push_back(j1);
01584             result.push_back(j2);
01585             result.push_back(j3);
01586           }
01587           break;
01588         case 2:
01589           {
01590             const cell& c1 = reference(get_cell(0));
01591             const cell& c2 = reference(get_cell(1));
01592             forall( const junction& j , neighbors(c1))
01593             {
01594               if(valence(j) == 1)
01595               {
01596                 result.push_back(prevTo(c1, j));
01597                 result.push_back(j);
01598                 result.push_back(nextTo(c1, j));
01599                 break;
01600               }
01601             }
01602             forall( const junction& j , neighbors(c2))
01603             {
01604               if(valence(j) == 1)
01605               {
01606                 result.push_back(j);
01607                 break;
01608               }
01609             }
01610           }
01611           break;
01612         default:
01613           // First, find one point of the contour
01614           forall(const junction& j, junctions())
01615           {
01616             if(border(j))
01617             {
01618               result.push_back(j);
01619               forall( const cell& c , neighbors(j))
01620               {
01621                 const junction& jn = nextTo(c, j);
01622                 int nb_common_cells = 0;
01623                 forall( const cell& cn , neighbors(jn))
01624                 {
01625                   if(edge(j, cn))
01626                     nb_common_cells++;
01627                 }
01628                 if(nb_common_cells == 1)
01629                 {
01630                   result.push_back(jn);
01631                   return nextContourVertex(j, c, jn, result);
01632                 }
01633               }
01634               return result;
01635             }
01636           }
01637       }
01638       return result; // Should not be reached!
01639     }
01640 
01641 
01642   };
01643 
01644   template <typename CplxGraph>
01645     void create_cplxgraph_methods(CplxGraph& G)
01646     {
01647       if(G.size())
01648       {
01649         if(G.valence(G.any_vertex1()) > G.size())
01650         {
01651           graph::create_bigraph_methods(G);
01652           typename CplxGraph::cell c = G.any_cell();
01653           typename CplxGraph::junction j = G.any_junction();
01654           G.nb_cells();
01655           G.nb_junctions();
01656           G.no_cell();
01657           G.no_junction();
01658           G.get_cell(10);
01659           G.get_junction(10);
01660           G.border(j);
01661           G.border(c);
01662           G.border(c,j);
01663           G.border(j,j);
01664           G.adjacentCell(c, j);
01665           G.adjacentCells(j, j);
01666           G.deleteCell(c);
01667           G.begin_cells();
01668           G.end_cells();
01669           G.begin_junctions();
01670           G.end_junctions();
01671           G.interfaceWall(c,c);
01672           G.interfaceWallSpan(c,c);
01673         }
01674       }
01675     }
01676 
01677 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01678 
01679 #define VVBIGRAPH graph::VVBiGraph<CellContent,JunctionContent,CellJunctionContent,JunctionContent>
01680 #define CPLXGRAPH complex_graph<CellContent,JunctionContent,CellJunctionContent,JunctionCellContent>
01681 #undef VVBIGRAPH
01682 #undef CPLXGRAPH
01683 
01684 #endif // DOXYGEN_SHOULD_SKIP_THIS
01685 
01726   struct InModelDivisionParam
01727   { };
01728 
01744   template <class VVComplex>
01745     DivisionData<typename VVComplex::junction_content> findDivisionPoints(const typename VVComplex::cell& c,
01746                                                                           VVComplex& T,
01747                                                                           const InModelDivisionParam& param)
01748     {
01749       IMPORT_COMPLEX_MODEL(VVComplex, T);
01750       return model.divisionParameters(c, T, param);
01751     }
01752 
01769   bool FindWallMin(Point3d &v, const Point3d& v1, const Point3d& v2, double mw, double *displacement = 0);
01770 
01785   template <typename VVComplex>
01786     void FindOppositeWall(const typename VVComplex::cell& c,
01787                           DivisionData<typename VVComplex::junction_content>& result,
01788                           VVComplex& T,
01789                           double cellWallMin, bool strictCellWallMin)
01790     {
01791       IMPORT_COMPLEX_VERTICES(VVComplex);
01792       IMPORT_COMPLEX_MODEL(VVComplex, T);
01793       double mindis = HUGE_VAL;
01794       const Point3d& cnml = model.normal(c);
01795       Point3d minu = result.pu;
01796       const Point3d& cpos = model.position(c);
01797       junction p_u1 = result.u1;
01798       junction p_u2 = T.S.nextTo(c, p_u1);
01799       forall( const junction& tv1 , T.S.neighbors(c))
01800       {
01801         const junction& tv2 = T.S.nextTo(c, tv1);
01802         const Point3d& v1 = model.position(tv1);
01803         const Point3d& v2 = model.position(tv2);
01804         if(tv2 == p_u2)
01805         {
01806           continue;
01807         }
01808         // Keep uc close to same plane as v1v2
01809         Point3d uc = cpos - minu;
01810         uc -= (uc * cnml) * cnml;
01811         Point3d n = cnml^uc;
01812         uc += minu;
01813         double s;
01814         Point3d v;
01815         bool found = geometry::planeLineIntersection(v, s, uc, n, v1, v2);
01816         if(found)
01817         {
01818           double dis;
01819           if(FindWallMin(v, v1, v2, cellWallMin, &dis) or not strictCellWallMin)
01820           {
01821             if(dis < mindis)
01822             {
01823               mindis = dis;
01824               result.pv = v;
01825               result.v1 = tv1;
01826             }
01827             if(dis == 0) break;
01828           }
01829         }
01830       }
01831     }
01832 
01837   template <typename VVComplex>
01838     void testDivisionOnVertices(const typename VVComplex::cell& c,
01839                                 DivisionData<typename VVComplex::junction_content>& result,
01840                                 VVComplex& T,
01841                                 double epsilon)
01842     {
01843       IMPORT_COMPLEX_MODEL(VVComplex, T);
01844       double eps_sq = epsilon*epsilon;
01845       if(util::normsq(result.pu-model.position(result.u1)) < eps_sq)
01846       {
01847         result.divide_at_u1 = true;
01848       }
01849       else if(util::normsq(result.pu-model.position(T.S.nextTo(c,result.u1))) < eps_sq)
01850       {
01851         result.u1 = T.S.nextTo(c,result.u1);
01852         result.divide_at_u1 = true;
01853       }
01854       if(util::normsq(result.pv-model.position(result.v1)) < eps_sq)
01855       {
01856         result.divide_at_v1 = true;
01857       }
01858       else if(util::normsq(result.pv-model.position(T.S.nextTo(c,result.v1))) < eps_sq)
01859       {
01860         result.v1 = T.S.nextTo(c,result.v1);
01861         result.divide_at_v1 = true;
01862       }
01863     }
01864 
01871   template <class VVComplex>
01872     Point3d findCenter(const typename VVComplex::cell& c, VVComplex& T)
01873     {
01874       IMPORT_COMPLEX_VERTICES(VVComplex);
01875       IMPORT_COMPLEX_MODEL(VVComplex, T);
01876       // First get average of points as estimate to center
01877       Point3d cest;
01878       forall( const junction& n , T.S.neighbors(c))
01879       {
01880         cest += model.position(n);
01881       }
01882       cest /= T.S.valence(c);
01883       // Average Area * midpoint of each triangle
01884       Point3d cpos;
01885       double sum = 0;
01886       forall( const junction& m , T.S.neighbors(c))
01887       {
01888         const junction& n = T.S.prevTo(c, m);
01889         const Point3d& mpos = model.position(m);
01890         const Point3d& npos = model.position(n);
01891         double ta = geometry::triangleArea(mpos, npos, cest);
01892         cpos += ta * (cest + ((mpos - cest) + (npos - cest))/3.0);
01893         sum += ta;
01894       }
01895       cpos /= sum;
01896 
01897       return cpos;
01898     }
01899 
01900 
01913   template <class VVComplex>
01914     void FindCenter(const typename VVComplex::cell& c, VVComplex& T)
01915     {
01916       IMPORT_COMPLEX_MODEL(VVComplex, T);
01917       const Point3d& cpos = findCenter(c, T);
01918       model.setPosition(c, cpos);
01919     }
01920 
01921 #ifdef USE_ALLOCATOR
01922 #  define ALL_COMPLEX_TEMPLATE_ARGS Model,CellContent,JunctionContent,WallContent,CellEdgeContent,CellJunctionContent,JunctionCellContent,compact,Alloc,LeafClass
01923 #  define MANDATORY_COMPLEX_TEMPLATE_ARGS Model,CellContent,JunctionContent,WallContent,CellEdgeContent,CellJunctionContent,JunctionCellContent,compact,Alloc
01924 #else // USE_ALLOCATOR
01925 #  define ALL_COMPLEX_TEMPLATE_ARGS Model,CellContent,JunctionContent,WallContent,CellEdgeContent,CellJunctionContent,JunctionCellContent,compact,LeafClass
01926 #  define MANDATORY_COMPLEX_TEMPLATE_ARGS Model,CellContent,JunctionContent,WallContent,CellEdgeContent,CellJunctionContent,JunctionCellContent,compact
01927 #endif // USE_ALLOCATOR
01928 
01934   template <typename Model,
01935            typename CellContent, typename JunctionContent,
01936            typename WallContent = graph::_EmptyEdgeContent, typename CellEdgeContent = graph::_EmptyEdgeContent,
01937            typename CellJunctionContent = graph::_EmptyEdgeContent, typename JunctionCellContent = graph::_EmptyEdgeContent,
01938            bool compact = false,
01939 #ifdef USE_ALLOCATOR
01940            typename Alloc = DEFAULT_ALLOC(CellContent),
01941 #endif
01942            typename LeafClass = template_utils::this_class
01943              >
01944   class VVComplex
01945   {
01949     typedef RESOLVE_LEAF_CLASS(LeafClass,VVComplex) leaf_class;
01950 
01951   public:
01952     typedef CellContent cell_content;
01953     typedef JunctionContent junction_content;
01954     typedef WallContent wall_content;
01955     typedef CellJunctionContent cell_junction_content;
01956     typedef JunctionCellContent junction_cell_content;
01957     typedef Model model_t;
01958 
01962     typedef graph::Vertex<CellContent> cell;
01963 
01967     typedef graph::Vertex<JunctionContent> junction;
01968 
01972     typedef graph::VVGraph<CellContent,CellEdgeContent,compact> cell_graph;
01973 
01977     typedef graph::VVGraph<JunctionContent,WallContent,compact> wall_graph;
01978 
01982     typedef VVComplexGraph<CellContent,JunctionContent,CellJunctionContent,JunctionCellContent,compact> complex_graph;
01983 
01987     typedef typename cell_graph::edge_t cell_edge;
01988 
01992     typedef typename cell_graph::arc_t cell_arc;
01993 
01997     typedef typename cell_graph::const_edge_t const_cell_edge;
01998 
02002     typedef typename wall_graph::edge_t wall;
02003 
02007     typedef typename wall_graph::arc_t wall_arc;
02008 
02012     typedef typename wall_graph::const_edge_t const_wall;
02013 
02017     typedef typename complex_graph::edge1_t cell_junction_edge;
02018 
02022     typedef typename complex_graph::const_edge1_t const_cell_junction_edge;
02023 
02027     typedef typename complex_graph::edge2_t junction_cell_edge;
02028 
02032     typedef typename complex_graph::const_edge2_t const_junction_cell_edge;
02033 
02037     typedef typename complex_graph::division_data division_data;
02038 
02042     Model* model;
02043 
02047     cell_graph C;
02051     cell_graph OldC;
02052 
02056     wall_graph W;
02060     wall_graph OldW;
02061 
02065     complex_graph S;
02069     complex_graph OldS;
02070 
02076     bool save_parameters;
02077 
02081     VVComplex(Model *mod)
02082       : model(mod)
02083       , save_parameters(false)
02084       { }
02085 
02089     VVComplex(const VVComplex& other)
02090       : model(other.model)
02091       , C(other.C)
02092       , W(other.W)
02093       , S(other.S)
02094       , save_parameters(other.save_parameters)
02095       { }
02096 
02100     virtual ~VVComplex() {}
02101 
02103     struct AngledJunction
02104     {
02105       junction v;
02106       double angle;
02107 
02108       AngledJunction(const junction& v, double a)
02109         : v(v)
02110         , angle(a)
02111         {}
02112 
02113       AngledJunction(const AngledJunction& copy)
02114         : v(copy.v)
02115         , angle(copy.angle)
02116         {}
02117 
02118       bool operator<(const AngledJunction& other) const
02119       {
02120         if(angle == other.angle)
02121           return v < other.v;
02122         return angle < other.angle;
02123       }
02124 
02125       bool operator==(const AngledJunction& other) const
02126       {
02127         return (angle == other.angle) && (v == other.v);
02128       }
02129     };
02131 
02135     virtual void clear()
02136     {
02137       S.clear();
02138       C.clear();
02139       W.clear();
02140       OldS.clear();
02141       OldC.clear();
02142       OldW.clear();
02143     }
02144 
02148     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3)
02149     {
02150       std::vector<junction> junctions(3, junction(0));
02151       junctions[0] = j1;
02152       junctions[1] = j2;
02153       junctions[2] = j3;
02154       return this->addCell(c, junctions);
02155     }
02156 
02160     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
02161                  const junction& j4)
02162     {
02163       std::vector<junction> junctions(4, junction(0));
02164       junctions[0] = j1;
02165       junctions[1] = j2;
02166       junctions[2] = j3;
02167       junctions[3] = j4;
02168       return this->addCell(c, junctions);
02169     }
02170 
02174     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
02175                  const junction& j4, const junction& j5)
02176     {
02177       std::vector<junction> junctions(5, junction(0));
02178       junctions[0] = j1;
02179       junctions[1] = j2;
02180       junctions[2] = j3;
02181       junctions[3] = j4;
02182       junctions[4] = j5;
02183       return this->addCell(c, junctions);
02184     }
02185 
02189     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
02190                  const junction& j4, const junction& j5, const junction& j6)
02191     {
02192       std::vector<junction> junctions(6, junction(0));
02193       junctions[0] = j1;
02194       junctions[1] = j2;
02195       junctions[2] = j3;
02196       junctions[3] = j4;
02197       junctions[4] = j5;
02198       junctions[5] = j6;
02199       return this->addCell(c, junctions);
02200     }
02201 
02205     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
02206                  const junction& j4, const junction& j5, const junction& j6, const junction& j7)
02207     {
02208       std::vector<junction> junctions(7, junction(0));
02209       junctions[0] = j1;
02210       junctions[1] = j2;
02211       junctions[2] = j3;
02212       junctions[3] = j4;
02213       junctions[4] = j5;
02214       junctions[5] = j6;
02215       junctions[6] = j7;
02216       return this->addCell(c, junctions);
02217     }
02218 
02222     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
02223                  const junction& j4, const junction& j5, const junction& j6, const junction& j7,
02224                  const junction& j8)
02225     {
02226       std::vector<junction> junctions(8, junction(0));
02227       junctions[0] = j1;
02228       junctions[1] = j2;
02229       junctions[2] = j3;
02230       junctions[3] = j4;
02231       junctions[4] = j5;
02232       junctions[5] = j6;
02233       junctions[6] = j7;
02234       junctions[7] = j8;
02235       return this->addCell(c, junctions);
02236     }
02237 
02241     bool addCell(const cell& c, const junction& j1, const junction& j2, const junction& j3,
02242                  const junction& j4, const junction& j5, const junction& j6, const junction& j7,
02243                  const junction& j8, const junction& j9)
02244     {
02245       std::vector<junction> junctions(9, junction(0));
02246       junctions[0] = j1;
02247       junctions[1] = j2;
02248       junctions[2] = j3;
02249       junctions[3] = j4;
02250       junctions[4] = j5;
02251       junctions[5] = j6;
02252       junctions[6] = j7;
02253       junctions[7] = j8;
02254       junctions[8] = j9;
02255       return this->addCell(c, junctions);
02256     }
02257 
02271     template <typename JunctionContainer>
02272       bool addCell(const cell& c, const JunctionContainer& junctions)
02273       {
02274         if(!S.addCell(c, junctions) ) return false;
02275         return this->addCellExtra(c);
02276       }
02277 
02283     virtual bool addCellExtra(const cell& c)
02284     {
02285       bool result = this->addCell_cell_graph(c) && this->addCell_wall_graph(c);
02286       return result;
02287     }
02288 
02290     bool addCell_wall_graph(const cell& c)
02291     {
02292       // Next, connect from the walls
02293       forall(const junction& j, S.neighbors(c)) if(!W.contains(j))
02294         W.insert(j);
02295       forall(const junction& j, S.neighbors(c))
02296       {
02297         const junction& pj = S.prevTo(c, j);
02298         const junction& nj = S.nextTo(c, j);
02299         if(!W.edge(j, pj)) // Then connect j -> pj
02300         {
02301           if(W.valence(j) < 2)
02302           {
02303             W.insertEdge(j, pj);
02304           }
02305           else if(W.edge(j, nj))
02306           {
02307             W.spliceAfter(j, nj, pj);
02308           }
02309           else
02310           {
02311             const cell& nc = S.nextTo(j, c);
02312             if(nc == c)
02313             {
02314               cerr << "There is something wrong: the junction already has more than two neighbors in W but only one cell in c" << endl;
02315               return false;
02316             }
02317             W.spliceBefore(j, S.nextTo(nc, j), pj);
02318           }
02319         }
02320         if(!W.edge(j, nj)) // Then connect j -> nj
02321         {
02322           if(W.valence(j) < 2)
02323           {
02324             W.insertEdge(j, nj);
02325           }
02326           else if(W.edge(j, pj))
02327           {
02328             W.spliceBefore(j, pj, nj);
02329           }
02330           else
02331           {
02332             const cell& pc = S.prevTo(j, c);
02333             if(pc == c)
02334             {
02335               cerr << "There is something wrong: the junction already has more than two neighbors in W but only one cell in c" << endl;
02336               return false;
02337             }
02338             W.spliceAfter(j, S.prevTo(pc, j), nj);
02339           }
02340         }
02341       }
02342       return true;
02343     }
02344 
02345   private:
02346     // Function used in addCell_cell_graph
02347     const cell& acg_find_next_cell(const junction& j, const cell& nc, const cell& c)
02348     {
02349       const junction& nj = S.nextTo(nc, j);
02350       forall( const cell& nnc , S.neighbors(j))
02351       {
02352         if(nnc != nc and nnc != c and S.edge(nj, nnc))
02353           return nnc;
02354       }
02355       return acg_find_next_cell(nj, nc, c);
02356     }
02357 
02358   public:
02359     bool addCell_cell_graph(const cell& c)
02360     {
02361       C.insert(c);
02362       // At last, connect the cells
02363       cell pc(0);
02364       forall(const junction& j, S.neighbors(c))
02365       {
02366         const cell& nc = S.adjacentCell(c, j);
02367         if(nc and !C.edge(c,nc))
02368         {
02369           if(pc)
02370           {
02371             if(!C.spliceAfter(c, pc, nc))
02372             {
02373               cerr << "error in "  << __FILE__ << " line " << __LINE__ << endl;
02374               return false;
02375             }
02376           }
02377           else
02378           {
02379             if(!C.insertEdge(c, nc))
02380             {
02381               cerr << "error in "  << __FILE__ << " line " << __LINE__ << endl;
02382               return false;
02383             }
02384           }
02385           if(C.valence(nc) < 2)
02386           {
02387             if(!C.insertEdge(nc, c))
02388             {
02389               cerr << "error in "  << __FILE__ << " line " << __LINE__ << endl;
02390               return false;
02391             }
02392           }
02393           else
02394           {
02395             const cell& nnc = acg_find_next_cell(j, nc, c);
02396             if(!C.spliceBefore(nc, nnc, c))
02397             {
02398               cerr << "error in "  << __FILE__ << " line " << __LINE__ << endl;
02399               return false;
02400             }
02401           }
02402           pc = nc;
02403         }
02404       }
02405       return true;
02406     }
02408 
02421     template <typename JunctionContainer>
02422       bool addCellUnsorted(const cell& c, const JunctionContainer& j)
02423       {
02424         Point3d normal = model->normal(c);
02425         Point3d cpos, ref, u1, u2;
02426         cpos = model->position(c);
02427         normal.normalize();
02428         bool ref_found = false;
02429         std::set<AngledJunction> sorted;
02430         forall(const junction& v,j)
02431         {
02432           if(ref_found)
02433           {
02434             const Point3d& pos = model->position(v);
02435             Point3d u = pos - cpos;
02436             Point3d proj = normalized(u - (u*normal)*normal);
02437             double cosa = proj*u1;
02438             double sina = (u1^proj)*normal;
02439             double angle = std::atan2(sina, cosa);
02440             sorted.insert(AngledJunction(v, angle));
02441           }
02442           else
02443           {
02444             ref = model->position(v);
02445             u1 = normalized(ref - cpos);
02446             sorted.insert(AngledJunction(v, 0));
02447             ref_found = true;
02448           }
02449         }
02450         std::vector<junction> sorted_list;
02451         forall(const AngledJunction& aj,sorted)
02452         {
02453           sorted_list.push_back(aj.v);
02454         }
02455         return this->addCell(c, sorted_list);
02456       }
02457 
02458     typedef typename complex_graph::division_result_t division_result_t;
02459 
02473     division_result_t divideCell( const cell& c,
02474                                   const division_data& ddata,
02475                                   const std::vector<cell>&to_keep)
02476     {
02477       std::set<junction> junctions_to_keep;
02478 
02479       forall(const cell& k,to_keep)
02480       {
02481         forall( const junction& j , S.neighbors(k))
02482         {
02483           junctions_to_keep.insert(j);
02484         }
02485       }
02486 
02487       OldS = S.subgraph(to_keep, junctions_to_keep);
02488       this->saveSubgraphs(to_keep, junctions_to_keep);
02489 
02490       division_result_t res = S.divideCell(c, ddata);
02491       if(!res)
02492         return res;
02493 
02494       // Set the position of u
02495       if(!ddata.divide_at_u1)
02496       {
02497         const Point3d& pu1 = model->position(res.u1);
02498         const Point3d& pu2 = model->position(res.u2);
02499         double ru = ((ddata.pu-pu1)*(pu2-pu1)) / normsq(pu2-pu1);
02500         model->setPositionHint(res.u, res.u1, res.u2, ru);
02501         model->setPosition(res.u, ddata.pu);
02502       }
02503 
02504       // Set the position of v
02505       if(!ddata.divide_at_v1)
02506       {
02507         const Point3d& pv1 = model->position(res.v1);
02508         const Point3d& pv2 = model->position(res.v2);
02509         double rv = ((ddata.pv-pv1)*(pv2-pv1)) / normsq(pv2-pv1);
02510         model->setPositionHint(res.v, res.v1, res.v2, rv);
02511         model->setPosition(res.v, ddata.pv);
02512       }
02513 
02514       // Set new centers, clear, and update concentrations from parent
02515       //FindCenter(cl, static_cast<leaf_class&>(*this));
02516       //FindCenter(cr, static_cast<leaf_class&>(*this));
02517 
02518       // Connect the other graphs
02519       this->reconnectGraphs(c, res.cl, res.cr, res.u1, res.u2, res.v1, res.v2, res.u, res.v);
02520 
02521       model->updateFromOld(res.cl, res.cr, c, ddata, static_cast<leaf_class&>(*this));
02522       OldS.clear();
02523       this->clearOldGraphs();
02524       return res;
02525     }
02526 
02527     division_result_t divideCell( const cell& c,
02528                                   const division_data& ddata )
02529     {
02530       return divideCell(c, ddata, std::vector<cell>());
02531     }
02532 
02536     template <typename CellContainer>
02537       division_result_t divideCell( const cell& c,
02538                                     const division_data& ddata,
02539                                     const CellContainer& to_keep)
02540       {
02541         std::vector<cell> tk(to_keep.begin(), to_keep.end());
02542         return this->divideCell(c, ddata, tk);
02543       }
02544 
02555     template <typename AlgoParameter>
02556       division_result_t divideCell( const cell& c, // cell to divide
02557                                     const AlgoParameter& params,
02558                                     const std::vector<cell>& to_keep)
02559       {
02560         // Exit if division fails
02561         const division_data& result = findDivisionPoints(c, static_cast<leaf_class&>(*this), params);
02562         if(!result)
02563         {
02564           OldS.clear();
02565           this->clearOldGraphs();
02566           cerr << "Error, division failed" << endl;
02567           return division_result_t();
02568         }
02569 
02570         return divideCell(c, result, to_keep);
02571       }
02572 
02573     void reconnectWallGraph(const junction& u1, const junction& u2,
02574                             const junction& v1, const junction& v2,
02575                             const junction& nu, const junction nv)
02576     {
02577       // First, update W
02578       if(nu != u1)
02579         algorithms::insert(u1, u2, W, nu);
02580       if(nv != v1)
02581         algorithms::insert(v1, v2, W, nv);
02582 
02583       W.spliceAfter(nu, u2, nv);
02584       W.spliceAfter(nv, v2, nu);
02585     }
02586 
02587     void reconnectCellGraph(const cell& cl, const cell& cr, const cell& c)
02588     {
02589       // Then C
02590       C.insert(cl);
02591       C.insert(cr);
02592 
02593       connectFromJunctions(c, cl, cr);
02594       connectFromJunctions(c, cr, cl);
02595 
02596       C.erase(c);
02597     }
02598 
02607     virtual void reconnectGraphs(const cell& c, const cell& cl, const cell& cr,
02608                                  const junction& u1, const junction& u2,
02609                                  const junction& v1, const junction& v2,
02610                                  const junction& nu, const junction& nv)
02611     {
02612       reconnectWallGraph(u1, u2, v1, v2, nu, nv);
02613       reconnectCellGraph(cl, cr, c);
02614     }
02615 
02619     template <typename AlgoParameter, typename CellContainer>
02620       division_result_t divideCell( const cell& c, // cell to divide
02621                                     const AlgoParameter& params,
02622                                     const CellContainer& to_keep )
02623       {
02624         std::vector<cell> tk(to_keep.begin(), to_keep.end());
02625         return this->divideCell(c, params, tk);
02626       }
02627 
02634     virtual void saveSubgraphs(const std::vector<cell>& cells_to_keep,
02635                                const std::set<junction>& junctions_to_keep)
02636     {
02637       OldC = C.subgraph(cells_to_keep);
02638       OldW = W.subgraph(junctions_to_keep);
02639     }
02640 
02645     virtual void clearOldGraphs()
02646     {
02647       OldC.clear();
02648       OldW.clear();
02649     }
02650 
02656     division_result_t divideCell( const cell& to_divide, // cell to divide
02657                                   const division_data& params,
02658                                   const cell& cell_kept )
02659     {
02660       std::vector<cell> k;
02661       k.push_back(cell_kept);
02662       return this->divideCell(to_divide, params, k);
02663     }
02664 
02670     template <typename AlgoParameter>
02671       division_result_t divideCell( const cell& to_divide, // cell to divide
02672                                     const AlgoParameter& params,
02673                                     const cell& cell_kept )
02674       {
02675         std::vector<cell> k;
02676         k.push_back(cell_kept);
02677         return this->divideCell(to_divide, params, k);
02678       }
02679 
02683     void deleteCell(const cell& c)
02684     {
02685       const std::vector<junction>& deleted =  S.deleteCell(c);
02686       this->deleteCellInGraphs(c, deleted);
02687     }
02688 
02693     virtual void deleteCellInGraphs(const cell& c, const std::vector<junction>& deleted)
02694     {
02695       C.erase(c);
02696       forall(const junction& j,deleted)
02697         W.erase(j);
02698     }
02699 
02708     std::pair<junction, junction> mergeCells(const cell& c1, const cell& c2)
02709     {
02710       std::vector<junction> deleted_junctions;
02711       std::pair<junction,junction> result = S.mergeCells(c1, c2, &deleted_junctions);
02712 
02713       const junction& j1 = result.first;
02714       const junction& j2 = result.second;
02715 
02716       // Remove junctions from W
02717       forall(const junction& j, deleted_junctions)
02718       {
02719         W.erase(j);
02720       }
02721       W.spliceAfter(j1, S.prevTo(c1, j1), j2);
02722       W.spliceBefore(j2, S.nextTo(c1, j2), j1);
02723 
02724       // Update cell graph
02725       const cell& after = C.nextTo(c1, c2);
02726       forall(const cell& c, C.neighbors(c2, C.nextTo(c2, c1)))
02727       {
02728         if(c == c1) break;
02729         C.spliceBefore(c1, after, c);
02730         C.replace(c, c2, c1);
02731       }
02732 
02733       // Erase c2 from C and S
02734       C.erase(c2);
02735 
02736       return result;
02737     }
02738 
02739 
02743     const cell& adjacentCell(const cell& c, const junction& j) const
02744     {
02745       return S.adjacentCell(c, j);
02746     }
02747 
02754     std::pair<cell,cell> adjacentCells(const junction& j1, const junction& j2) const
02755     {
02756       return S.adjacentCells(j1, j2);
02757     }
02758 
02763     const junction& interfaceWall(const cell& c1, const cell& c2) const
02764     {
02765       return S.interfaceWall(c1, c2);
02766     }
02767 
02774     std::pair<junction, junction> interfaceWallSpan(const cell& c1, const cell& c2) const
02775     {
02776       return S.interfaceWallSpan(c1, c2);
02777     }
02778 
02782     const junction& splitWall(const junction& j1, const junction& j2, const junction& x = junction(0))
02783     {
02784       const junction& j = algorithms::insert(j1, j2, W, x);
02785       S.splitWall(j1, j2, j);
02786       this->splitWallExtra(j1, j2, j);
02787       return j;
02788     }
02789 
02793     const junction& splitWall(const cell& c, const junction& j1, const junction& x = junction(0))
02794     {
02795       const junction& j2 = S.nextTo(c, j1);
02796       const junction& j = algorithms::insert(j1, j2, W, x);
02797       S.splitWall(c, j1, j);
02798       this->splitWallExtra(j1, j2, j);
02799       return j;
02800     }
02801 
02808     virtual void splitWallExtra(const junction& , const junction& , const junction& ) { }
02809 
02816     bool deleteJunction(const junction& j)
02817     {
02818       size_t nb_cells = S.valence(j);
02819       size_t nb_junctions = W.valence(j);
02820       if(nb_cells > 2)
02821         return false;
02822       if(nb_cells == 2 and nb_junctions != 2)
02823         return false;
02824       if(nb_cells > 0)
02825       {
02826         const cell& c = S.anyIn(j);
02827         const junction& pj = S.prevTo(c, j);
02828         const junction& nj = S.nextTo(c, j);
02829         W.replace(pj, j, nj);
02830         W.replace(nj, j, pj);
02831       }
02832       W.erase(j);
02833       S.erase(j);
02834       this->deleteJunctionExtra(j);
02835       return true;
02836     }
02837 
02841     virtual void deleteJunctionExtra(const junction& /*j*/) {}
02842 
02846     bool border(const cell& c) const
02847     {
02848       size_t nb_walls = 0;
02849       forall(const junction& j, S.neighbors(c))
02850       {
02851         if(W.valence(j) > 2)
02852           nb_walls++;
02853       }
02854       return C.empty(c) or nb_walls != C.valence(c);
02855     }
02856 
02860     bool border(const junction& j) const
02861     {
02862       return S.valence(j) != W.valence(j);
02863     }
02864 
02868     bool border(const cell& c, const junction &j ) const
02869     {
02870       return S.border(c, j);
02871     }
02872 
02876     bool border(const junction& j1, const junction& j2) const
02877     {
02878       return S.border(j1, j2);
02879     }
02880 
02890     bool serialize(storage::VVEStorage&);
02891 
02892   protected:
02899     void connectFromJunctions( const cell& old_c, const cell& c, const cell& cc)
02900     {
02901       C.insertEdge(c, cc);
02902       // Connect c to its neighbors
02903       cell pn(0);
02904       forall( const junction& jn , S.neighbors(c))
02905       {
02906         const junction& jp = S.prevTo(c, jn);
02907         const cell& n = S.nextTo(jn, c);
02908         // If we are not at a border ...
02909         if(n != c and S.edge(jp, n))
02910         {
02911           if(n != cc)
02912           {
02913             // Two cases:
02914             // 1 - old_c is in the neighborhood of n -> we replace it by the 
02915             // current
02916             // 2 - cc is in the neighborhood of n -> we figure if we should 
02917             // place it before or after
02918             cell_edge e = C.replace(n, old_c, c);
02919             if(e.isNull()) // c was not in the neighborhood of n
02920             {
02921               const cell& cc1 = S.nextTo(jp, c);
02922               if(cc1 == cc)
02923               {
02924                 C.spliceBefore(n, cc, c);
02925               }
02926               else
02927               {
02928                 C.spliceAfter(n, cc, c);
02929               }
02930             }
02931             if(pn.isNull())
02932             {
02933               C.insertEdge(c, n);
02934             }
02935             else
02936             {
02937               C.spliceAfter(c, pn, n);
02938             }
02939           }
02940           pn = n;
02941         }
02942       }
02943     }
02944 
02945   };
02946 
02947   template <typename Complex>
02948     std::vector<typename Complex::junction> contour(const Complex& T)
02949     {
02950       return T.S.contour();
02951     }
02952 
02953 }
02954 
02955 #endif // VVELIB_ALGORITHMS_COMPLEX_H
02956 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Fri May 31 15:37:49 2013 for VVE by  doxygen 1.6.3