Smooth.cpp
资源名称:08.zip [点击查看]
上传用户:ynjin1970
上传日期:2014-10-13
资源大小:6438k
文件大小:10k
源码类别:
中间件编程
开发平台:
Visual C++
- // Smooth.cpp: implementation of the CSmooth class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.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
- //////////////////////////////////////////////////////////////////////
- CSmooth::CSmooth(XYZ* points, int count)
- {
- // 初始哈原始点和点数量
- points_ = points;
- count_ = count;
- ptArrayCount = 0;
- // other initial
- ssum = 0;
- dts=20;
- }
- CSmooth::~CSmooth()
- {
- }
- /*
- 获得平滑过后的点
- */
- void CSmooth::GetSmoothedPoints(XYZ **points, int& count)
- {
- count = ptArrayCount;
- *points = ptArray;
- }
- //平滑由多个点组成的折线, 并把这些平滑的线画在DC上
- void CSmooth::Smooth()
- {
- double x, y, s(0);
- int i;
- int MAXSIZE = 512; // ptArray的最大大小,动态增加
- XYZ *tmpXYZ;
- ptArray = new XYZ[MAXSIZE]; // 不释放,将在哪儿释放呢?
- // bakup points and count for remove repeat points later.
- int count = count_;
- XYZ* points = new XYZ[count];
- for(i=0; i<count; i++)
- points[i] = points_[i];
- RemoveRepeatPoints(points, count);//规范化处理,剔除重复的点
- ssum = 0;
- ptArray[ptArrayCount++] = points[0]; //往数组中添加一个元素
- // 点的个数不够,退出平滑处理
- if(count < 2)
- {
- delete []points; return;
- }
- // 两个点。
- if(count == 2)
- {
- ptArray[ptArrayCount++] = points[1];
- delete []points; return;
- }
- // 只有三个点
- if(count==3)
- {
- CalcPara(0, true, points);
- ax0 = ax; bx0 = bx; cx0 = cx;
- ay0 = ay; by0 = by; cy0 = cy;
- si00 = si0; si10 = si1; si20 = si2; si30 = si3;
- do
- {
- s += dts;
- if (s>=si20) s = si20;
- x = x1(s); y = y1(s);
- ptArray[ptArrayCount++] = XYZ(x, y);
- if ( ptArrayCount >= MAXSIZE )
- {
- tmpXYZ = ptArray;
- ptArray = new XYZ[MAXSIZE + 512];
- memcpy(ptArray, tmpXYZ, sizeof(XYZ) * MAXSIZE);
- delete []tmpXYZ;
- MAXSIZE += 512;
- }
- } while(s<si20);
- delete []points;
- return;
- }
- //有四个或更多的点
- //绘制第一个和第二个点之间的曲线
- CalcPara(0, true, points);
- ax0 = ax; bx0 = bx; cx0 = cx;
- ay0 = ay; by0 = by; cy0 = cy;
- si00 = si0; si10 = si1; si20 = si2;
- do
- {
- s += dts;
- if (s>=si10) s=si10;
- x = x1(s); y = y1(s);
- ptArray[ptArrayCount++] = XYZ(x, y);
- if ( ptArrayCount >= MAXSIZE )
- {
- tmpXYZ = ptArray;
- ptArray = new XYZ[MAXSIZE + 512];
- memcpy(ptArray, tmpXYZ, sizeof(XYZ) * MAXSIZE);
- delete []tmpXYZ;
- MAXSIZE += 512;
- }
- } while(s<si10);
- //绘制中间点的曲线
- for (i=0; i<count-3; i++)
- {
- CalcPara(i, true, points);
- ax0 = ax; bx0 = bx; cx0 = cx;
- ay0 = ay; by0 = by; cy0 = cy;
- si00 = si0; si10 = si1; si20 = si2; si30 = si3;
- ssum = si10;
- CalcPara(i+1, false, points);
- s = si10;
- do
- {
- s += dts;
- if ( s >= si20) s = si20;
- x = a(s)*x1(s)+(1-a(s))*x2(s);
- y = a(s)*y1(s)+(1-a(s))*y2(s);
- ptArray[ptArrayCount++] = XYZ(x, y);
- ASSERT(ptArrayCount <= 10000);
- if ( ptArrayCount >= MAXSIZE )
- {
- tmpXYZ = ptArray;
- ptArray = new XYZ[MAXSIZE + 512];
- memcpy(ptArray, tmpXYZ, sizeof(XYZ) * MAXSIZE);
- delete []tmpXYZ;
- MAXSIZE += 512;
- }
- }
- while(s<si20);
- }
- //绘制最后的点与倒数第二个点之间的曲线
- s = si20;
- do
- {
- s += dts;
- if (s >= si2) s = si2;
- x = x2(s); y = y2(s);
- ptArray[ptArrayCount++] = XYZ(x, y);
- if ( ptArrayCount >= MAXSIZE )
- {
- tmpXYZ = ptArray;
- ptArray = new XYZ[MAXSIZE + 512];
- memcpy(ptArray, tmpXYZ, sizeof(XYZ) * MAXSIZE);
- delete []tmpXYZ;
- MAXSIZE += 512;
- }
- } while(s<si2);
- delete []points;
- }
- double CSmooth::x1(const double s)
- {
- 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);
- }
- double CSmooth::y1(const double s)
- {
- 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);
- }
- double CSmooth::x2(const double s)
- {
- 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);
- }
- double CSmooth::y2(const double s)
- {
- 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);
- }
- double CSmooth::a(const double s)
- {
- return (si20-s)/(si20-si10);
- }
- //算法中的处理
- void CSmooth::CalcPara(const int i, bool bCalcS, const XYZ* points)
- {
- si0 = ssum;
- 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));
- 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));
- // 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));
- ax = points[i].x/((si0-si1)*(si0-si2));
- bx = points[i+1].x/((si1-si0)*(si1-si2));
- cx = points[i+2].x/((si2-si0)*(si2-si1));
- ay = points[i].y/((si0-si1)*(si0-si2));
- by = points[i+1].y/((si1-si0)*(si1-si2));
- cy = points[i+2].y/((si2-si0)*(si2-si1));
- }
- //消除重复的点
- void CSmooth::RemoveRepeatPoints(XYZ* points, int& count)
- {
- for (int i= 0 ; i<count-1; i++)
- {
- if (points[i] == points[i+1])
- {
- for ( int j = i; j<count-1; j++)
- points[j] = points[j+1];
- count--;
- i--;
- }
- }
- }
- //画平滑线
- void CSmooth::DrawSmoothLines(CDC *dc)
- {
- /* CPoint point;
- point = ptArray.ElementAt(0);
- dc->MoveTo(point);
- for (int i=1; i<ptArray.GetSize(); i++)
- {
- point = ptArray.ElementAt(i);
- dc->LineTo(point);
- }
- */}
- //标注
- void CSmooth::DrawLable(CDC *dc, double zvalue)
- {
- // dc->Ellipse(ptArray.GetAt(0).x-50,ptArray.GetAt(0).y-50,ptArray.GetAt(0).x+50,ptArray.GetAt(0).y+50);
- //if (zvalue!=1750) return;
- /* int i;
- int kkkmmm=0;
- double bzjd_m;
- double dX1, dY1, dX2, dY2, dX3, dY3;
- const double pie = 3.1416;
- CString TextString;
- LOGFONT myFont;
- double r1;
- bool bSearched;
- myFont.lfHeight = 780;
- myFont.lfWidth = 460;
- myFont.lfEscapement = 0;
- myFont.lfWeight = 400;
- myFont.lfItalic = 0;
- myFont.lfUnderline = 0;
- myFont.lfStrikeOut = 0;
- myFont.lfOutPrecision = 0;
- myFont.lfClipPrecision = 0;
- myFont.lfQuality = 0;
- myFont.lfPitchAndFamily = 0;
- myFont.lfCharSet = 0;
- strcpy(myFont.lfFaceName, "Arial");
- //寻找标注点的位置及字体的标注角度
- r1 = 0;
- int nnk = 0;
- double RS = 0;
- i = ptArray.GetSize() - 1;
- TextString.Format("%7.2f", zvalue);
- int iWidth = TextString.GetLength()*myFont.lfWidth;
- int iHeight = myFont.lfHeight;
- int iNeedDots = (int)floor(iWidth/dts)+1;
- if (i >= 10)
- {
- for (int t = 5; t<=i-10; t++)
- {
- bSearched = false;//假设没有找到。。。
- int iik=t;
- dX1 = ptArray.GetAt(iik).x;
- dY1 = ptArray.GetAt(iik).y;
- dX2 = ptArray.GetAt(iik+1).x;
- dY2 = ptArray.GetAt(iik+1).y;
- dX3 = ptArray.GetAt(iik+2).x;
- dY3 = ptArray.GetAt(iik+2).y;
- double dist=sqrt((dX1-dX2)*(dX1-dX2)+(dY1-dY2)*(dY1-dY2))+sqrt((dX3-dX2)*(dX3-dX2)+(dY3-dY2)*(dY3-dY2));
- double mmk, kkm, xc, yc, ro;
- do
- {
- double pf1 = dX1*dX1 + dY1*dY1 - dX2*dX2 - dY2*dY2;
- double pf2 = dX2*dX2 + dY2*dY2 - dX3*dX3 - dY3*dY3;
- if (dY1 ==dY2) goto lbl100;
- mmk = pf2 - ((dY2 - dY3) / (dY1 - dY2)) * pf1;
- kkm = 2 * (dX2 - dX3 - (dY2 - dY3) * (dX1 - dX2) / (dY1 - dY2));
- if (fabs(kkm) < 0.0001) goto lbl100;
- xc = mmk / kkm;//(xc,yc)为园心,ro为半径
- yc = (pf2 - 2 * (dX1 - dX2) * xc) / (2 * (dY1 - dY2));
- ro = sqrt((yc - dX2)*(yc - dX2) + (yc - dY2)*(yc - dY2));
- if (ro<myFont.lfHeight*5) {bSearched=false;break;}
- lbl100: //如果满足要求的话,继续。。。
- bSearched=true;
- if (dist>iWidth) break;
- iik++;
- if (iik+2>i-10) {bSearched=false; break;}//点的个数不够,停止追踪
- dX1=dX2;dY1=dY2; dX2=dX3; dY2=dY3;
- dX3 = ptArray.GetAt(iik+2).x;
- dY3 = ptArray.GetAt(iik+2).y;
- dist+=sqrt((dX3-dX2)*(dX3-dX2)+(dY3-dY2)*(dY3-dY2));
- // 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);
- }while(1);
- if (bSearched == true) {kkkmmm = t; break;}
- }
- if (bSearched == false || kkkmmm==0)
- {
- return;
- }
- dc->Ellipse(ptArray.GetAt(kkkmmm).x-40,ptArray.GetAt(kkkmmm).y-40,ptArray.GetAt(kkkmmm).x+40,ptArray.GetAt(kkkmmm).y+40);
- double xzwz = ptArray.GetAt(kkkmmm).x;
- double yzwz = ptArray.GetAt(kkkmmm).y;
- double dltx = ptArray.GetAt(kkkmmm).x - ptArray.GetAt(kkkmmm+iNeedDots).x;
- double dlty = ptArray.GetAt(kkkmmm).y - ptArray.GetAt(kkkmmm+iNeedDots).y;
- double fzqz;
- if (dltx != 0)
- {
- fzqz = -atan(dlty/dltx);
- if (dlty == 0) fzqz = 0;
- }
- else
- double fzqz = 3 * pie / 2;
- bzjd_m = -fzqz;
- if ((fzqz<pie/2 && fzqz>0) || (fzqz<-3*pie/2 && fzqz>-2*pie) || (fzqz>pie && fzqz<3*pie/2) || (fzqz>-pie && fzqz<-pie/2))
- {
- // xzwz += (sqrt(iHeight*iHeight+iWidth*iWidth)/2 * cos(fzqz - atan(iHeight/iWidth)));
- // yzwz += (sqrt(iHeight*iHeight+iWidth*iWidth)/2 * sin(fzqz - atan(iHeight/iWidth)));
- //xzwz = xzwz - abs(myFont.lfWidth * cos(fzqz)) - abs(myFont.lfHeight * sin(fzqz) / 2);
- // yzwz = yzwz - abs(myFont.lfHeight * cos(fzqz) / 2) + abs(myFont.lfWidth * sin(fzqz));
- }
- else
- {
- // xzwz -= (sqrt(iHeight*iHeight+iWidth*iWidth)/2 * cos(fzqz - atan(iHeight/iWidth)));
- // yzwz += (sqrt(iHeight*iHeight+iWidth*iWidth)/2 * sin(fzqz - atan(iHeight/iWidth)));
- // xzwz = xzwz - abs(myFont.lfWidth * cos(fzqz)) + abs(myFont.lfHeight * sin(fzqz) / 2);
- // yzwz = yzwz - abs(myFont.lfHeight * cos(fzqz) / 2) - abs(myFont.lfWidth * sin(fzqz));
- }
- myFont.lfEscapement =(long)( fzqz * 1800.0 / pie);
- //标注
- CFont NewFont;
- NewFont.CreateFontIndirect(&myFont);
- CFont *OrgFont = dc->SelectObject(&NewFont);
- dc->TextOut((int)xzwz, (int)yzwz, TextString, 5); //TextString.GetLength());
- dc->SelectObject(OrgFont);
- NewFont.DeleteObject();
- OrgFont->DeleteObject();
- }
- */}