/*------------------------------------------------------------------------------*/
GW_Float GW_TriangularInterpolation_Cubic::ComputeValue( GW_GeodesicVertex& v0, GW_GeodesicVertex& v1, GW_GeodesicVertex& v2, GW_Float x, GW_Float y )
{
    /* compute local basis */
    GW_Vector3D& e = v2.GetPosition();            // origin
    GW_Vector3D e0 = v0.GetPosition() - e;
    GW_Vector3D e1 = v1.GetPosition() - e;

    /* compute (s,t) the parameter of the point M in basis (w;u,v). We use equality :
        M = w + s u + t v = e + x e0 + y e1     so :
        s = x <e0,u> + y <e1,u> + <e-w,u>
        t = x <e0,v> + y <e1,v> + <e-w,v>
    i.e. :
        |s|   |<e0,u> <e1,u>| |x|   |<e-w,u>|
        |t| = |<e0,v> <e1,v>|*|y| + |<e-w,v>|
    */
    GW_Vector3D trans = e-w;
    /* compute passage matrix */
    GW_Float p00 = e0*u;
    GW_Float p01 = e1*u;
    GW_Float p10 = e0*v;
    GW_Float p11 = e1*v;
    GW_Float s = x*p00 + y*p01 + (trans*u);
    GW_Float t = x*p10 + y*p11 + (trans*v);

    /* now we can compute the value in orthogonal basis (w;u,v) */
    return Coeffs[0] + Coeffs[1]*s + Coeffs[2]*t + Coeffs[3]*s*t + Coeffs[4]*s*s + Coeffs[5]*t*t;
}
/*------------------------------------------------------------------------------*/
void GW_TriangularInterpolation_Linear::ComputeGradient( GW_GeodesicVertex& v0, GW_GeodesicVertex& v1, GW_GeodesicVertex& v2, GW_Float x, GW_Float y, GW_Float& dx, GW_Float& dy )
{
    (void) x;
    (void) y;

    GW_Float d0 = v0.GetDistance();
    GW_Float d1 = v1.GetDistance();
    GW_Float d2 = v2.GetDistance();

    /* compute gradient */
    GW_Vector3D e0 = v0.GetPosition() - v2.GetPosition();
    GW_Vector3D e1 = v1.GetPosition() - v2.GetPosition();
    GW_Float l0 = e0.Norm();
    GW_Float l1 = e1.Norm();
    e0 /= l0;
    e1 /= l1;
    GW_Float dot = e0*e1;
    /* The gradient in direction (e1,e2) is:
            |<grad(d),e0>|   |(d0-d2)/l0|   |gu|
        D = |<grad(d),e1>| = |(d1-d2)/l1| = |gv|
    We are searching for grad(d) = dx e0 + dy e1 wich gives rise to the system :
        | 1  dot|   |dx|
        |dot  1 | * |dy| = D            where dot=<e0,e2>
    ie it is:
        1/det    *    |  1 -dot|*|gu|
                    |-dot  1 | |gv|
    */
    GW_Float det = 1-dot*dot;
    GW_ASSERT( det!=0 );
    GW_Float gu = (d0-d2)/l0;
    GW_Float gv = (d1-d2)/l1;
    dx = 1/det * (     gu - dot*gv  );
    dy = 1/det * (-dot*gu +     gv  );
}
예제 #3
0
/*------------------------------------------------------------------------------*/
void GW_VoronoiVertex::SetBaseVertex( GW_GeodesicVertex& BaseVertex )
{
    GW_SmartCounter::CheckAndDelete( pBaseVertex_ );
    pBaseVertex_ = &BaseVertex;
    pBaseVertex_->UseIt();
    /* copy the parameters of the base mesh */
    this->SetPosition(    BaseVertex.GetPosition() );
    this->SetNormal(    BaseVertex.GetNormal() );
}
/*------------------------------------------------------------------------------*/
void GW_TriangularInterpolation_Quadratic::ComputeGradient( GW_GeodesicVertex& v0, GW_GeodesicVertex& v1, GW_GeodesicVertex& v2, GW_Float x, GW_Float y, GW_Float& dx, GW_Float& dy )
{
	/* compute local basis */
	GW_Vector3D& e = v2.GetPosition();			// origin
	GW_Vector3D e0 = v0.GetPosition() - e;
	GW_Vector3D e1 = v1.GetPosition() - e;
	
	/* compute (s,t) the parameter of the point M in basis (w;u,v). We use equality : 
		M = w + s u + t v = e + x e0 + y e1     so :
		s = x <e0,u> + y <e1,u> + <e-w,u>
		t = x <e0,v> + y <e1,v> + <e-w,v>
	i.e. : 
		|s|   |<e0,u> <e1,u>| |x|   |<e-w,u>|
		|t| = |<e0,v> <e1,v>|*|y| + |<e-w,v>|
	*/
	GW_Vector3D trans = e-w;
	/* compute passage matrix */
	GW_Float p00 = e0*u;
	GW_Float p01 = e1*u;
	GW_Float p10 = e0*v;
	GW_Float p11 = e1*v;
	GW_Float s = x*p00 + y*p01 + (trans*u);
	GW_Float t = x*p10 + y*p11 + (trans*v);

	/* now we can compute the gradient in orthogonal basis (w;u,v) */
	GW_Float gu = Coeffs[1] + Coeffs[3]*t + Coeffs[4]*2*s;
	GW_Float gv = Coeffs[2] + Coeffs[3]*s + Coeffs[5]*2*t;

	/* convert from orthogonal basis to local basis :
		|<e0,u> <e1,u>| |dx|   |gu|
		|<e0,v> <e1,v>|*|dy| = |gv|    
	ie : 
		|dx|           | p11 -p01| |gu|
		|dy| = 1/det * |-p10  p00|*|gv|	*/
	GW_Float rDet = p00*p11 - p01*p10;
	GW_ASSERT( rDet!=0 );
	if( GW_ABS(rDet)>GW_EPSILON )
	{
		dx = 1/rDet * ( p11*gu - p01*gv ) * ~e0;
		dy = 1/rDet * (-p10*gu + p00*gv ) * ~e1;
	}
	else
		dx = dy = 0;
}
/*------------------------------------------------------------------------------*/
void GW_GeodesicDisplayer::DisplayVoronoiPoints( GW_VoronoiMesh& VoronoiMesh, GW_Vector3D& Color, GW_Float rPointSize )
{
	GW_Bool bIsTextureOn = glIsEnabled( GL_TEXTURE_2D );
	glDisable( GL_TEXTURE_2D );

	T_GeodesicVertexList BaseVertexList = VoronoiMesh.GetBaseVertexList();
	glPointSize( (GLfloat) rPointSize );
	glColor( Color );
	glDisable( GL_LIGHTING );
	glBegin( GL_POINTS );
	for( IT_GeodesicVertexList it = BaseVertexList.begin(); it!=BaseVertexList.end(); ++it )
	{
		GW_GeodesicVertex* pVert = *it;
		glVertex( pVert->GetPosition() );
	}
	glEnd();
	glEnable( GL_LIGHTING );

	if( bIsTextureOn )
		glEnable( GL_TEXTURE_2D );
}
/*------------------------------------------------------------------------------*/
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_GeodesicDisplayer::ComputeColor( GW_Vertex& Vert, float* color )
{
	GW_GeodesicVertex& GeoVert = (GW_GeodesicVertex&) Vert;
	GW_BasicDisplayer::ComputeColor( Vert, color );
	if( bProrieties[kGeodesicDistance] )
	{
		if( GeoVert.GetDistance()<GW_INFINITE/2 )
		{
			float dist = (float) GW_SCALE_01(GeoVert.GetDistance(), aMinValue_[kGeodesicDistance], aMaxValue_[kGeodesicDistance]);
			GW_ASSERT(GeoVert.GetFront()!=NULL);
			GW_U32 nID = GeoVert.GetFront()->GetID();
			if( VertexColorMap_.find(nID)!=VertexColorMap_.end() )
			{
				GW_Vector3D colvect = VertexColorMap_[nID];
				color[0] = (GLfloat) colvect[0]*(1-dist);
				color[1] = (GLfloat) colvect[1]*(1-dist);
				color[2] = (GLfloat) colvect[2]*(1-dist);
			}
			else
			{
				/* no colorisation was provided for this front */
				color[0] = color[1] = color[2] = 1-dist;
			}
			if( bProrieties[kGeodesicDistanceStreamColor] )
			{
				GW_Float max = aMaxValue_[kGeodesicDistance];
				if( rColorStreamFixedRadius_>0 )
					max = rColorStreamFixedRadius_;
				GW_Vector3D colvect = this->GetStreamColor( GeoVert.GetDistance(), max );
				color[0] = (GLfloat) colvect[0];
				color[1] = (GLfloat) colvect[1];
				color[2] = (GLfloat) colvect[2];
			}
		}
	}
	if( bProrieties[kMarchingState] )
	{

		if( GeoVert.GetState()==GW_GeodesicVertex::kAlive )
		{
			GW_Vector3D TheColor(1,0,0);	// default color = red
			GW_ASSERT(GeoVert.GetFront()!=NULL);
			GW_U32 nID = GeoVert.GetFront()->GetID();
			if( VertexColorMap_.find(nID)!=VertexColorMap_.end() )
				TheColor = VertexColorMap_[nID];
			color[0] = (float) TheColor[0]*0.5f;
			color[1] = (float) TheColor[1]*0.5f;
			color[2] = (float) TheColor[2]*0.5f;
		}
		if( GeoVert.GetState()==GW_GeodesicVertex::kDead )
		{
			GW_Vector3D TheColor(1,0,0);	// default color = red
			GW_ASSERT(GeoVert.GetFront()!=NULL);
			GW_U32 nID = GeoVert.GetFront()->GetID();
			if( VertexColorMap_.find(nID)!=VertexColorMap_.end() )
				TheColor = VertexColorMap_[nID];
			color[0] = (float) TheColor[0];
			color[1] = (float) TheColor[1];
			color[2] = (float) TheColor[2];
		}
	}
	if( bProrieties[kVertexParametrization] )
	{
#if 1
		GW_U32 nNbrParameter = 0;
		GW_Vector3D Color;
		for( GW_U32 i=0; i<3; ++i )
		{
			GW_Float rParam = 0;
			GW_VoronoiVertex* pParamVert = GeoVert.GetParameterVertex( i, rParam );
			if( pParamVert!=NULL )
			{
				GW_U32 nID = pParamVert->GetBaseVertex()->GetID();
				if( VertexColorMap_.find(nID)!=VertexColorMap_.end() )
				{
					Color += VertexColorMap_[nID]*rParam;
					nNbrParameter++;
				}
			}
		}
		color[0] = (float) Color[0];
		color[1] = (float) Color[1];
		color[2] = (float) Color[2];
		Color /= nNbrParameter;
#else
		for( GW_U32 i=0; i<3; ++i )
		{
			GW_Float rParam;
			GW_VoronoiVertex* pParamVert = GeoVert.GetParameterVertex( i, rParam );
			if( pParamVert!=NULL )
				color[i] = (float) rParam;
			else
				color[i] = 0;
		}
#endif
	}
	if( bProrieties[kStoppingVertex] && GeoVert.GetIsStoppingVertex() )
	{
		color[0] = color[2] = 0;
		color[1] = 1;
	}

#if 0	// just for debugging
	T_GeodesicVertexList& VertList = GW_Toolkit::GetStartVertex();
	if( !VertList.empty() )
	{
		GW_GeodesicVertex* pVert = VertList.front();
		GW_Float rDist = ~(pVert->GetPosition() - GeoVert.GetPosition());
		rDist = GW_ABS( rDist - GeoVert.GetDistance() );
		color[0] = color[1] = color[2] = rDist*5;
	}
#endif
}