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