From 3f2d58a60eb95b7a0205b04e74d6f0eb840d8edf Mon Sep 17 00:00:00 2001 From: nicopietroni Date: Tue, 1 Jun 2004 09:45:29 +0000 Subject: [PATCH] first release edge split --- vcg/complex/tetramesh/edge_split.h | 473 +++++++++++++++++++++++++++++ 1 file changed, 473 insertions(+) create mode 100644 vcg/complex/tetramesh/edge_split.h diff --git a/vcg/complex/tetramesh/edge_split.h b/vcg/complex/tetramesh/edge_split.h new file mode 100644 index 00000000..bf560018 --- /dev/null +++ b/vcg/complex/tetramesh/edge_split.h @@ -0,0 +1,473 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History +****************************************************************************/ + +#include +#include +#include +namespace vcg{ +namespace tetra{ + +/** \addtogroup tetramesh */ +/*@{*/ +/// This Class is used for split the edges + +template +class EdgeSplit + { + public: + /// The tetrahedral mesh type + typedef typename TETRA_MESH_TYPE TetraMeshType; + /// The tetrahedron type + typedef typename TetraMeshType::TetraType TetraType; + /// The vertex type + typedef typename TetraType::VertexType VertexType; + /// The vertex iterator type + typedef typename TetraMeshType::VertexIterator VertexIterator; + /// The tetra iterator type + typedef typename TetraMeshType::TetraIterator TetraIterator; + /// The coordinate type + typedef typename TetraType::VertexType::CoordType CoordType; + ///the container of tetrahedron type + typedef typename TetraMeshType::TetraContainer TetraContainer; + ///the container of vertex type + typedef typename TetraMeshType::VertexContainer VertexContainer; + /// The HEdgePos type + typedef PosLoop PosType; + /// The topology updater type + typedef vcg::tetra::UpdateTetraTopology Topology; + /// The allocator type + typedef vcg::tetra::Allocator TetraAllocator; + /// Default Constructor + EdgeSplit() + { + }; + + ~EdgeSplit() + { + }; + +private: +///the tetrahedron that must mark as Deleted after substitution +TetraType* _toDel[30]; +///The number of tetrahedrons that are substituted +int _nT; + +Topology _Topo; + +///add a vertex into the edge at distance alfa ( 0 All= Allocator(); + VertexIterator vn=All.AddVertices(tm,1); + vn->Flags()=0; + vn->VTb()=NULL; + vn->VTi()=-1; + vn->P()=(v0->P()*alfa)+(v1->P()*(1.0f-alfa)); + return (&(*vn)); +} + +///set the default v-t topology +void _SetDefultVTTopology(TetraType *t) +{ +unsigned int j; +for (j=0;j<4;j++) +{ + t->TVp(j) = NULL; + t->TVi(j) = -1; +} +} + +/// Transform the vertex index according to rotation of the tetraedron +/// that trasform it in the basic case +static int _GetMapVertEdgeRot(const int &indexE,const int &indexV) + { + static int mapvertedgerot[12][4]={ + {0,3,1,2}, + {0,1,2,3}, + {0,2,3,1}, + {1,3,2,0}, + {1,0,3,2}, + {2,1,3,0}, + + {1,2,0,3}, + {2,3,0,1}, + {3,1,0,2}, + {2,0,1,3}, + {3,2,1,0}, + {3,0,2,1}, + }; + assert ((indexE<12)&&(indexV<4)); + return mapvertedgerot[indexE][indexV]; + } + +/// Transform the face index according to rotation of the tetraedron +/// that trasform it in the basic case + static int _GetMapFaceEdgeRot(const int &indexE,const int &indexF) + { + static int mapfaceedgerot[12][4]={ + {1,2,0,3}, + {0,1,2,3}, + {2,0,1,3}, + {3,1,0,2}, + {1,0,3,2}, + {3,0,2,1}, + + {0,3,1,2}, + {2,3,0,1}, + {1,3,2,0}, + {0,2,3,1}, + {3,2,1,0}, + {2,1,3,0}, + }; + assert ((indexE<12)&&(indexF<4)); + return mapfaceedgerot[indexE][indexF]; + } + +/// Returns the rotation sense during the loop on the edge to divide +/// according to rotation of the tetraedron that trasform it in the basic case + static int _GetDirRot(int indexE,int indexF) + { + static int mapfaceedgerot[12][4]={ + {2,0,-1,-1}, + {0,-1,2,-1}, + {-1,2,0,-1}, + {2,-1,-1,0}, + {-1,0,-1,2}, + {-1,-1,2,0}, + + {0,2,-1,-1}, + {2,-1,0,-1}, + {-1,0,2,-1}, + {0,-1,-1,2}, + {-1,2,-1,0}, + {-1,-1,0,2}, + }; + + assert ((indexE<12)&&(indexF<4)); + return mapfaceedgerot[indexE][indexF]; + } + +///Built an Half edge on tetrahedron t using edge edge +PosType _FindPos(TetraType *t,int edge) +{ + int face0=Tetra::FofE(edge,0); + int ve0=Tetra::VofE(edge,0); + PosType pos(t,face0,edge,ve0); + return pos; +} + +///Assert the right order of vertex that compose the tetrahedron +void _AssertOrder(TetraType *t,VertexType *v0,VertexType *v1,VertexType *v2,VertexType *v3) +{ + assert(t->V(0)==v0); + assert(t->V(1)==v1); + assert(t->V(2)==v2); + assert(t->V(3)==v3); +} + +///Connect trought Tetrahedron-Tetrahedron Topology t0 and t1 with faces i0 and i1 +void _ConnectTTTopology(TetraType *t0,int i0,TetraType *t1,int i1) +{ + assert((i0>=0)&&(i0<4)); + assert((i1>=0)&&(i1<4)); + assert((!t0->IsD())&&(!t1->IsD())); + t0->TTp(i0)=t1; + t0->TTi(i0)=i1; + t1->TTp(i1)=t0; + t1->TTi(i1)=i0; + assert( (((t0->TTp(i0))->TTp(t0->TTi(i0)))==t0)); + assert( (((t1->TTp(i1))->TTp(t1->TTi(i1)))==t1)); +} + +///Divide the tetrahadron in pos in two tetrahedrons using the new vertex vnew +void _Divide(PosType pos,VertexType *vnew,TetraType *newtp0,TetraType *newtp1,bool invert) +{ + int curredge=pos.E(); + + //control if the edge vertices arein the right order for the table + if (invert) + curredge+=6; + + //find the new position to vertex according + int ie0=_GetMapVertEdgeRot(curredge,0); + int ie1=_GetMapVertEdgeRot(curredge,2); + int in0=_GetMapVertEdgeRot(curredge,1); + int in1=_GetMapVertEdgeRot(curredge,3); + + //as first the ones that appartain to the selected curredge + VertexType *ve0=pos.T()->V(ie0); + VertexType *ve1=pos.T()->V(ie1); + + //and after the others that will be in the cutting plane + VertexType *vn0=pos.T()->V(in0); + VertexType *vn1=pos.T()->V(in1); + + newtp0->V(0)=ve0; + newtp0->V(1)=vn0; + newtp0->V(2)=vnew; + newtp0->V(3)=vn1; + + newtp1->V(0)=vnew; + newtp1->V(1)=vn0; + newtp1->V(2)=ve1; + newtp1->V(3)=vn1; + + //right order of the vertices +#ifdef _DEBUG + _AssertOrder(newtp0,ve0,vn0,vnew,vn1); + _AssertOrder(newtp1,vnew,vn0,ve1,vn1); + //end asserts +#endif +} + +bool _InvertRotation(PosType pos) +{ + return (pos.V()!=Tetra::VofE(pos.E(),0)); +} + +///substitute the told tetrahedon on VT topology with newtp0 and newtp1 as created +void _SubstituteVTTopology(TetraType *told,TetraType *newtp0,TetraType *newtp1) +{ + _SetDefultVTTopology(newtp0); + _SetDefultVTTopology(newtp1); + + //detach the old tetrahedron from VTtopology + _Topo.DetachVTTopology(told); + //tetrahedron 0 + _Topo.InsertVTTopology(newtp0); + //tetrahedron 1 + _Topo.InsertVTTopology(newtp1); +} + +///control if the connections between tetrahedron created have the right shared vertices +void _ControlConnection(TetraType *oldtp0,TetraType *newtp0) +{ + VertexType *v00=oldtp0->V(0); + VertexType *v01=oldtp0->V(1); + VertexType *v02=oldtp0->V(2); + VertexType *v03=oldtp0->V(3); + + VertexType *v10=newtp0->V(0); + VertexType *v11=newtp0->V(1); + VertexType *v12=newtp0->V(2); + VertexType *v13=newtp0->V(3); + + assert(((v00==v10)&&(v02==v12))||((v00==v12)&&(v02==v10))); + assert(((v01==v13)&&(v03!=v11))||((v01!=v13)&&(v03==v11))); +} + +///set as extern the 4 faces of the tetrahedron +void _SetDefaultTTExtern(TetraType *t) +{ + for (int y=0;y<4;y++) + { + t->TTp(y)=t; + t->TTi(y)=y; + } +} + +///substitute in Tetra Tetra Topology the tetrahedron old_t with new_t in according +///to face and edge + +void _SubstituteTTTopology(TetraType *old_t,TetraType *new_t,int edgerot,int face) +{ + int indexface=_GetMapFaceEdgeRot(edgerot,face); + + if (old_t->IsBorderF(indexface)) + { + new_t->TTp(face)=new_t; + new_t->TTi(face)=face; + } + else + { + TetraType *tetrad=old_t->TTp(indexface); + int fad=old_t->TTi(indexface); + _ConnectTTTopology(new_t,face,tetrad,fad); + assert (!tetrad->IsD()); + } +} + +/// sobstitute the old tetrahedrons that share the edge in pos with new ones +/// that share the vertex vnew that divide the old edge + +void _AddNewTetrahedrons(TetraMeshType &tm,PosType pos,VertexType *vnew) +{ + + TetraType *oldtp0=NULL; + TetraType *oldtp1=NULL; + + TetraType *newtp0; + TetraType *newtp1; + + TetraType *firsttp0=NULL; + TetraType *firsttp1=NULL; + + + int curredge; + int direction=-1; + bool invert=false; + +TetraAllocator All=TetraAllocator(); +pos.Reset(); +_nT=0; + +while (!pos.LoopEnd()) + { + assert(!pos.T()->IsD()); + + invert=_InvertRotation(pos); + + //CREATE THE NEW TETRAHEDRONS + + //create the new ones putting the veritices in the right order + TetraIterator ti=All.AddTetra(tm,2); + newtp0 = &(*ti); + ti++; + newtp1 = &(*ti); + + + _Divide(pos,vnew,newtp0,newtp1,invert); + +#ifdef _DEBUG + if ((oldtp0!=NULL)&&(!pos.Jump())) + _ControlConnection(oldtp0,newtp0); + if ((oldtp1!=NULL)&&(!pos.Jump())) + _ControlConnection(oldtp1,newtp1); +#endif + + // SUBSTITUTE NEW TETRAHEDRONS ON VT TOPOLOGY + if (tm.HasVTTopology()) + _SubstituteVTTopology(pos.T(),newtp0,newtp1); + + + //THEN SET THE T-T TOPOLOGY + + _SetDefaultTTExtern(newtp0); + _SetDefaultTTExtern(newtp1); + + curredge=pos.E(); + if (invert) + curredge+=6; + + //face3 + _SubstituteTTTopology(pos.T(),newtp1,curredge,3); + + //face1 + _SubstituteTTTopology(pos.T(),newtp0,curredge,1); + + //now I set t-t topology between themselfes + + _ConnectTTTopology(newtp0,3,newtp1,1); + + if (pos.Jump()) + { + vnew->SetB(); + oldtp0=NULL; + oldtp1=NULL; + } + + direction=_GetDirRot(curredge,pos.F()); + assert(direction!=-1); + //control the direction of moving + if ((oldtp0!=NULL)&&(oldtp1!=NULL)) + { + //direction=_GetDirRot(oldtp0,newtp0); + + //find direction of moving + if (direction==0) + { + _ConnectTTTopology(oldtp0,0,newtp0,2); + _ConnectTTTopology(oldtp1,0,newtp1,2); + } + else + if (direction==2) + { + _ConnectTTTopology(oldtp0,2,newtp0,0); + _ConnectTTTopology(oldtp1,2,newtp1,0); + } + } + //assign if it is the first one + if (firsttp0==NULL) + firsttp0=newtp0; + if (firsttp1==NULL) + firsttp1=newtp1; + + oldtp0=newtp0; + oldtp1=newtp1; + + _toDel[_nT]=pos.T(); + _nT++; + pos.NextT(); + } + + //at the end I finish the connections + if (!(pos.Jump())&&(direction==0)&&(firsttp0!=NULL)&&(firsttp1!=NULL)&&(oldtp0!=NULL)&&(oldtp1!=NULL)) + { + _ConnectTTTopology(oldtp0,0,firsttp0,2); + _ConnectTTTopology(oldtp1,0,firsttp1,2); + } + else if (!(pos.Jump())&&(direction==2)&&(firsttp0!=NULL)&&(firsttp1!=NULL)&&(oldtp0!=NULL)&&(oldtp1!=NULL)) + { + _ConnectTTTopology(oldtp0,2,firsttp0,0); + _ConnectTTTopology(oldtp1,2,firsttp1,0); + } + else if (pos.Jump()) + vnew->SetB(); + +} + +///Mark as deleted the tetrahedron that must be substituted +void _DeleteOldTetra() +{ + for (int i=0;i<_nT;i++) + _toDel[i]->SetD(); +} + +//========================================================================= + +public: + +/// Split the edge with local remeshing +/// Tetrahedron-Tetrahedron topology is required +VertexType* DoSplit(TetraMeshType &tm,TetraType *t,int edge,double alfa) +{ + assert(!t->IsD()); + assert(tm.HasTTTopology()); + assert((alfa>0)&&(alfa<1)); + assert((edge>=0)&&(edge<6)); + VertexType *vnew=_AddVertexEdge(tm,*t,edge,alfa); + _AddNewTetrahedrons(tm,_FindPos(t,edge),vnew); + _DeleteOldTetra(); + return(vnew); +} + +};//end class + +}//end namespace tetra +}//end namespace vcg \ No newline at end of file