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

中间件编程

开发平台:

Visual C++

  1. // Smooth.cpp: implementation of the CSmooth class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "Onecontour.h"
  6. #include <math.h>
  7. #include "Smooth.h"
  8. #ifdef _DEBUG
  9. #undef THIS_FILE
  10. static char THIS_FILE[]=__FILE__;
  11. #define new DEBUG_NEW
  12. #endif
  13. //////////////////////////////////////////////////////////////////////
  14. // Construction/Destruction
  15. //////////////////////////////////////////////////////////////////////
  16. CSmooth::CSmooth(XYZ* points, int count)
  17. {
  18. // 初始哈原始点和点数量
  19. points_ = points;
  20. count_ = count;
  21. ptArrayCount = 0;
  22. // other initial
  23. ssum = 0;
  24. dts=20;
  25. }
  26. CSmooth::~CSmooth()
  27. {
  28. }
  29. /*
  30. 获得平滑过后的点
  31. */
  32. void CSmooth::GetSmoothedPoints(XYZ **points, int& count)
  33. {
  34. count = ptArrayCount;
  35. *points = ptArray;
  36. }
  37. //平滑由多个点组成的折线, 并把这些平滑的线画在DC上
  38. void CSmooth::Smooth()
  39. {
  40. double x, y, s(0);
  41. int i;
  42. int MAXSIZE = 512; // ptArray的最大大小,动态增加
  43. XYZ *tmpXYZ;
  44. ptArray = new XYZ[MAXSIZE]; // 不释放,将在哪儿释放呢?
  45. // bakup points and count for remove repeat points later.
  46. int count = count_;
  47. XYZ* points = new XYZ[count];
  48. for(i=0; i<count; i++)
  49. points[i] = points_[i];
  50. RemoveRepeatPoints(points, count);//规范化处理,剔除重复的点
  51. ssum = 0;
  52. ptArray[ptArrayCount++] = points[0]; //往数组中添加一个元素
  53. // 点的个数不够,退出平滑处理
  54. if(count < 2)
  55. {
  56. delete []points; return;
  57. }
  58. // 两个点。
  59. if(count == 2) 
  60. {
  61. ptArray[ptArrayCount++] = points[1];
  62. delete []points; return;
  63. // 只有三个点
  64. if(count==3) 
  65. {
  66. CalcPara(0, true, points);
  67. ax0 = ax; bx0 = bx; cx0 = cx;
  68. ay0 = ay; by0 = by; cy0 = cy;
  69. si00 = si0; si10 = si1; si20 = si2; si30 = si3;
  70. do 
  71. {
  72. s += dts;
  73. if (s>=si20) s = si20;
  74. x = x1(s); y = y1(s);
  75. ptArray[ptArrayCount++] = XYZ(x, y);
  76. if ( ptArrayCount >= MAXSIZE )
  77. {
  78. tmpXYZ = ptArray;
  79. ptArray = new XYZ[MAXSIZE + 512];
  80. memcpy(ptArray, tmpXYZ, sizeof(XYZ) * MAXSIZE);
  81. delete []tmpXYZ;
  82. MAXSIZE += 512;
  83. }
  84. } while(s<si20);
  85. delete []points; 
  86. return;
  87. }
  88. //有四个或更多的点
  89. //绘制第一个和第二个点之间的曲线
  90. CalcPara(0, true, points);
  91. ax0 = ax; bx0 = bx; cx0 = cx;
  92. ay0 = ay; by0 = by; cy0 = cy;
  93. si00 = si0; si10 = si1; si20 = si2;
  94. do 
  95. {
  96. s += dts;
  97. if (s>=si10) s=si10;
  98. x = x1(s); y = y1(s);
  99. ptArray[ptArrayCount++] = XYZ(x, y);
  100. if ( ptArrayCount >= MAXSIZE )
  101. {
  102. tmpXYZ = ptArray;
  103. ptArray = new XYZ[MAXSIZE + 512];
  104. memcpy(ptArray, tmpXYZ, sizeof(XYZ) * MAXSIZE);
  105. delete []tmpXYZ;
  106. MAXSIZE += 512;
  107. }
  108. } while(s<si10);
  109. //绘制中间点的曲线
  110. for (i=0; i<count-3; i++)
  111. {
  112. CalcPara(i, true, points);
  113. ax0 = ax; bx0 = bx; cx0 = cx;
  114. ay0 = ay; by0 = by; cy0 = cy;
  115. si00 = si0; si10 = si1; si20 = si2; si30 = si3;
  116. ssum = si10;
  117. CalcPara(i+1, false, points);
  118. s = si10;
  119. do
  120. {
  121. s += dts;
  122. if ( s >= si20) s = si20;
  123. x = a(s)*x1(s)+(1-a(s))*x2(s);
  124. y = a(s)*y1(s)+(1-a(s))*y2(s);
  125. ptArray[ptArrayCount++] = XYZ(x, y);
  126. ASSERT(ptArrayCount <= 10000);
  127. if ( ptArrayCount >= MAXSIZE )
  128. {
  129. tmpXYZ = ptArray;
  130. ptArray = new XYZ[MAXSIZE + 512];
  131. memcpy(ptArray, tmpXYZ, sizeof(XYZ) * MAXSIZE);
  132. delete []tmpXYZ;
  133. MAXSIZE += 512;
  134. }
  135. }
  136. while(s<si20);
  137. }
  138. //绘制最后的点与倒数第二个点之间的曲线
  139. s = si20;
  140. do 
  141. {
  142. s += dts;
  143. if (s >= si2) s = si2;
  144. x = x2(s); y = y2(s);
  145. ptArray[ptArrayCount++] = XYZ(x, y);
  146. if ( ptArrayCount >= MAXSIZE )
  147. {
  148. tmpXYZ = ptArray;
  149. ptArray = new XYZ[MAXSIZE + 512];
  150. memcpy(ptArray, tmpXYZ, sizeof(XYZ) * MAXSIZE);
  151. delete []tmpXYZ;
  152. MAXSIZE += 512;
  153. }
  154. } while(s<si2);
  155. delete []points;
  156. }
  157. double CSmooth::x1(const double s)
  158. {
  159. return (ax0+bx0+cx0)*s*s-(ax0*(si10+si20)+bx0*(si00+si20)+cx0*(si00+si10))*s+(ax0*si10*si20+bx0*si20*si00+cx0*si00*si10);
  160. }
  161. double CSmooth::y1(const double s)
  162. {
  163. return (ay0+by0+cy0)*s*s-(ay0*(si10+si20)+by0*(si00+si20)+cy0*(si00+si10))*s+(ay0*si10*si20+by0*si20*si00+cy0*si00*si10);
  164. }
  165. double CSmooth::x2(const double s)
  166. {
  167. return (ax+bx+cx)*s*s-(ax*(si1+si2)+bx*(si0+si2)+cx*(si0+si1))*s+(ax*si1*si2+bx*si2*si0+cx*si0*si1);
  168. }
  169. double CSmooth::y2(const double s)
  170. {
  171. return (ay+by+cy)*s*s-(ay*(si1+si2)+by*(si0+si2)+cy*(si0+si1))*s+(ay*si1*si2+by*si2*si0+cy*si0*si1);
  172. }
  173. double CSmooth::a(const double s)
  174. {
  175. return (si20-s)/(si20-si10);
  176. }
  177. //算法中的处理
  178. void CSmooth::CalcPara(const int i, bool bCalcS, const XYZ* points)
  179. {
  180. si0 = ssum;
  181. si1=si0+sqrt((points[i+1].x-points[i].x)*(points[i+1].x-points[i].x)+(points[i+1].y-points[i].y)*(points[i+1].y-points[i].y));
  182. si2=si1+sqrt((points[i+2].x-points[i+1].x)*(points[i+2].x-points[i+1].x)+(points[i+2].y-points[i+1].y)*(points[i+2].y-points[i+1].y));
  183. // si3=si2+sqrt((points[i+2].x-points[i+3].x)*(points[i+2].x-points[i+3].x)+(points[i+2].y-points[i+3].y)*(points[i+2].y-points[i+3].y));
  184. ax = points[i].x/((si0-si1)*(si0-si2));
  185. bx = points[i+1].x/((si1-si0)*(si1-si2));
  186. cx = points[i+2].x/((si2-si0)*(si2-si1));
  187. ay = points[i].y/((si0-si1)*(si0-si2));
  188. by = points[i+1].y/((si1-si0)*(si1-si2));
  189. cy = points[i+2].y/((si2-si0)*(si2-si1));
  190. }
  191. //消除重复的点
  192. void CSmooth::RemoveRepeatPoints(XYZ* points, int& count)
  193. {
  194. for (int i= 0 ; i<count-1; i++)
  195. {
  196. if (points[i] == points[i+1])
  197. {
  198. for ( int j = i; j<count-1; j++)
  199. points[j] = points[j+1];
  200. count--;
  201. i--;
  202. }
  203. }
  204. }
  205. //画平滑线
  206. void CSmooth::DrawSmoothLines(CDC *dc)
  207. {
  208. /* CPoint point;
  209. point = ptArray.ElementAt(0);
  210. dc->MoveTo(point);
  211. for (int i=1; i<ptArray.GetSize(); i++)
  212. {
  213. point = ptArray.ElementAt(i);
  214. dc->LineTo(point);
  215. }
  216. */}
  217. //标注
  218. void CSmooth::DrawLable(CDC *dc, double zvalue)
  219. {
  220. // dc->Ellipse(ptArray.GetAt(0).x-50,ptArray.GetAt(0).y-50,ptArray.GetAt(0).x+50,ptArray.GetAt(0).y+50);
  221. //if (zvalue!=1750) return;
  222. /* int i;
  223. int kkkmmm=0;
  224. double bzjd_m;
  225. double dX1, dY1, dX2, dY2, dX3, dY3;
  226. const double pie = 3.1416;
  227. CString TextString;
  228. LOGFONT myFont;
  229.     double r1;
  230. bool bSearched;
  231. myFont.lfHeight = 780;
  232.     myFont.lfWidth = 460;
  233.     myFont.lfEscapement = 0;
  234.     myFont.lfWeight = 400;
  235.     myFont.lfItalic = 0;
  236.     myFont.lfUnderline = 0;
  237.     myFont.lfStrikeOut = 0;
  238.     myFont.lfOutPrecision = 0;
  239.     myFont.lfClipPrecision = 0;
  240.     myFont.lfQuality = 0;
  241.     myFont.lfPitchAndFamily = 0;
  242.     myFont.lfCharSet = 0;
  243. strcpy(myFont.lfFaceName, "Arial");            
  244. //寻找标注点的位置及字体的标注角度
  245.     r1 = 0;
  246.     int nnk = 0;
  247.     double RS = 0;
  248.     i = ptArray.GetSize() - 1;
  249.     TextString.Format("%7.2f", zvalue);
  250. int iWidth = TextString.GetLength()*myFont.lfWidth;
  251. int iHeight = myFont.lfHeight;
  252.     int iNeedDots = (int)floor(iWidth/dts)+1;
  253. if (i >= 10)
  254. {
  255. for (int t = 5; t<=i-10; t++)
  256. {
  257. bSearched = false;//假设没有找到。。。
  258. int iik=t;
  259. dX1 = ptArray.GetAt(iik).x;
  260. dY1 = ptArray.GetAt(iik).y;
  261. dX2 = ptArray.GetAt(iik+1).x;
  262. dY2 = ptArray.GetAt(iik+1).y;
  263. dX3 = ptArray.GetAt(iik+2).x;
  264. dY3 = ptArray.GetAt(iik+2).y;
  265. double dist=sqrt((dX1-dX2)*(dX1-dX2)+(dY1-dY2)*(dY1-dY2))+sqrt((dX3-dX2)*(dX3-dX2)+(dY3-dY2)*(dY3-dY2));
  266. double mmk, kkm, xc, yc, ro;
  267. do 
  268. {
  269.   double pf1 = dX1*dX1 + dY1*dY1 - dX2*dX2 - dY2*dY2;
  270.   double pf2 = dX2*dX2 + dY2*dY2 - dX3*dX3 - dY3*dY3;
  271.   if (dY1 ==dY2) goto lbl100;
  272.   mmk = pf2 - ((dY2 - dY3) / (dY1 - dY2)) * pf1;
  273.   kkm = 2 * (dX2 - dX3 - (dY2 - dY3) * (dX1 - dX2) / (dY1 - dY2));
  274.   if (fabs(kkm) < 0.0001) goto lbl100;
  275.   xc = mmk / kkm;//(xc,yc)为园心,ro为半径
  276.   yc = (pf2 - 2 * (dX1 - dX2) * xc) / (2 * (dY1 - dY2));
  277.   ro = sqrt((yc - dX2)*(yc - dX2) + (yc - dY2)*(yc - dY2));
  278.   if (ro<myFont.lfHeight*5) {bSearched=false;break;}
  279. lbl100:   //如果满足要求的话,继续。。。
  280.   bSearched=true;
  281.   if (dist>iWidth) break;
  282.   iik++;
  283.   if (iik+2>i-10) {bSearched=false; break;}//点的个数不够,停止追踪
  284.   dX1=dX2;dY1=dY2; dX2=dX3; dY2=dY3;
  285.   dX3 = ptArray.GetAt(iik+2).x;
  286.   dY3 = ptArray.GetAt(iik+2).y;
  287.   dist+=sqrt((dX3-dX2)*(dX3-dX2)+(dY3-dY2)*(dY3-dY2));
  288. // dc->Ellipse(ptArray.GetAt(iik+2).x-10,ptArray.GetAt(iik+2).y-10,ptArray.GetAt(iik+2).x+10,ptArray.GetAt(iik+2).y+10);
  289. }while(1);
  290. if (bSearched == true) {kkkmmm = t; break;}
  291. }
  292.         if (bSearched == false || kkkmmm==0) 
  293. {
  294. return;
  295. }
  296. dc->Ellipse(ptArray.GetAt(kkkmmm).x-40,ptArray.GetAt(kkkmmm).y-40,ptArray.GetAt(kkkmmm).x+40,ptArray.GetAt(kkkmmm).y+40);
  297. double xzwz = ptArray.GetAt(kkkmmm).x;
  298. double yzwz = ptArray.GetAt(kkkmmm).y;
  299. double dltx = ptArray.GetAt(kkkmmm).x - ptArray.GetAt(kkkmmm+iNeedDots).x;
  300. double dlty = ptArray.GetAt(kkkmmm).y - ptArray.GetAt(kkkmmm+iNeedDots).y;
  301. double fzqz;
  302.    
  303.         if (dltx != 0)
  304. {
  305. fzqz = -atan(dlty/dltx);
  306. if (dlty == 0) fzqz = 0;
  307. }
  308.         else
  309.              double fzqz = 3 * pie / 2;
  310.         
  311.         bzjd_m = -fzqz;
  312.         if ((fzqz<pie/2 && fzqz>0) || (fzqz<-3*pie/2 && fzqz>-2*pie) || (fzqz>pie && fzqz<3*pie/2) || (fzqz>-pie && fzqz<-pie/2))
  313. {
  314. // xzwz += (sqrt(iHeight*iHeight+iWidth*iWidth)/2 * cos(fzqz - atan(iHeight/iWidth)));
  315. // yzwz += (sqrt(iHeight*iHeight+iWidth*iWidth)/2 * sin(fzqz - atan(iHeight/iWidth)));
  316. //xzwz = xzwz - abs(myFont.lfWidth * cos(fzqz)) - abs(myFont.lfHeight * sin(fzqz) / 2);
  317. // yzwz = yzwz - abs(myFont.lfHeight * cos(fzqz) / 2) + abs(myFont.lfWidth * sin(fzqz));
  318. }
  319.         else
  320. {
  321. // xzwz -= (sqrt(iHeight*iHeight+iWidth*iWidth)/2 * cos(fzqz - atan(iHeight/iWidth)));
  322. // yzwz += (sqrt(iHeight*iHeight+iWidth*iWidth)/2 * sin(fzqz - atan(iHeight/iWidth)));
  323. // xzwz = xzwz - abs(myFont.lfWidth * cos(fzqz)) + abs(myFont.lfHeight * sin(fzqz) / 2);
  324. // yzwz = yzwz - abs(myFont.lfHeight * cos(fzqz) / 2) - abs(myFont.lfWidth * sin(fzqz));
  325. }
  326.         myFont.lfEscapement =(long)( fzqz * 1800.0 / pie);
  327.        //标注          
  328.         CFont NewFont;
  329. NewFont.CreateFontIndirect(&myFont);
  330.         CFont *OrgFont = dc->SelectObject(&NewFont);
  331.         dc->TextOut((int)xzwz, (int)yzwz, TextString, 5); //TextString.GetLength());
  332.         dc->SelectObject(OrgFont);
  333. NewFont.DeleteObject();
  334. OrgFont->DeleteObject();
  335. */}