/*------------------------------------------------------------------------------*/ GW_U32 GW_VoronoiMesh::AddFurthestPoint( T_GeodesicVertexList& VertList,GW_GeodesicMesh& Mesh, GW_Bool bUseRandomStartVertex ) { if( VertList.empty() ) { Mesh.ResetGeodesicMesh(); /* choose 1 point at random */ GW_GeodesicVertex* pStartVertex = (GW_GeodesicVertex*) Mesh.GetRandomVertex(); GW_ASSERT( pStartVertex!=NULL ); if( pStartVertex==NULL ) return 0; VertList.push_back( pStartVertex ); if( !bUseRandomStartVertex ) { /* find furthest point from this one */ GW_VoronoiMesh::PerformFastMarching( Mesh, VertList ); GW_GeodesicVertex* pSelectedVert = GW_VoronoiMesh::FindMaxVertex( Mesh ); GW_ASSERT( pSelectedVert!=NULL ); VertList.push_back( pSelectedVert ); VertList.pop_front(); // remove random choosen vertex Mesh.ResetGeodesicMesh(); } } else { Mesh.RegisterVertexInsersionCallbackFunction( GW_VoronoiMesh::FastMarchingCallbackFunction_VertexInsersion ); /* perform marching */ GW_VoronoiMesh::ResetOnlyVertexState( Mesh ); GW_GeodesicVertex* pStartVert = VertList.back(); GW_ASSERT( pStartVert!=NULL ); Mesh.PerformFastMarching( pStartVert ); /* find intersection points */ GW_GeodesicVertex* pSelectedVert = GW_VoronoiMesh::FindMaxVertex( Mesh ); GW_ASSERT( pSelectedVert!=NULL ); /* find the triangle where the maximum occurs */ #if 0 GW_Face* pMaxFace = GW_VoronoiMesh::FindMaxFace( *pSelectedVert ); GW_ASSERT( pMaxFace!=NULL ); /* this is a critical point */ GW_Float x=1.0f/3, y=1.0f/3, z=1.0f/3; GW_GeodesicVertex* pNewVert = (GW_GeodesicVertex*) Mesh.InsertVertexInFace( *pMaxFace, x,y,z ); pNewVert->SetFront( pSelectedVert->GetFront() ); pNewVert->SetDistance( pSelectedVert->GetDistance() ); #else GW_GeodesicVertex* pNewVert = pSelectedVert; #endif /* compute the real point */ VertList.push_back( pNewVert ); Mesh.RegisterVertexInsersionCallbackFunction( NULL ); } return 1; }
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[] ) { nbr_iter = 0; /* retrive arguments */ if( nrhs<6 ) mexErrMsgTxt("6 or 7 input arguments are required."); if( nlhs<1 ) mexErrMsgTxt("1 or 2 output arguments are required."); // arg1 : vertex vertex = mxGetPr(prhs[0]); nverts = mxGetN(prhs[0]); if( mxGetM(prhs[0])!=3 ) mexErrMsgTxt("vertex must be of size 3 x nverts."); // arg2 : faces faces = mxGetPr(prhs[1]); nfaces = mxGetN(prhs[1]); if( mxGetM(prhs[1])!=3 ) mexErrMsgTxt("face must be of size 3 x nfaces."); // arg3 : W Ww = mxGetPr(prhs[2]); int m = mxGetM(prhs[2]); if( m!=nverts ) mexErrMsgTxt("W must be of same size as vertex."); // arg4 : start_points start_points = mxGetPr(prhs[3]); nstart = mxGetM(prhs[3]); // arg5 : end_points end_points = mxGetPr(prhs[4]); nend = mxGetM(prhs[4]); // arg6 : niter_max niter_max = (int) *mxGetPr(prhs[5]); // arg7 : H if( nrhs>=7 ) { H = mxGetPr(prhs[6]); int m =mxGetM(prhs[6]); if( m>0 && m!=nverts ) mexErrMsgTxt("H must be of size nverts."); if( m==0 ) H = NULL; } else { H = NULL; } // arg8 : L if( nrhs>=8 ) { L = mxGetPr(prhs[7]); int m =mxGetM(prhs[7]); if( m>0 && mxGetM(prhs[7])!=nverts ) mexErrMsgTxt("L must be of size nverts."); if( m==0 ) L = NULL; } else L = NULL; // argument 9: value list if( nrhs>=9 ) { values = mxGetPr(prhs[8]); if( mxGetM(prhs[8])==0 && mxGetN(prhs[8])==0 ) values=NULL; if( values!=NULL && (mxGetM(prhs[8])!=nstart || mxGetN(prhs[8])!=1) ) mexErrMsgTxt("values must be of size nb_start_points x 1."); } else values = NULL; // argument 10: dmax if( nrhs>=9 ) dmax = *mxGetPr(prhs[9]); else dmax = 1e9; // first ouput : distance plhs[0] = mxCreateDoubleMatrix(nverts, 1, mxREAL); D = mxGetPr(plhs[0]); // second output : state plhs[1] = mxCreateDoubleMatrix(nverts, 1, mxREAL); S = mxGetPr(plhs[1]); // second output : segmentation plhs[2] = mxCreateDoubleMatrix(nverts, 1, mxREAL); Q = mxGetPr(plhs[2]); // create the mesh GW_GeodesicMesh Mesh; Mesh.SetNbrVertex(nverts); for( int i=0; i<nverts; ++i ) { GW_GeodesicVertex& vert = (GW_GeodesicVertex&) Mesh.CreateNewVertex(); vert.SetPosition( GW_Vector3D(vertex_(0,i),vertex_(1,i),vertex_(2,i)) ); Mesh.SetVertex(i, &vert); } Mesh.SetNbrFace(nfaces); for( int i=0; i<nfaces; ++i ) { GW_GeodesicFace& face = (GW_GeodesicFace&) Mesh.CreateNewFace(); GW_Vertex* v1 = Mesh.GetVertex((int) faces_(0,i)); GW_ASSERT( v1!=NULL ); GW_Vertex* v2 = Mesh.GetVertex((int) faces_(1,i)); GW_ASSERT( v2!=NULL ); GW_Vertex* v3 = Mesh.GetVertex((int) faces_(2,i)); GW_ASSERT( v3!=NULL ); face.SetVertex( *v1,*v2,*v3 ); Mesh.SetFace(i, &face); } Mesh.BuildConnectivity(); // set up fast marching Mesh.ResetGeodesicMesh(); for( int i=0; i<nstart; ++i ) { GW_GeodesicVertex* v = (GW_GeodesicVertex*) Mesh.GetVertex((GW_U32) start_points[i]); GW_ASSERT( v!=NULL ); Mesh.AddStartVertex( *v ); } Mesh.SetUpFastMarching(); Mesh.RegisterWeightCallbackFunction( WeightCallback ); Mesh.RegisterForceStopCallbackFunction( StopMarchingCallback ); Mesh.RegisterVertexInsersionCallbackFunction( InsersionCallback ); if( H!=NULL ) Mesh.RegisterHeuristicToGoalCallbackFunction( HeuristicCallback ); // initialize the distance of the starting points if( values!=NULL ) for( int i=0; i<nstart; ++i ) { GW_GeodesicVertex* v = (GW_GeodesicVertex*) Mesh.GetVertex((GW_U32) start_points[i]); GW_ASSERT( v!=NULL ); v->SetDistance( values[i] ); } // perform fast marching // display_message("itermax=%d", niter_max); Mesh.PerformFastMarching(); // output result for( int i=0; i<nverts; ++i ) { GW_GeodesicVertex* v = (GW_GeodesicVertex*) Mesh.GetVertex((GW_U32) i); GW_ASSERT( v!=NULL ); D[i] = v->GetDistance(); S[i] = v->GetState(); GW_GeodesicVertex* v1 = v->GetFront(); if( v1==NULL ) Q[i] = -1; else Q[i] = v1->GetID(); } return; }
/*------------------------------------------------------------------------------*/ void GW_VoronoiMesh::FastMarchingCallbackFunction_MeshBuilding( GW_GeodesicVertex& CurVert ) { GW_GeodesicVertex* pFront = CurVert.GetFront(); GW_ASSERT( pFront!=NULL ); /* retrieve the voronoi vertex corresponding to the front */ GW_VoronoiVertex* pVoronoiVert0 = GW_VoronoiMesh::GetVoronoiFromGeodesic( *pFront ); GW_ASSERT( pVoronoiVert0!=NULL ); /* test if this point is a saddle point */ for( GW_VertexIterator it=CurVert.BeginVertexIterator(); it!=CurVert.EndVertexIterator(); ++it ) { GW_GeodesicVertex* pNeighborVert = (GW_GeodesicVertex*) *it; GW_GeodesicVertex* pNeighborFront = pNeighborVert->GetFront(); if( pNeighborFront!=NULL && pNeighborFront!=pFront ) { /* that's it ! */ GW_VoronoiVertex* pVoronoiVert1 = GW_VoronoiMesh::GetVoronoiFromGeodesic( *pNeighborFront ); GW_ASSERT( pVoronoiVert1!=NULL ); if( !pVoronoiVert0->IsNeighbor(*pVoronoiVert1) ) { GW_ASSERT( ! pVoronoiVert1->IsNeighbor(*pVoronoiVert0) ); /* test for manifold structure for the future edge */ GW_U32 nNumTriangle = 0; for( IT_VoronoiVertexList itVoronoi=pVoronoiVert1->BeginNeighborIterator(); itVoronoi!=pVoronoiVert1->EndNeighborIterator(); ++itVoronoi ) { GW_VoronoiVertex* pVoronoiVert2 = *itVoronoi; GW_ASSERT( pVoronoiVert2!=NULL ); if( pVoronoiVert2!=pVoronoiVert0 && pVoronoiVert0->IsNeighbor(*pVoronoiVert2) ) nNumTriangle++; } if( nNumTriangle<=2 ) { pVoronoiVert0->AddNeighbor( *pVoronoiVert1 ); pVoronoiVert1->AddNeighbor( *pVoronoiVert0 ); } /* test for manifold structure on the newly created edges */ for( IT_VoronoiVertexList itVoronoi=pVoronoiVert1->BeginNeighborIterator(); itVoronoi!=pVoronoiVert1->EndNeighborIterator(); ++itVoronoi ) { GW_VoronoiVertex* pVoronoiVert2 = *itVoronoi; GW_ASSERT( pVoronoiVert2!=NULL ); if( pVoronoiVert2!=pVoronoiVert0 && pVoronoiVert0->IsNeighbor(*pVoronoiVert2) ) { /* we are on a newly created face : test for structure integrity */ if( !GW_VoronoiMesh::TestManifoldStructure(*pVoronoiVert0, *pVoronoiVert2) ) { pVoronoiVert0->RemoveNeighbor( *pVoronoiVert1 ); pVoronoiVert1->RemoveNeighbor( *pVoronoiVert0 ); break; } if( !GW_VoronoiMesh::TestManifoldStructure(*pVoronoiVert1, *pVoronoiVert2) ) { pVoronoiVert0->RemoveNeighbor( *pVoronoiVert1 ); pVoronoiVert1->RemoveNeighbor( *pVoronoiVert0 ); break; } } } } else { /* the graph must be undirected */ GW_ASSERT( pVoronoiVert1->IsNeighbor(*pVoronoiVert0) ); } } } }