www.pudn.com > cad3d.zip > DelaunayTriangulation.cpp


// DelaunayTriangulation.cpp: implementation of the CDelaunayTriangulation class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "Topology\stdafx.h" 
#include "Topology\DelaunayTriangulation.h" 
#include "3DMath\3DSegment.h" 
#include  
/* 
class CDtVertex : public CVertex 
{ 
public: 
    CDtVertex(double x = 0,double y = 0,double z = 0,double w = 1) 
	: CVertex (x,y,z,w) {} 
     
}; 
*/ 
 
#define CLIP_CONCAVE 
 
class CDtEdge : public CSameFacesEdge 
{ 
public: 
    CDtEdge(CDtVertex* pV0 = NULL, CDtVertex* pV1 = NULL) 
	: CSameFacesEdge(pV0, pV1) {} 
     
    C3DSegment	    GetSegment() const  
    { 
	return C3DSegment(GetVertexRef(0), GetVertexRef(1));   
    } 
 
    C3DSegment	    GetNormalSeg() const 
    { 
	C3DPoint mPt( GetSegment().Evaluate(0.5) ); 
	C3DVector v( GetSegment().GetVector()); 
	C3DVector n( -v(1), v(0), 0); 
	C3DPoint oPt( mPt + n); 
	return C3DSegment(mPt, oPt); 
    } 
}; 
 
static C3DSegment sTestSeg; 
static C3DSegment sEdgeSeg; 
static C3DSegment sInnerSeg; 
class CDtTri : public CLinkedPoly 
{ 
public:    
        CDtTri(	CDtVertex* pVer0 = NULL, CDtVertex* pVer1 = NULL, CDtVertex* pVer2 = NULL, 
		CDtEdge* pEdge0 = NULL,CDtEdge* pEdge1 = NULL,CDtEdge* pEdge2 = NULL) 
	    : CLinkedPoly() 
	{ 
	    SetVertex(0, pVer0); 
	    SetVertex(1, pVer1);  
	    SetVertex(2, pVer2); 
	    SetLink(0, pEdge0); 
	    SetLink(1, pEdge1); 
	    SetLink(2, pEdge2); 
	} 
 
	bool	    IsIn(const C3DPoint& rPt, CDtEdge*& pOnEdge)  
	{ 
 
	    C3DSegment testSeg( (*this)(0), rPt); 
	    C3DSegment edgeSeg( GetLinkRef(0).GetSegment() ); 
	     
	    sTestSeg = testSeg; 
	    sEdgeSeg = edgeSeg; 
 
	    CDoubleRange testRange, edgeRange, inRange(0,1); 
	    if ( testSeg.IsPoint() || edgeSeg.IsPoint() )  
		return false; 
	    testRange = testSeg.Intersect(edgeSeg, edgeRange); 
 
	    if ( testRange.IsEmpty() ) 
	    { 
		return false; 
	    } 
	    CHECK( testRange.IsPoint() ); 
	    CHECK( edgeRange.IsPoint() ); 
 
	    if ( inRange.IsIn( edgeRange.GetMax() ) ) 
	    {//the line (*this)(0) intersects the edge(0) 
		C3DPoint intPt = edgeSeg.Evaluate(edgeRange.GetMax()); 
		C3DSegment innerSeg( (*this)(0), intPt); 
		 
		sInnerSeg = innerSeg; 
 
		double dParam = innerSeg.GetEvalParamFast(rPt); 
 
		if ( inRange.IsIn( (math_real)dParam ) ) 
		{ 
		    if ( IsZero(edgeRange.GetMax()) ) 
		    {// point lies on edge #2 (see SetupEdges()) 
			pOnEdge = GetLinkPtr(2); 
		    } 
		    else if ( Equal((math_real)edgeRange.GetMax(), (math_real)1.0) ) 
		    {// point lies on edge #1 (see SetupEdges()) 
			pOnEdge = GetLinkPtr(1); 
		    } 
		    else if ( Equal((math_real)dParam, (math_real)1.0) ) 
		    {// point lies on edge #0 (see SetupEdges()) 
			pOnEdge = GetLinkPtr((top_int)0); 
		    } 
		    else  
		    { 
			pOnEdge = NULL; 
		    } 
		    return true; 
		} 
	    } 
	    return false; 
	} 
	 
	void	    SetupEdges() 
	{ 
	    CHECK(GetLinkPtr(0) != NULL); 
	    CHECK(GetLinkPtr(1) != NULL); 
	    CHECK(GetLinkPtr(2) != NULL); 
 
	    GetLinkRef(2).SetVertex(0, GetVertexPtr((top_int)0) ); 
	    GetLinkRef(2).SetVertex(1, GetVertexPtr(1) ); 
	    CHECK_RES( GetLinkRef(2).SetOnNull(this) ); 
 
	    GetLinkRef(0).SetVertex(0, GetVertexPtr(1) ); 
	    GetLinkRef(0).SetVertex(1, GetVertexPtr(2) ); 
	    CHECK_RES( GetLinkRef(0).SetOnNull(this) ); 
 
	    GetLinkRef(1).SetVertex(0, GetVertexPtr(2) ); 
	    GetLinkRef(1).SetVertex(1, GetVertexPtr((top_int)0) ); 
	    CHECK_RES( GetLinkRef(1).SetOnNull(this) ); 
 
	} 
 
	C3DPoint    GetOutCircleCenter() const 
	{ 
	    C3DSegment n0( GetLinkRef(0).GetNormalSeg() ); 
	    C3DSegment n1( GetLinkRef(1).GetNormalSeg() ); 
 
	    CDoubleRange n0Range, n1Range; 
	    n0Range = n0.Intersect(n1, n1Range); 
	     
	    if ( !n0Range.IsPoint() || !n1Range.IsPoint() ) 
		return C3DVector(); 
	     
	    CHECK( n0Range.IsPoint() ); 
	    CHECK( n1Range.IsPoint() ); 
	    return n0.Evaluate( n0Range.GetMax() ); 
	} 
 
	double	    GetOutCircleRadius() const 
	{ 
	    C3DPoint center( GetOutCircleCenter() ); 
	    if ( center.IsVector() )  
		return 0; 
	    C3DVector v( center - (*this)(0) ); 
	    return v.Norm(); 
	} 
 
	//doesn't check if rPt is on the plane(faster) 
	bool	    IsInOutCircle(const C3DPoint& rPt) const 
	{ 
	    C3DPoint center( GetOutCircleCenter() ); 
	    if ( center.IsVector() )  
		return false; 
 
	    C3DPoint pt(rPt); 
	    pt.Normalize(); 
	    C3DVector v(  pt - center );     
	    if ( IsLt((math_real)v.Norm(), (math_real)GetOutCircleRadius() ) ) 
		return true; 
	    return false; 
	} 
 
	void	    DrawOutCircle()  
	{ 
	    C3DPoint center( GetOutCircleCenter() ); 
	    if ( center.IsVector() )  
		return; 
/* 
	    double dR = GetOutCircleRadius(); 
	     
	    glBegin(GL_LINE_STRIP ); 
	    for (double dFi = 0; dFi < 2*M_PI; dFi+= 0.01) 
	    { 
		double x = center(0) + cos(dFi)*dR; 
		double y = center(1) + sin(dFi)*dR; 
		glVertex3d(x,y,0); 
	    } 
	    glEnd(); 
*/ 
	} 
 
	void	    DrawVoroniDiagram() 
	{ 
	    C3DPoint center( GetOutCircleCenter() ); 
	    if ( center.IsVector() )  
		return; 
/* 
	    glBegin(GL_LINES); 
	    for (int i = 0; i < 3; ++i) 
	    { 
		C3DPoint middle( GetLinkRef(i).GetSegment().Evaluate(0.5) ); 
		glVertex3dv(middle); 
		glVertex3dv(center); 
	    } 
	    glEnd(); 
*/ 
	} 
 
 
	bool	    IsToClip(CDtVertex* pVertices, int nVertCount, double dLimit) 
	{ 
	    C3DPoint center( GetOutCircleCenter() ); 
	    if ( center.IsVector() )  
		return true; 
	    //checks if the center is in/out of the contour 
/*	    CDtEdge* pOnEdge = NULL; 
	    if ( !IsIn(center, pOnEdge) || pOnEdge != NULL) 
		return true; 
*/ 
	    C3DPoint limitPt(center(0), (math_real)dLimit); 
	    C3DSegment ray(center, limitPt); 
	    bool bIsIn = false; 
	    CDoubleRange rayRange, testRange, inRange(0,1); 
	     
 
	    for (int i = 1; i < nVertCount; ++i) 
	    { 
		C3DSegment testSeg(pVertices[i], pVertices[i-1]); 
		rayRange = ray.Intersect(testSeg, testRange); 
		if ( rayRange.IsPoint() && testRange.IsPoint() ) 
		{ 
		    if ( inRange.IsIn(testRange.GetMax()) && inRange.IsIn(rayRange.GetMax()) ) 
		    { 
			bIsIn = !bIsIn; 
		    } 
		} 
	    } 
	    return !bIsIn;	     
	} 
//	void	    SetupVertices(); 
 
}; 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CDelaunayTriangulation::CDelaunayTriangulation (C3DPoint* pVertices, int nVertsCount) 
:   m_nVertsCount(nVertsCount), m_pVertices(pVertices), m_nTrisCount(0), m_pTris(NULL), 
    m_nEdgesCount(0), m_pEdges(NULL) 
{ 
    Init(); 
} 
 
CDelaunayTriangulation::~CDelaunayTriangulation() 
{ 
    delete [] m_pTris; 
    delete [] m_pEdges; 
    delete [] m_pVertices; 
} 
  
void CDelaunayTriangulation::Init() 
{ 
    m_nVertsCount += 3; 
     
    CDtVertex* pTempVertices = m_pVertices; 
    m_pVertices = new CDtVertex[m_nVertsCount]; 
    memcpy(m_pVertices, pTempVertices, sizeof(CDtVertex)*(m_nVertsCount - 3) ); 
 
    int nMaxEdges = 3*m_nVertsCount - 3; 
    int nMaxTris = 2*m_nVertsCount /*- 2*/; 
 
    m_pEdges = new CDtEdge[nMaxEdges]; 
    m_pTris = new CDtTri[nMaxTris]; 
 
    AddLimitTri(); 
} 
 
void CDelaunayTriangulation::AddLimitTri() 
{ 
    double dMaxWidth = 0; 
    for (int i = 0; i < m_nVertsCount - 3; ++i) 
    { 
	for (int j = 0; j < 3; ++j) 
	{ 
	    if ( dMaxWidth < fabs(m_pVertices[i](j)) ) 
	    { 
		dMaxWidth = fabs(m_pVertices[i](j)); 
	    } 
	} 
    } 
 
    //the last three vers... 
    double dLimit = 3.5*dMaxWidth; 
    m_pVertices[m_nVertsCount - 1] = CDtVertex((math_real)dLimit,0,0); 
    m_pVertices[m_nVertsCount - 2] = CDtVertex(0,(math_real)dLimit,0); 
    m_pVertices[m_nVertsCount - 3] = CDtVertex((math_real)-dLimit,(math_real)-dLimit,0); 
 
    //the first tri is the limit tri 
    m_pTris[0].SetVertex(0,&m_pVertices[m_nVertsCount - 1]);  
    m_pTris[0].SetVertex(1,&m_pVertices[m_nVertsCount - 2]);  
    m_pTris[0].SetVertex(2,&m_pVertices[m_nVertsCount - 3]);  
    m_nTrisCount++; 
     
    m_pTris[0].SetLink(0, &m_pEdges[0]); 
    m_pTris[0].SetLink(1, &m_pEdges[1]); 
    m_pTris[0].SetLink(2, &m_pEdges[2]); 
    m_pTris[0].SetupEdges(); 
 
    m_nEdgesCount += 3; 
    m_dLimit = dLimit; 
} 
 
 
CDtTri* CDelaunayTriangulation::FindContainingTri(const CDtVertex& rPt, CDtEdge*& pOnEdge) 
{ 
    //skipps the limit tri 
    for (int i = 0; i < m_nTrisCount; ++i) 
    { 
	if ( m_pTris[i].IsIn(rPt, pOnEdge) ) 
	{ 
	    return (m_pTris + i); 
	} 
    } 
    //returns the limit tri 
    return NULL; 
} 
 
static CDtTri* spTri0; 
static CDtTri* spTri1; 
static CDtTri* spTri2; 
 
void CDelaunayTriangulation::SplitTri(CDtVertex& rPt, CDtTri* pOnTri) 
{ 
    CDtTri tempTri = *pOnTri; 
 
    //pEdgeX is the new edge containing the vertex(X) of the triangle pTri 
    CDtEdge* pEdge0 = m_pEdges + m_nEdgesCount++; 
    CDtEdge* pEdge1 = m_pEdges + m_nEdgesCount++; 
    CDtEdge* pEdge2 = m_pEdges + m_nEdgesCount++; 
 
    pEdge0->SetVertex(0,&rPt); 
    pEdge0->SetVertex(1,tempTri.GetVertexPtr((top_int)0)); 
 
    pEdge1->SetVertex(0,&rPt); 
    pEdge1->SetVertex(1,tempTri.GetVertexPtr(1)); 
 
    pEdge2->SetVertex(0,&rPt); 
    pEdge2->SetVertex(1,tempTri.GetVertexPtr(2)); 
 
    CDtTri* pTri0 = /*(pOnTri == m_pLimitTri) ? (m_pTris + m_nTrisCount++) :*/ pOnTri; 
    CDtTri* pTri1 = m_pTris + m_nTrisCount++; 
    CDtTri* pTri2 = m_pTris + m_nTrisCount++; 
 
    *pTri0 = CDtTri( tempTri.GetVertexPtr(1), tempTri.GetVertexPtr(2), &rPt, 
		      pEdge2, pEdge1, tempTri.GetLinkPtr((top_int)0)); 
    *pTri1 = CDtTri( tempTri.GetVertexPtr(2), tempTri.GetVertexPtr((top_int)0), &rPt, 
		      pEdge0, pEdge2, tempTri.GetLinkPtr(1)); 
    *pTri2 = CDtTri( tempTri.GetVertexPtr((top_int)0), tempTri.GetVertexPtr(1), &rPt, 
		      pEdge1, pEdge0, tempTri.GetLinkPtr(2)); 
     
    tempTri.GetLinkPtr((top_int)0)->ChangeFace(pOnTri, pTri0); 
    tempTri.GetLinkPtr(1)->ChangeFace(pOnTri, pTri1); 
    tempTri.GetLinkPtr(2)->ChangeFace(pOnTri, pTri2); 
 
    pEdge0->SetLeftFace(pTri1); 
    pEdge0->SetRightFace(pTri2); 
 
    pEdge1->SetLeftFace(pTri0); 
    pEdge1->SetRightFace(pTri2); 
     
    pEdge2->SetLeftFace(pTri0); 
    pEdge2->SetRightFace(pTri1); 
 
    spTri0 = pTri0; 
    spTri1 = pTri1;  
    spTri2 = pTri2; 
 
    LegalizeTri(&rPt, pTri0); 
    LegalizeTri(&rPt, pTri1); 
    LegalizeTri(&rPt, pTri2); 
} 
 
void CDelaunayTriangulation::SplitEdge(CDtVertex& rPt, CDtEdge* pOnEdge) 
{ 
    CDtEdge tempEdge = *pOnEdge; 
 
    CDtTri* pLeftTri = tempEdge.GetLeftFacePtr(); 
    CDtTri* pRightTri = tempEdge.GetRightFacePtr(); 
    if ( pLeftTri == NULL || pRightTri == NULL) return; 
 
    CDtTri tempLeftTri(*pLeftTri); 
    CDtTri tempRightTri(*pRightTri); 
 
    //we have 3 new edges and we use one old - this is the pOnEdge, which is splitted 
    CDtEdge* pEdge0 = pOnEdge; 
    CDtEdge* pEdge1 = m_pEdges + m_nEdgesCount++; 
    CDtEdge* pEdge2 = m_pEdges + m_nEdgesCount++; 
    CDtEdge* pEdge3 = m_pEdges + m_nEdgesCount++; 
 
    //setting up the middle edges  
    //pEdge0 & pEdge1 are the edges colinear with pOnEdge 
    pEdge0->SetVertex(0, tempEdge.GetVertexPtr(0) ); 
    pEdge0->SetVertex(1, &rPt ); 
 
    pEdge1->SetVertex(0, &rPt ); 
    pEdge1->SetVertex(1, tempEdge.GetVertexPtr(1) ); 
 
    //pEdge2 splits left triangle in two 
    pEdge2->SetVertex(0, tempLeftTri.GetVertexPtr(pOnEdge) ); 
    pEdge2->SetVertex(1, &rPt); 
 
    //pEdge3 splits rigth triangle in two 
    pEdge3->SetVertex(0, &rPt ); 
    pEdge3->SetVertex(1, tempRightTri.GetVertexPtr(pOnEdge) ); 
     
    //two old tris will be used, as two new too 
    { 
	//the corresponding edges opposite to the splitting edge's vertices 
	//for the 'left' tri 
	CDtEdge* pLtEdge0 = tempLeftTri.GetLinkPtr( tempEdge.GetVertexPtr(0) ); 
	CDtEdge* pLtEdge1 = tempLeftTri.GetLinkPtr( tempEdge.GetVertexPtr(1) ); 
 
	CDtTri* pTri0 = pLeftTri; 
	CDtTri* pTri1 = pRightTri; 
	//pTri0 & pTri1 are the remains of pLeftTri 
	//pLtEdge1 is the edge opposite of pOnEdge's #1 vertex, so now it'll be opposite for rPt 
	*pTri0 = CDtTri(pEdge0->GetVertexPtr(0), &rPt, pEdge2->GetVertexPtr(0), 
			pEdge2,  pLtEdge1 , pEdge0); 
	pLtEdge1->ChangeFace(pLeftTri, pTri0);//this call is unnessasaty, but just in case... 
 
	//pLtEdge0 is the edge opposite of pOnEdge's #0 vertex, so now it'll be opposite for rPt 
	*pTri1 = CDtTri(pEdge1->GetVertexPtr(1), &rPt, pEdge2->GetVertexPtr(0),  
			pEdge2,  pLtEdge0 , pEdge1); 
	pLtEdge0->ChangeFace(pLeftTri, pTri1); 
 
	pEdge2->SetLeftFace(pTri0); 
	pEdge2->SetRightFace(pTri1); 
	pEdge0->SetLeftFace(pTri0); 
    	pEdge1->SetLeftFace(pTri1); 
    } 
    { 
	//the corresponding edges opposite to the splitting edge's vertices 
	//for the 'right' tri 
	CDtEdge* pRtEdge0 = tempRightTri.GetLinkPtr( tempEdge.GetVertexPtr(0) ); 
	CDtEdge* pRtEdge1 = tempRightTri.GetLinkPtr( tempEdge.GetVertexPtr(1) ); 
	//pTri2 & pTri3 are the remains of pRightTri 
	CDtTri* pTri2 = m_pTris + m_nTrisCount++; 
	CDtTri* pTri3 = m_pTris + m_nTrisCount++; 
 
	//pRtEdge1 is the edge opposite of pOnEdge's #1 vertex, so now it'll be opposite for rPt 
	*pTri2 = CDtTri(pEdge0->GetVertexPtr(0), &rPt, pEdge3->GetVertexPtr(1), 
			pEdge3,  pRtEdge1 , pEdge0); 
	pRtEdge1->ChangeFace(pRightTri, pTri2); 
 
	//pRtEdge0 is the edge opposite of pOnEdge's #0 vertex, so now it'll be opposite for rPt 
	*pTri3 = CDtTri(pEdge1->GetVertexPtr(1), &rPt, pEdge3->GetVertexPtr(1),  
			pEdge3,  pRtEdge0 , pEdge1); 
	pRtEdge0->ChangeFace(pRightTri, pTri3); 
 
	pEdge3->SetLeftFace(pTri2); 
	pEdge3->SetRightFace(pTri3); 
	pEdge0->SetRightFace(pTri2); 
	pEdge1->SetRightFace(pTri3); 
    } 
} 
 
void CDelaunayTriangulation::LegalizeTri(CDtVertex* pPt, CDtTri* pTri) 
{ 
    CDtEdge* pTestEdge = pTri->GetLinkPtr(pPt); 
    CDtTri* pTestTri = pTestEdge->GetOtherFacePtr(pTri); 
    if ( pTestTri == NULL) return; 
    CDtVertex *pTestPt = pTestTri->GetVertexPtr(pTestEdge); 
 
//    bool bLegal = true; 
	 
    CDtVertex* pVer0 = pPt;  
    CDtVertex* pVer1 = pTestPt; 
    CDtVertex* pVer2 = pTestEdge->GetVertexPtr(0); 
    CDtVertex* pVer3 = pTestEdge->GetVertexPtr(1);  
 
 
    if ( pTri->IsInOutCircle(*pTestPt) ) 
    {//Flip pTestEdge 
 
	CDtTri* pTri0 = pTri; 
	CDtTri* pTri1 = pTestTri; 
 
	//flips edge 
	pTestEdge->SetVertex(0, pVer0); 
	pTestEdge->SetVertex(1, pVer1); 
 
	CDtEdge* pEdge0 = pTri0->GetLinkPtr(pVer3); 
	CDtEdge* pEdge1 = pTri1->GetLinkPtr(pVer3); 
	CDtEdge* pEdge2 = pTri0->GetLinkPtr(pVer2); 
	CDtEdge* pEdge3 = pTri1->GetLinkPtr(pVer2); 
 
	*pTri0 = CDtTri(pVer0, pVer1, pVer2, pEdge1, pEdge0, pTestEdge); 
	pEdge1->ChangeFace(pTri1, pTri0); 
	//pEdge0->ChangeFace(pTri0, pTri0); 
 
	*pTri1 = CDtTri(pVer0, pVer1, pVer3, pEdge3, pEdge2, pTestEdge); 
	pEdge2->ChangeFace(pTri0, pTri1); 
	//pEdge3->ChangeFace(pTri1, pTri1); 
	LegalizeTri(pPt, pTri0); 
	LegalizeTri(pPt, pTri1); 
 
    } 
} 
/* 
void CDelaunayTriangulation::LegalizeEdge(CDtVertex& rPt, CDtEdge* pEdge) 
{ 
     
 
 
} 
*/ 
 
bool CDelaunayTriangulation::IsLimitTri(const CDtTri& rTri) 
{ 
    for (int i = 0; i < 3; ++i) 
    { 
	if ( IsLimitVertex( rTri.GetVertexPtr(i) ) ) 
	    return true; 
    } 
    return false; 
} 
 
bool CDelaunayTriangulation::IsLimitEdge(const CDtEdge& rEdge) 
{ 
    for (int i = 0; i < 2; ++i) 
    { 
	if ( IsLimitVertex( rEdge.GetVertexPtr(i) ) ) 
	    return true; 
    } 
    return false; 
} 
 
bool CDelaunayTriangulation::IsLimitVertex(const CDtVertex* pVertex) 
{ 
 
    return ((pVertex - m_pVertices) >= (m_nVertsCount - 3)); 
} 
 
void CDelaunayTriangulation::Perform(const COglRenderer& rRc) 
{ 
    int nOrigVertsCount = m_nVertsCount - 3; 
    for (int i = 0; i < nOrigVertsCount; ++i) 
    { 
	CDtVertex& rPt = m_pVertices[i]; 
	CDtEdge* pOnEdge = NULL; 
	CDtTri* pOnTri = FindContainingTri(rPt, pOnEdge); 
	 
//	CHECK(pOnTri != NULL); 
	if ( pOnTri == NULL) 
	    continue; 
 
	if (pOnEdge == NULL) 
	{  
	    SplitTri(rPt, pOnTri); 
	} 
	else 
	{ 
	    SplitEdge(rPt, pOnEdge); 
	} 
    } 
    DrawTris(rRc); 
} 
 
void CDelaunayTriangulation::DrawEdges(const COglRenderer& /*rRc*/) 
{ 
/* 
    rRc.SetDrawColor(1,1,0); 
    glBegin(GL_LINES); 
    for (int i = 0; i < m_nEdgesCount; ++i) 
    { 
	if (IsLimitEdge(m_pEdges[i]) ) 
	    continue; 
	rRc.AddVertex(m_pEdges[i].GetVertexRef(0)); 
	rRc.AddVertex(m_pEdges[i].GetVertexRef(1)); 
    } 
    glEnd(); 
    rRc.SetDrawColor(0,0,1); 
*/ 
} 
 
void CDelaunayTriangulation::DrawTris(const COglRenderer& /*rRc*/) 
{ 
#if 0 
/*     
    CDtVertex testv0(-50,0,0); 
    CDtVertex testv1( 50,0,0); 
    CDtVertex testv2( 0,50,0); 
    CDtEdge e0( &testv0, &testv1); 
    CDtEdge e1( &testv1, &testv2); 
    CDtEdge e2( &testv2, &testv0); 
     
    CDtTri testt(&testv0, &testv1, &testv2, &e1, &e2, &e0); 
    rRc.SetDrawColor(0,0,1); 
    testt.DrawOutCircle(); 
    return; 
*/ 
    rRc.SetDrawColor(0.4f, 0.3f, 0.7f); 
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
    for (int i = 0; i < m_nTrisCount; ++i) 
    { 
/*	 
	if ( (m_pTris + i) ==  spTri0 )  
	    rRc.SetDrawColor(0,0,1); 
	else if ( (m_pTris + i) ==  spTri1 )  
	    rRc.SetDrawColor(0,1,0); 
	else if ( (m_pTris + i) ==  spTri2 )  
	    rRc.SetDrawColor(1,0,0); 
	else 
	{     
//	    rRc.SetDrawColor(0.2,0.2,0.2); 
	    float fI = (float)(i+1)/(float)m_nTrisCount; 
	    rRc.SetDrawColor(fI, fI, fI); 
	} 
*/ 
	if ( IsLimitTri(m_pTris[i]) ) 
	{ 
	    continue; 
	    rRc.SetDrawColor(1,1,0); 
	} 
#ifdef CLIP_CONCAVE	 
	else if ( m_pTris[i].IsToClip( m_pVertices, m_nVertsCount - 3, m_dLimit ) ) 
	{ 
	    continue; 
	} 
#endif 
	else  
	{ 
	    rRc.SetDrawColor(1,1,1); 
	} 
//        rRc.SetDrawColor((float)i/(float)m_nTrisCount, 0.3f, 0.7f); 
/* 
        rRc.BeginVertices(GL_TRIANGLES); 
	    rRc.AddVertex((m_pTris[i])(0)); 
	    rRc.AddVertex((m_pTris[i])(1)); 
	    rRc.AddVertex((m_pTris[i])(2)); 
	rRc.EndVertices(); 
*/ 
/* 
	rRc.SetDrawColor(0.3f,0.3f,0.3f); 
	m_pTris[i].DrawOutCircle(); 
*/ 
	rRc.SetDrawColor(1.0f,0.1f,0.7f); 
	m_pTris[i].DrawVoroniDiagram(); 
 
/*	if ( (m_pTris + i) ==  spTri0 )  
	{ 
	    rRc.SetDrawColor(0,0,1); 
	    m_pTris[i].DrawOutCircle(); 
	    glLineWidth(1); 
	} 
	else if ( (m_pTris + i) ==  spTri1 )  
	{ 
	    rRc.SetDrawColor(0,1,0); 
	    m_pTris[i].DrawOutCircle(); 
	    glLineWidth(1); 
	} 
	else if ( (m_pTris + i) ==  spTri2 )  
	{ 
	    rRc.SetDrawColor(1,0,0); 
	    m_pTris[i].DrawOutCircle(); 
	    glLineWidth(1); 
	} 
*/ 
    } 
    rRc.SetDrawColor(0,0,1); 
/* 
    rRc.BeginVertices(GL_LINES); 
	glLineWidth(10); 
	rRc.SetDrawColor(1,1,0); 
	rRc.AddVertex( sTestSeg.GetPtRef(0) ); 
	rRc.AddVertex( sTestSeg.GetPtRef(1) ); 
	rRc.SetDrawColor(1,1,1); 
	rRc.AddVertex( sEdgeSeg.GetPtRef(0) ); 
	rRc.AddVertex( sEdgeSeg.GetPtRef(1) ); 
	rRc.SetDrawColor(0,1,1); 
	rRc.AddVertex( sInnerSeg.GetPtRef(0) ); 
	rRc.AddVertex( sInnerSeg.GetPtRef(1) ); 
    rRc.EndVertices(); 
    glLineWidth(1); 
*/ 
#endif 
 
}