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
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
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
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
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
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))
01221 {
01222 if(pj == start)
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))
01237 {
01238 if(nj == start)
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
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
01415 const cell& nu = adjacentCell(c, u1);
01416 const cell& nv = adjacentCell(c, v1);
01417
01418
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
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
01441
01442
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
01462 cell cl, cr;
01463 this->insert(cl);
01464 this->insert(cr);
01465
01466
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
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
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
01523 forall(const junction& j, *deleted_junctions)
01524 {
01525 eraseEdge(c1, j);
01526 }
01527
01528
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
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;
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
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;
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
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
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
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
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))
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))
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
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
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
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
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
02515
02516
02517
02518
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,
02557 const AlgoParameter& params,
02558 const std::vector<cell>& to_keep)
02559 {
02560
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
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
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,
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,
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,
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
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
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
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& ) {}
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
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
02909 if(n != c and S.edge(jp, n))
02910 {
02911 if(n != cc)
02912 {
02913
02914
02915
02916
02917
02918 cell_edge e = C.replace(n, old_c, c);
02919 if(e.isNull())
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