📄 smooth.cpp
字号:
// 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();
}
*/}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -