⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smooth.cpp

📁 VC实现等值线编成的COM组件的源程序代码
💻 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 + -