예제 #1
0
/*------------------------------------------------------------------------------*/
void GW_GeodesicPath::AddVertexToPath( GW_GeodesicVertex& Vert )
{
	pPrevFace_ = pCurFace_;
	GW_Float rBestDistance = GW_INFINITE;
	pCurFace_ = NULL;
	GW_GeodesicVertex* pSelectedVert = NULL;
	for( GW_VertexIterator it = Vert.BeginVertexIterator(); it!=Vert.EndVertexIterator(); ++it )
	{
		GW_GeodesicVertex* pVert = (GW_GeodesicVertex*)  *it;
		if( pVert->GetDistance()<rBestDistance )
		{
			rBestDistance = pVert->GetDistance();
			pSelectedVert = pVert;
			GW_GeodesicVertex* pVert1 = (GW_GeodesicVertex*) it.GetLeftVertex();
			GW_GeodesicVertex* pVert2 = (GW_GeodesicVertex*) it.GetRightVertex();
			if( pVert1!=NULL && pVert2!=NULL )
			{
				if( pVert1->GetDistance()<pVert2->GetDistance() )
					pCurFace_ = (GW_GeodesicFace*) it.GetLeftFace();
				else
					pCurFace_ = (GW_GeodesicFace*) it.GetRightFace();
			}
			else if( pVert1!=NULL )
			{
				pCurFace_ = (GW_GeodesicFace*) it.GetLeftFace();
			}
			else
			{
				GW_ASSERT( pVert2!=NULL );
				pCurFace_ = (GW_GeodesicFace*) it.GetRightFace();
			}
		}
	}
	GW_ASSERT( pCurFace_!=NULL );
	GW_ASSERT( pSelectedVert!=NULL );

	GW_GeodesicPoint* pPoint = new GW_GeodesicPoint;
	Path_.push_back( pPoint );
	pPoint->SetVertex1( Vert );
	pPoint->SetVertex2( *pSelectedVert );
	pPoint->SetCoord(1);
	pPoint->SetCurFace( *pCurFace_ );
}
/*------------------------------------------------------------------------------*/
void GW_TriangularInterpolation_Cubic::ComputeLocalGradient(  GW_GeodesicVertex& Vert )
{
    /* compute the total angle */
    GW_Vector3D PrevEdge;
    GW_Float rTotalAngle = 0;
    for( GW_VertexIterator it=Vert.BeginVertexIterator(); it!=Vert.EndVertexIterator(); ++it )
    {
        GW_Vertex* pVert = *it;
        GW_ASSERT( pVert!=NULL );
        if( it==Vert.BeginVertexIterator() )
        {
            PrevEdge = pVert->GetPosition() - Vert.GetPosition();
            PrevEdge.Normalize();
        }
        else
        {
            GW_Vector3D NextEdge = pVert->GetPosition() - Vert.GetPosition();
            NextEdge.Normalize();
            rTotalAngle += acos( NextEdge*PrevEdge );
            PrevEdge = NextEdge;
        }
    }

    /* matrix and RHS for least square minimusation */
    GW_Float M[2][2] = {{0,0},{0,0}};
    GW_Float b[2] = {0,0};

    GW_Float rCurAngle = 0;
    PrevEdge.SetZero();
    for( GW_VertexIterator it=Vert.BeginVertexIterator(); it!=Vert.EndVertexIterator(); ++it )
    {
        GW_GeodesicVertex* pVert = (GW_GeodesicVertex*) *it;
        GW_ASSERT( pVert!=NULL );

        GW_Vector3D Edge = pVert->GetPosition() - Vert.GetPosition();
        GW_Float a = Edge.Norm();
        Edge /= a;

        if( it!=Vert.BeginVertexIterator() )
        {
            /* update the angle */
            rCurAngle += acos( Edge*PrevEdge );
        }

        /* directional gradient estimation */
        GW_Float delta = (pVert->GetDistance() - Vert.GetDistance())/a;
        /* coordonate of the edge on (u,v) [flatened coords] */
        GW_Float eu = a*cos( rCurAngle/rTotalAngle );
        GW_Float ev = a*sin( rCurAngle/rTotalAngle );
        /* update the matrix */
        M[0][0] += eu*eu;
        M[0][1] += eu*ev;
        M[1][0] += eu*ev;
        M[1][1] += ev*ev;
        b[0] += delta*eu;
        b[1] += delta*ev;

        PrevEdge = Edge;
    }

    /* invert the system */
    GW_Float det = M[0][0]*M[1][1] - M[0][1]*M[1][0];
    GW_ASSERT( det!=0 );
    GW_Float gu = 1/det * ( M[1][1]*b[0] - M[0][1]*b[1] );
    GW_Float gv = 1/det * (-M[1][0]*b[0] + M[0][0]*b[1] );

    /* set the gradient in local coords for each surrounding face */
    rCurAngle = 0;
    for( GW_FaceIterator it = Vert.BeginFaceIterator(); it!=Vert.EndFaceIterator(); ++it )
    {
        GW_GeodesicFace* pFace = (GW_GeodesicFace*) *it;
        GW_ASSERT( pFace!=NULL );
        GW_Vertex* pVert1 = it.GetLeftVertex();        GW_ASSERT( pVert1!=NULL );
        GW_Vertex* pVert2 = it.GetRightVertex();    GW_ASSERT( pVert1!=NULL );
        GW_Vector3D e1 = pVert1->GetPosition() - Vert.GetPosition();
        GW_Vector3D e2 = pVert2->GetPosition() - Vert.GetPosition();
        GW_Float a1 = e1.Norm();
        GW_Float a2 = e2.Norm();
        e1 /= a1;
        e2 /= a2;
        GW_Float rInnerAngle = acos( e1*e2 );
        /* flattened position of the two vertex */
        GW_Float p1[2], p2[2];
        p1[0] = cos( rCurAngle );
        p1[1] = sin( rCurAngle );
        p2[0] = cos( rCurAngle+rInnerAngle );
        p2[1] = sin( rCurAngle+rInnerAngle );

        /* we have                    grad = gu*u + gv*v
           we are searching for        grad = g1*p1 + g2*p2, so:
                gu = g1*<p1,u> + g2*<p2,u>
                gv = g1*<p1,v> + g2*<p2,v>
            i.e.
                |p1[0] p2[0]| |g1|   |gu|
                |p1[1] p2[1]|*|g2| = |gv|
        */
        det = p1[0]*p2[1]-p1[1]*p2[0];
        GW_ASSERT( det!=0 );
        GW_Float g1 = 1/det * ( p2[1]*gu - p2[0]*gv );
        GW_Float g2 = 1/det * (-p1[1]*gu + p1[0]*gv );

        /* now compute the gradient in world coords */
        GW_Vector3D LocGrad = e1*g1 + e2*g2;

        GW_TriangularInterpolation_ABC* pInterp = pFace->GetTriangularInterpolation();
        if( pInterp==NULL )
        {
            pInterp = new GW_TriangularInterpolation_Cubic;
            pFace->SetTriangularInterpolation( *pInterp );
        }
        GW_ASSERT( pInterp->GetType()==kCubicTriangulationInterpolation );

        ((GW_TriangularInterpolation_Cubic*) pInterp)->SetLocalGradient( LocGrad, *pFace, Vert );

        rCurAngle += rInnerAngle;
    }

}
/*------------------------------------------------------------------------------*/
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) );
			}
		}
	}
}