/*------------------------------------------------------------------------------*/ void GW_VoronoiMesh::PerformLocalFastMarching( GW_GeodesicMesh& Mesh, GW_VoronoiVertex& Vert ) { Mesh.ResetGeodesicMesh(); /* set up a boundary to stop the front propagation */ for( GW_FaceIterator it=Vert.BeginFaceIterator(); it!=Vert.EndFaceIterator(); ++it ) { GW_Face* pFace = *it; GW_ASSERT( pFace!=NULL ); GW_VoronoiVertex* pVert1 = (GW_VoronoiVertex*) pFace->GetNextVertex( Vert ); GW_VoronoiVertex* pVert2 = (GW_VoronoiVertex*) pFace->GetNextVertex( *pVert1 ); GW_ASSERT( pVert1!=NULL ); GW_ASSERT( pVert2!=NULL ); GW_U32 nID = GW_Vertex::ComputeUniqueId( *pVert1, *pVert2 ); /* get the geodesic edge */ GW_ASSERT( VertexPathMap_.find(nID)!=VertexPathMap_.end() ); T_GeodesicVertexList* pVertexGeodesicEdge = VertexPathMap_[nID]; GW_ASSERT( pVertexGeodesicEdge!=NULL ); if( pVertexGeodesicEdge!=NULL ) for( IT_GeodesicVertexList VertIt = pVertexGeodesicEdge->begin(); VertIt!=pVertexGeodesicEdge->end(); ++VertIt ) { GW_GeodesicVertex* pGeodesicVert = *VertIt; pGeodesicVert->SetStoppingVertex( GW_True ); } } /* now compute the fast marching */ GW_ASSERT( Vert.GetBaseVertex()!=NULL ); Mesh.PerformFastMarching( Vert.GetBaseVertex() ); }
/*------------------------------------------------------------------------------*/ void GW_VoronoiMesh::ComputeVertexParameters( GW_GeodesicMesh& Mesh ) { for( GW_U32 i=0; i<Mesh.GetNbrVertex(); ++i ) { GW_GeodesicVertex* pVert = (GW_GeodesicVertex*) Mesh.GetVertex( i ); GW_ASSERT( pVert!=NULL ); GW_Float d0, d1, d2; GW_VoronoiVertex* pVornoiVert0 = pVert->GetParameterVertex( 0, d0 ); GW_VoronoiVertex* pVornoiVert1 = pVert->GetParameterVertex( 1, d1 ); GW_VoronoiVertex* pVornoiVert2 = pVert->GetParameterVertex( 2, d2 ); if( pVornoiVert0!=NULL && pVornoiVert1!=NULL && pVornoiVert2!=NULL ) { GW_ASSERT( pVornoiVert0!=NULL ); GW_ASSERT( pVornoiVert1!=NULL ); GW_ASSERT( pVornoiVert2!=NULL ); GW_GeodesicVertex* pVert0 = pVornoiVert0->GetBaseVertex(); GW_GeodesicVertex* pVert1 = pVornoiVert1->GetBaseVertex(); GW_GeodesicVertex* pVert2 = pVornoiVert2->GetBaseVertex(); GW_ASSERT( pVert0!=NULL ); GW_ASSERT( pVert1!=NULL ); GW_ASSERT( pVert2!=NULL ); GW_U32 nID0 = GW_Vertex::ComputeUniqueId( *pVornoiVert1, *pVornoiVert2 ); GW_U32 nID1 = GW_Vertex::ComputeUniqueId( *pVornoiVert0, *pVornoiVert2 ); GW_U32 nID2 = GW_Vertex::ComputeUniqueId( *pVornoiVert0, *pVornoiVert1 ); if( GeodesicDistanceMap_.find(nID0)!=GeodesicDistanceMap_.end() && GeodesicDistanceMap_.find(nID1)!=GeodesicDistanceMap_.end() && GeodesicDistanceMap_.find(nID2)!=GeodesicDistanceMap_.end() ) { /* length of each triangle segment. */ GW_Float l0 = GeodesicDistanceMap_[nID0]; GW_Float l1 = GeodesicDistanceMap_[nID1]; GW_Float l2 = GeodesicDistanceMap_[nID2]; /* now use Heron rule to compute parameter */ GW_Float a0 = GW_Maths::ComputeTriangleArea( l0, d1, d2 ); GW_Float a1 = GW_Maths::ComputeTriangleArea( d0, l1, d2 ); GW_Float a2 = GW_Maths::ComputeTriangleArea( d0, d1, l2 ); GW_Float t = GW_Maths::ComputeTriangleArea( l0, l1, l2 ); // area of the big triangle GW_Float a = a0 + a1 + a2; GW_ASSERT( a>GW_EPSILON ); /* test if the point is outside */ if( a1+a2>t ) pVert->SetParameterVertex( 0, a1/(a1+a2), a2/(a1+a2) ); else if( a0+a2>t ) pVert->SetParameterVertex( a0/(a0+a2), 0, a2/(a0+a2) ); else if( a0+a1>t ) pVert->SetParameterVertex( a0/(a0+a1), a1/(a0+a1), 0 ); else { /* the point is inside the triangle */ pVert->SetParameterVertex( a0/a, a1/a, a2/a ); } pVert->SetParameterVertex( a0/a, a1/a, a2/a ); } else { pVert->SetParameterVertex( 0, 0, 0 ); } } } /* fix parameter for voronoi vertex */ for( GW_U32 i=0; i<this->GetNbrVertex(); ++i ) { GW_VoronoiVertex* pVoronoiVert0 = (GW_VoronoiVertex*) this->GetVertex( i ); GW_ASSERT( pVoronoiVert0!=NULL ); GW_GeodesicVertex* pVert = pVoronoiVert0->GetBaseVertex(); GW_ASSERT( pVert!=NULL ); GW_Face* pFace = pVoronoiVert0->GetFace(); GW_ASSERT( pFace!=NULL ); GW_VoronoiVertex* pVoronoiVert1 = (GW_VoronoiVertex*) pFace->GetNextVertex( *pVoronoiVert0 ); GW_ASSERT( pVoronoiVert1!=NULL ); GW_VoronoiVertex* pVoronoiVert2 = (GW_VoronoiVertex*) pFace->GetNextVertex( *pVoronoiVert1 ); GW_ASSERT( pVoronoiVert2!=NULL ); pVert->ResetParametrizationData(); pVert->AddParameterVertex( *pVoronoiVert0, 1 ); pVert->AddParameterVertex( *pVoronoiVert1, 0 ); pVert->AddParameterVertex( *pVoronoiVert2, 0 ); } /* find the center of each voronoi face */ CentralParameterMap_.clear(); T_FloatMap BestVertexValue; for( GW_U32 i=0; i<Mesh.GetNbrVertex(); ++i ) { GW_GeodesicVertex* pVert = (GW_GeodesicVertex*) Mesh.GetVertex( i ); GW_ASSERT( pVert!=NULL ); GW_Float a,b,c; GW_VoronoiVertex* pVert0 = pVert->GetParameterVertex( 0, a ); GW_ASSERT( pVert0!=NULL ); GW_VoronoiVertex* pVert1 = pVert->GetParameterVertex( 1, b ); GW_ASSERT( pVert1!=NULL ); GW_VoronoiVertex* pVert2 = pVert->GetParameterVertex( 2, c ); if( pVert2!=NULL ) { GW_Float rBestDist = GW_INFINITE; GW_U32 nID = GW_Vertex::ComputeUniqueId( *pVert0, *pVert1, *pVert2 ); if( BestVertexValue.find(nID)!=BestVertexValue.end() ) rBestDist = BestVertexValue[nID]; GW_Float rDist = GW_ABS(a - 1.0/3.0) + GW_ABS(b - 1.0/3.0) + GW_ABS(c - 1.0/3.0); if( rDist<rBestDist ) { BestVertexValue[nID] = rDist; CentralParameterMap_[nID] = pVert; } } } }