⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 onecontour.cpp

📁 VC实现等值线编成的COM组件的源程序代码
💻 CPP
字号:
// Contour.cpp: implementation of the COneContour class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
//#include "ct.h"
#include "OneContour.h"
#include <math.h>
#include "smooth.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

COneContour::COneContour(CTriangulate *T, double z)
{
	this->T = T;
	zvalue = z;
	segsum_ = 0;
	epsilon = 0.0000001;
}

COneContour::~COneContour()
{
	for (int i=0; i<segsum_; i++)
	{
		delete []points_[i];
		if ( this->smoothmethod_ > 0 )
			delete []afterpoints_[i];
	}
}


//////////////////////////////////////////////////////////////////
//
//  从指定的三角形集合中画等直线
//  查找符合zvalue值的三角形并绘制等值线。。。
//
void COneContour::SearchZValuePointsOfTris()
{
	int MAXPOINTS = 1000;		// 搜索到的点的最大个数,会动态变化
	int MAXUSEDTRIS = 1000;		// 记录UsedTris的最大个数,会动态变化

	int p1, p2, p3;							// 三角形的三个点
	int end1, end2, end1_bak, end2_bak;		// 三角形中有等值线通过的两个边
	double z1, z2, z3;

	bool *flag; // 三角形是否使用过的标记
	
	XYZ *pv = T->GetVertex();			// 散点数据
	int vcount = T->GetVertexCount();
	TRIANGLE *ptri = T->GetTriangle();	// 网格数据
	int tcount = T->GetTriangleCount();
	
	XYZ *tmpxyz;	// 临时数据

	int FirstTri, InTri; 
									
	double zbak;							//zvalue是常量,不能加上一个epsilon,故用此变量
	
	bool HadSearched;						//是否找到了合适的相邻三角形
	int i, j;
	double *dArrayZ;

	flag = new bool[tcount];		// 缺省情况为没有用过
	for (i =0; i< tcount; i++)
		flag[i] = false;

	//以前采用临时调整zvalue的方法,现在采用临时调整
	//数组z的方法.但仍然保留老的方法,因为,同时采用两个方法
	//并不冲突,后者会自然屏蔽前者方法.声明内部变量
	dArrayZ = new double[vcount];
	for(i=0; i<vcount; i++)				
	{								
		dArrayZ[i] = pv[i].z;				//对成员变量数组z进行备份,然后在结束时恢复数组z
		if (pv[i].z == zvalue) 
			pv[i].z += epsilon;				//只在这个地方对Z进行了修改
	}


	// 从序号为FirstTri的三角形的哪一条边开始追踪...
	// 追踪到的第二个三角形序号,正在追踪的三角形序号。
	// 注意:
	//     如果一条边被两个三角形共享,因此,可以从两个方向来追踪下一个三角形。
	//     secondTri用于反向追踪时作为其实三角形使用。
	HadSearched = false;
	for(i = 0; i < tcount; i++)
	{
		//TRACE("%d\n", i);
		// 判断第i个三角形是否已经存在于已用过的三角形列表中?
		if ( flag[i] ) continue;  //判断第i个三角形是否已用过

 		zbak = zvalue;  
		p1 = ptri[i].p1;
		p2 = ptri[i].p2;
		p3 = ptri[i].p3;
		z1 = pv[p1].z;	// 三角形的三个顶点的Z值
		z2 = pv[p2].z;
		z3 = pv[p3].z;

		if (!( ((z1 - zbak) * (z2 - zbak) <= 0) || ((z3 - zbak) * (z2 - zbak) <= 0) ) )	
			continue;						// Z值没有落在此三角形(第i个三角形)内
		HadSearched = true;
		
		//找到了合适的三角形!!!
		//从第一号三角形开始查找满足条件的等值点
		points_[segsum_] = new XYZ[MAXPOINTS];		// 成员变量
		pointscount_[segsum_] = 0;

		if ((z1 - zbak) * (z2 - zbak) < 0)
		{
			end1 = p1;
			end2 = p2;
			if ((z1 -zbak) * (z3 - zbak) < 0)
			{
				end1_bak = p1;
				end2_bak = p3;
			}
			else 
			{
				end1_bak = p2;
				end2_bak = p3;
			}
		}
		else
		{
			end1 = p3;
			end2 = p2;
			end1_bak = p1;
			end2_bak = p3;
		}
		points_[segsum_][pointscount_[segsum_]].x = (pv[end1_bak].x * (zbak - pv[end2_bak].z) + pv[end2_bak].x * (pv[end1_bak].z-zbak) ) / (pv[end1_bak].z - pv[end2_bak].z);
		points_[segsum_][pointscount_[segsum_]].y = (pv[end1_bak].y * (zbak - pv[end2_bak].z) + pv[end2_bak].y * (pv[end1_bak].z-zbak) ) / (pv[end1_bak].z - pv[end2_bak].z);
		pointscount_[segsum_]++;
		points_[segsum_][pointscount_[segsum_]].x = (pv[end1].x * (zbak - pv[end2].z) + pv[end2].x * (pv[end1].z-zbak) ) / (pv[end1].z - pv[end2].z);
		points_[segsum_][pointscount_[segsum_]].y = (pv[end1].y * (zbak - pv[end2].z) + pv[end2].y * (pv[end1].z-zbak) ) / (pv[end1].z - pv[end2].z);
		pointscount_[segsum_]++;
		FirstTri =i;
		InTri = i;
//		UsedTris[UsedTrisCount] = InTri; // "已用过"
//		UsedTrisCount++;
		flag[i] = true;

		//然后从临接三角形中再次查找满足条件的等值点
		for (j=0; j<2; j++) //只循环两次,一次为正向追踪,另外一次为反向追踪
		{
			while(1)
			{
				if ( end1 + end2 == ptri[InTri].p1 + ptri[InTri].p2 ) 
					InTri = ptri[InTri].t3;
				else if ( end1 + end2 == ptri[InTri].p3 + ptri[InTri].p2 ) 
					InTri = ptri[InTri].t1;
				else 
					InTri = ptri[InTri].t2;
				if ( InTri < 0  || flag[InTri] )
					break;  // 不存在邻接三角形,正向追踪无可用的下一个三角形,停止正向追踪

				p3 = ptri[InTri].p1 + ptri[InTri].p2 + ptri[InTri].p3 - end1 - end2;
				z1 = pv[end1].z;
				z3 = pv[p3].z;
				if (( z1 - zvalue ) * ( z3 - zvalue ) <= 0 )
					end2 = p3;
				else
					end1 = p3;
				flag[InTri] = true;

				// 增加等值点
				points_[segsum_][pointscount_[segsum_]].x = (pv[end1].x * (zbak-pv[end2].z) + pv[end2].x * (pv[end1].z-zbak))/(pv[end1].z-pv[end2].z);
				points_[segsum_][pointscount_[segsum_]].y = (pv[end1].y * (zbak-pv[end2].z) + pv[end2].y * (pv[end1].z-zbak))/(pv[end1].z-pv[end2].z);
				pointscount_[segsum_]++;
				ASSERT(pointscount_[segsum_] < 4000); //Debug....
				if ( pointscount_[segsum_] >= MAXPOINTS )	// 重新分配内存
				{
					tmpxyz = points_[segsum_];
					points_[segsum_] = new XYZ[MAXPOINTS + 1000];
					memcpy(points_[segsum_], tmpxyz, sizeof(XYZ) * MAXPOINTS);
					delete []tmpxyz;
					MAXPOINTS += 1000;
				}
			}
			if(j==0)	//如果正向追踪完毕,则设置反向追踪条件,继续追踪
			{
				for(int	k=0; k<(int)floor(pointscount_[segsum_]/2); k++) //倒序排列正向追踪过程中已经追踪到的点
				{
					XYZ tmpPoint = points_[segsum_][k];
					points_[segsum_][k] = points_[segsum_][pointscount_[segsum_]-1-k];
					points_[segsum_][pointscount_[segsum_]-1-k] = tmpPoint;
				}
				//反向追踪,下面三条语句是根据两点(一条边)及一个三角形,必然能找到与这条边共享的另一个三角形
				end1 = end1_bak;
				end2 = end2_bak;
				InTri = FirstTri;
			}
		} // End for j
		segsum_++;
//		ASSERT(segsum_ == 1);

	} // End for i

//	if (HadSearched == false) 
//		AfxMessageBox("不能找到第一个点!");

	for(i=0; i<vcount; i++)		//恢复数组z原来的值
		pv[i].z = dArrayZ[i];
	delete []dArrayZ;
	delete []flag;
}//end function



// 选择平滑方法,如果为0,则不平滑
void COneContour::CreateContour()
{
	SearchZValuePointsOfTris();
	if ( smoothmethod_ > 0 )
	{
		for ( int i = 0; i < segsum_; i++)
		{
			CSmooth s(points_[i], pointscount_[i]);
			s.Smooth();
			s.GetSmoothedPoints(&afterpoints_[i], afterpointscount_[i]);
		}
	}
}

void COneContour::Initial(CTriangulate *T, double z, int smoothmethod)
{
	this->T = T;
	zvalue = z;
	smoothmethod_ = smoothmethod;
}

COneContour::COneContour()
{
	segsum_ = 0;
	epsilon = 0.0000001;
}

XYZ ** COneContour::GetPoints()
{
	return points_;
}

int * COneContour::GetPointsCount()
{
	return pointscount_;
}

XYZ ** COneContour::GetAfterPoints()
{
	return afterpoints_;
}

int * COneContour::GetAfterPointsCount()
{
	return afterpointscount_;
}

double COneContour::GetZValue()
{
	return zvalue;
}

int COneContour::GetSegCount()
{
	return segsum_;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -