📄 onecontour.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 + -