OneContour.cpp
上传用户:ynjin1970
上传日期:2014-10-13
资源大小:6438k
文件大小:7k
源码类别:

中间件编程

开发平台:

Visual C++

  1. // Contour.cpp: implementation of the COneContour class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. //#include "ct.h"
  6. #include "OneContour.h"
  7. #include <math.h>
  8. #include "smooth.h"
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char THIS_FILE[]=__FILE__;
  12. #define new DEBUG_NEW
  13. #endif
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. COneContour::COneContour(CTriangulate *T, double z)
  18. {
  19. this->T = T;
  20. zvalue = z;
  21. segsum_ = 0;
  22. epsilon = 0.0000001;
  23. }
  24. COneContour::~COneContour()
  25. {
  26. for (int i=0; i<segsum_; i++)
  27. {
  28. delete []points_[i];
  29. if ( this->smoothmethod_ > 0 )
  30. delete []afterpoints_[i];
  31. }
  32. }
  33. //////////////////////////////////////////////////////////////////
  34. //
  35. //  从指定的三角形集合中画等直线
  36. //  查找符合zvalue值的三角形并绘制等值线。。。
  37. //
  38. void COneContour::SearchZValuePointsOfTris()
  39. {
  40. int MAXPOINTS = 1000; // 搜索到的点的最大个数,会动态变化
  41. int MAXUSEDTRIS = 1000; // 记录UsedTris的最大个数,会动态变化
  42. int p1, p2, p3; // 三角形的三个点
  43. int end1, end2, end1_bak, end2_bak; // 三角形中有等值线通过的两个边
  44. double z1, z2, z3;
  45. bool *flag; // 三角形是否使用过的标记
  46. XYZ *pv = T->GetVertex(); // 散点数据
  47. int vcount = T->GetVertexCount();
  48. TRIANGLE *ptri = T->GetTriangle(); // 网格数据
  49. int tcount = T->GetTriangleCount();
  50. XYZ *tmpxyz; // 临时数据
  51. int FirstTri, InTri; 
  52. double zbak; //zvalue是常量,不能加上一个epsilon,故用此变量
  53. bool HadSearched; //是否找到了合适的相邻三角形
  54. int i, j;
  55. double *dArrayZ;
  56. flag = new bool[tcount]; // 缺省情况为没有用过
  57. for (i =0; i< tcount; i++)
  58. flag[i] = false;
  59. //以前采用临时调整zvalue的方法,现在采用临时调整
  60. //数组z的方法.但仍然保留老的方法,因为,同时采用两个方法
  61. //并不冲突,后者会自然屏蔽前者方法.声明内部变量
  62. dArrayZ = new double[vcount];
  63. for(i=0; i<vcount; i++)
  64. {
  65. dArrayZ[i] = pv[i].z; //对成员变量数组z进行备份,然后在结束时恢复数组z
  66. if (pv[i].z == zvalue) 
  67. pv[i].z += epsilon; //只在这个地方对Z进行了修改
  68. }
  69. // 从序号为FirstTri的三角形的哪一条边开始追踪...
  70. // 追踪到的第二个三角形序号,正在追踪的三角形序号。
  71. // 注意:
  72. //     如果一条边被两个三角形共享,因此,可以从两个方向来追踪下一个三角形。
  73. //     secondTri用于反向追踪时作为其实三角形使用。
  74. HadSearched = false;
  75. for(i = 0; i < tcount; i++)
  76. {
  77. //TRACE("%dn", i);
  78. // 判断第i个三角形是否已经存在于已用过的三角形列表中?
  79. if ( flag[i] ) continue;  //判断第i个三角形是否已用过
  80.   zbak = zvalue;  
  81. p1 = ptri[i].p1;
  82. p2 = ptri[i].p2;
  83. p3 = ptri[i].p3;
  84. z1 = pv[p1].z; // 三角形的三个顶点的Z值
  85. z2 = pv[p2].z;
  86. z3 = pv[p3].z;
  87. if (!( ((z1 - zbak) * (z2 - zbak) <= 0) || ((z3 - zbak) * (z2 - zbak) <= 0) ) )
  88. continue; // Z值没有落在此三角形(第i个三角形)内
  89. HadSearched = true;
  90. //找到了合适的三角形!!!
  91. //从第一号三角形开始查找满足条件的等值点
  92. points_[segsum_] = new XYZ[MAXPOINTS]; // 成员变量
  93. pointscount_[segsum_] = 0;
  94. if ((z1 - zbak) * (z2 - zbak) < 0)
  95. {
  96. end1 = p1;
  97. end2 = p2;
  98. if ((z1 -zbak) * (z3 - zbak) < 0)
  99. {
  100. end1_bak = p1;
  101. end2_bak = p3;
  102. }
  103. else 
  104. {
  105. end1_bak = p2;
  106. end2_bak = p3;
  107. }
  108. }
  109. else
  110. {
  111. end1 = p3;
  112. end2 = p2;
  113. end1_bak = p1;
  114. end2_bak = p3;
  115. }
  116. 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);
  117. 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);
  118. pointscount_[segsum_]++;
  119. 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);
  120. 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);
  121. pointscount_[segsum_]++;
  122. FirstTri =i;
  123. InTri = i;
  124. // UsedTris[UsedTrisCount] = InTri; // "已用过"
  125. // UsedTrisCount++;
  126. flag[i] = true;
  127. //然后从临接三角形中再次查找满足条件的等值点
  128. for (j=0; j<2; j++) //只循环两次,一次为正向追踪,另外一次为反向追踪
  129. {
  130. while(1)
  131. {
  132. if ( end1 + end2 == ptri[InTri].p1 + ptri[InTri].p2 ) 
  133. InTri = ptri[InTri].t3;
  134. else if ( end1 + end2 == ptri[InTri].p3 + ptri[InTri].p2 ) 
  135. InTri = ptri[InTri].t1;
  136. else 
  137. InTri = ptri[InTri].t2;
  138. if ( InTri < 0  || flag[InTri] )
  139. break;  // 不存在邻接三角形,正向追踪无可用的下一个三角形,停止正向追踪
  140. p3 = ptri[InTri].p1 + ptri[InTri].p2 + ptri[InTri].p3 - end1 - end2;
  141. z1 = pv[end1].z;
  142. z3 = pv[p3].z;
  143. if (( z1 - zvalue ) * ( z3 - zvalue ) <= 0 )
  144. end2 = p3;
  145. else
  146. end1 = p3;
  147. flag[InTri] = true;
  148. // 增加等值点
  149. 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);
  150. 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);
  151. pointscount_[segsum_]++;
  152. ASSERT(pointscount_[segsum_] < 4000); //Debug....
  153. if ( pointscount_[segsum_] >= MAXPOINTS ) // 重新分配内存
  154. {
  155. tmpxyz = points_[segsum_];
  156. points_[segsum_] = new XYZ[MAXPOINTS + 1000];
  157. memcpy(points_[segsum_], tmpxyz, sizeof(XYZ) * MAXPOINTS);
  158. delete []tmpxyz;
  159. MAXPOINTS += 1000;
  160. }
  161. }
  162. if(j==0) //如果正向追踪完毕,则设置反向追踪条件,继续追踪
  163. {
  164. for(int k=0; k<(int)floor(pointscount_[segsum_]/2); k++) //倒序排列正向追踪过程中已经追踪到的点
  165. {
  166. XYZ tmpPoint = points_[segsum_][k];
  167. points_[segsum_][k] = points_[segsum_][pointscount_[segsum_]-1-k];
  168. points_[segsum_][pointscount_[segsum_]-1-k] = tmpPoint;
  169. }
  170. //反向追踪,下面三条语句是根据两点(一条边)及一个三角形,必然能找到与这条边共享的另一个三角形
  171. end1 = end1_bak;
  172. end2 = end2_bak;
  173. InTri = FirstTri;
  174. }
  175. } // End for j
  176. segsum_++;
  177. // ASSERT(segsum_ == 1);
  178. } // End for i
  179. // if (HadSearched == false) 
  180. // AfxMessageBox("不能找到第一个点!");
  181. for(i=0; i<vcount; i++) //恢复数组z原来的值
  182. pv[i].z = dArrayZ[i];
  183. delete []dArrayZ;
  184. delete []flag;
  185. }//end function
  186. // 选择平滑方法,如果为0,则不平滑
  187. void COneContour::CreateContour()
  188. {
  189. SearchZValuePointsOfTris();
  190. if ( smoothmethod_ > 0 )
  191. {
  192. for ( int i = 0; i < segsum_; i++)
  193. {
  194. CSmooth s(points_[i], pointscount_[i]);
  195. s.Smooth();
  196. s.GetSmoothedPoints(&afterpoints_[i], afterpointscount_[i]);
  197. }
  198. }
  199. }
  200. void COneContour::Initial(CTriangulate *T, double z, int smoothmethod)
  201. {
  202. this->T = T;
  203. zvalue = z;
  204. smoothmethod_ = smoothmethod;
  205. }
  206. COneContour::COneContour()
  207. {
  208. segsum_ = 0;
  209. epsilon = 0.0000001;
  210. }
  211. XYZ ** COneContour::GetPoints()
  212. {
  213. return points_;
  214. }
  215. int * COneContour::GetPointsCount()
  216. {
  217. return pointscount_;
  218. }
  219. XYZ ** COneContour::GetAfterPoints()
  220. {
  221. return afterpoints_;
  222. }
  223. int * COneContour::GetAfterPointsCount()
  224. {
  225. return afterpointscount_;
  226. }
  227. double COneContour::GetZValue()
  228. {
  229. return zvalue;
  230. }
  231. int COneContour::GetSegCount()
  232. {
  233. return segsum_;
  234. }