QGISAlgorithmLib.cpp
资源名称:QGIS.rar [点击查看]
上传用户:oybseng
上传日期:2015-04-27
资源大小:7831k
文件大小:26k
源码类别:
GDI/图象编程
开发平台:
Visual C++
- // QGISAlgorithmLib->cpp: implementation of the CQGISAlgorithmLib class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "..stdafx.h"
- #include "....QObjectsincludeResource.h"
- #include "..includeResource.h"
- #include "..includeQGISAlgorithmLib.h"
- #include "....QObjectsincludeQLineObj.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CQGISAlgorithmLib::CQGISAlgorithmLib()
- {
- }
- CQGISAlgorithmLib::~CQGISAlgorithmLib()
- {
- }
- //////////////////////////////////////////
- ///***************CQGIS****************///
- ///函数名称:IsLineCross
- ///返回类型:BOOL
- ///入口参数:CQPoint p1,CQPoint p2,CQPoint q1,CQPoint q2
- ///出口参数:无
- ///思路说明:边界矩形,矢量跨立实验
- ///***************CQGIS****************///
- //////////////////////////////////////////
- BOOL CQGISAlgorithmLib::IsLineCross(CQPoint p1,CQPoint p2,CQPoint q1,CQPoint q2)
- {
- //创建两条直线对象 用于进行边界矩形的判断
- if(p1 == q1 || p1 == q2 || p2 == q1 || p2 == q2)
- return TRUE; //直接得出直线相交
- CQLineObj * pLine1 = new CQLineObj;
- pLine1->m_PtList.AddPoint(&p1);
- pLine1->m_PtList.AddPoint(&p2);
- CQLineObj * pLine2 = new CQLineObj;
- pLine2->m_PtList.AddPoint(&q1);
- pLine2->m_PtList.AddPoint(&q2);
- CBoundaryRect * pRect1 = new CBoundaryRect;
- pLine1->GetBoundingRect(pRect1);
- CBoundaryRect * pRect2 = new CBoundaryRect;
- pLine2->GetBoundingRect(pRect2);
- if(!pRect1->IsCross(pRect2))
- {
- //假如两个边界矩形不相交
- delete pRect2;
- delete pRect1;
- delete pLine2;
- delete pLine1;
- return FALSE; //不相交
- }
- //进行跨立实验
- double p1q1x = p1.GetX() - q1.GetX();
- double p1q1y = p1.GetY() - q1.GetY();
- double q2q1x = q2.GetX() - q1.GetX();
- double q2q1y = q2.GetY() - q1.GetY();
- double p2q1x = p2.GetX() - q1.GetX();
- double p2q1y = p2.GetY() - q1.GetY();
- double fResult; //运算结果
- double fpq = p1q1x*q2q1y - q2q1x*p1q1y;
- double fqp = q2q1x*p2q1y - p2q1x*q2q1y;
- fResult = fpq*fqp;
- if(fResult>=0)
- {
- delete pRect2;
- delete pRect1;
- delete pLine2;
- delete pLine1;
- return TRUE;
- }
- delete pRect2;
- delete pRect1;
- delete pLine2;
- delete pLine1;
- return FALSE;
- }
- //////////////////////////////////////////
- ///***************CQGIS****************///
- ///函数名称:CalLineCrossPoint
- ///返回类型:无
- ///入口参数:CQPoint p1,CQPoint p2,CQPoint q1,CQPoint q2
- ///出口参数:CQPointArray * pResult
- ///思路说明:判断两条直线是否相交,若相交则返回其交点
- ///***************CQGIS****************///
- //////////////////////////////////////////
- void CQGISAlgorithmLib::CalLineCrossPoint(CQPoint pp1,CQPoint pp2,CQPoint qq1,CQPoint qq2,CQPointArray * pResult)
- {
- if(!IsLineCross(pp1,pp2,qq1,qq2))
- {
- pResult = 0;
- return;
- }
- CQPoint * p1 = new CQPoint(pp1);
- CQPoint * p2 = new CQPoint(pp2);
- CQPoint * q1 = new CQPoint(qq1);
- CQPoint * q2 = new CQPoint(qq2);
- //计算两条直线的斜率
- //double k1 = (p2.GetY()-p1.GetY())/(p2.GetX()-p1.GetX());
- //double k2 = (q2.GetY()-q1.GetY())/(q2.GetX()-q1.GetX());
- //L0(p1,p2),L1(q1,q2);
- //情况1 L0平行于Y轴
- //分两种情况 当L1也与Y轴平行时,则两条直线共线
- //若L1与Y轴不平行,则直接代入方程求解
- if(p1->GetX() == p2->GetX())
- {
- if(q1->GetX() == q2->GetX()) //L1也与Y轴平行
- {
- CalSameLineCrossPoint(*p1,*p2,*q1,*q2,pResult);
- return;
- }
- else //L1与Y轴不平行
- {
- double k2 = (q2->GetY()-q1->GetY())/(q2->GetX()-q1->GetX());
- double x2 = p1->GetX();
- //y2 = k2x2-k2x1+y1;x1 = q1->GetX(),y1 = q1->getY();
- double y2 = k2*x2-k2*q1->GetX()+q1->GetY();
- pResult->AddPoint(x2,y2);
- delete q2;
- }
- }
- else if(q1->GetX() == q2->GetX())
- {
- double k1 = (p2->GetY()-p1->GetY())/(p2->GetX()-p1->GetX());
- double x1 = q1->GetX(),y1;
- y1 = k1*x1-k1*p1->GetX()+p1->GetY();
- pResult->AddPoint(x1,y1);
- }
- else if(p1->GetY() == p2->GetY()) //平行与X 轴
- {
- if(q1->GetY() == q2->GetY()) //L1也平行与X轴
- {
- CalSameLineCrossPoint(*p1,*p2,*q1,*q2,pResult);
- }
- else
- {
- double k2 = (q2->GetY()-q1->GetY())/(q2->GetX()-q1->GetX());
- double y2 = p1->GetY();
- double x2 = (y2+k2*q1->GetX()-q1->GetY())/k2;
- pResult->AddPoint(x2,y2);
- }
- }
- else if(q1->GetY() == q2->GetY())
- {
- double k1 = (p2->GetY()-p1->GetY())/(p2->GetX()-p1->GetX());
- double y1 = q1->GetY();
- double x1 = (y1+k1*p1->GetX()-p1->GetY())/k1;
- pResult->AddPoint(x1,y1);
- }
- else
- {
- double k1 = (p2->GetY()-p1->GetY())/(p2->GetX()-p1->GetX());
- double k2 = (q2->GetY()-q1->GetY())/(q2->GetX()-q1->GetX());
- if(k1-k2 == SMALL_NUMBER)
- {
- CalSameLineCrossPoint(*p1,*p2,*q1,*q1,pResult);
- }
- else
- {
- double xResult = k1*p1->GetX()-k2*q1->GetX()+q1->GetY()-p1->GetY();
- xResult = xResult/(k1-k2);
- double yResult = k1*xResult-k1*p1->GetX()+p1->GetY();
- pResult->AddPoint(xResult,yResult);
- }
- }
- delete q2;
- delete q1;
- delete p2;
- delete p1;
- }
- //////////////////////////////////////////
- ///***************CQGIS****************///
- ///函数名称:CalSameLineCrossPoint
- ///返回类型:无
- ///入口参数:CQPoint p1,CQPoint p2,CQPoint q1,CQPoint q2
- ///出口参数:CQPointArray * pResult
- ///思路说明:
- ///***************CQGIS****************///
- //////////////////////////////////////////
- void CQGISAlgorithmLib::CalSameLineCrossPoint(CQPoint pp1,CQPoint pp2,CQPoint qq1,CQPoint qq2,CQPointArray * pResult)
- {
- //直接计算 不做条件判断 在调用之前一定要确保两直线是相交的
- //共线计算只考虑垂直于X,Y轴的情形
- double fy1,fy2;
- double fy3,fy4;
- double fx1,fx2;
- double fx3,fx4;
- CQPoint * p1 = new CQPoint(pp1);
- CQPoint * p2 = new CQPoint(pp2);
- CQPoint * q1 = new CQPoint(qq1);
- CQPoint * q2 = new CQPoint(qq2);
- //先找出较长的直线
- double dd1 = p1->Distance(*p2);
- double dd2 = q1->Distance(*q2);
- //始终用较长的线段为基准进行判断
- if(dd1<dd2)
- {
- CQPoint tmPoint = *p1;
- *p1 = *q1;
- *q1 = tmPoint;
- tmPoint = *p2;
- *p2 = *q2;
- *q2 = tmPoint;
- }
- if(p1->GetX() == p2->GetX() && q1->GetX() == q2->GetX()) //两条直线都与Y轴平行
- {
- fy1 = min(p1->GetY(),p2->GetY());
- fy2 = max(p1->GetY(),p2->GetY());
- fy3 = min(q1->GetY(),q2->GetY());
- fy4 = max(q1->GetY(),q2->GetY());
- p1->SetPoint(p1->GetX(),fy1); //Y较小的点
- p2->SetPoint(p2->GetX(),fy2); //Y较大的点
- q1->SetPoint(q1->GetX(),fy3);
- q2->SetPoint(q2->GetX(),fy4);
- if(p1->GetY() > q2->GetY() || p2->GetY() < q1->GetY())
- {
- pResult = 0;
- }
- else
- {
- if(p2->GetY() == q1->GetY())
- {
- pResult->AddPoint(p2->GetX(),p2->GetY());
- }
- else if(q1->GetY()<p2->GetY() && q1->GetY() >p1->GetY())
- {
- if(p2->GetY()>q1->GetY() && p2->GetY()<q2->GetY())
- {
- pResult->AddPoint(q1->GetX(),q1->GetY());
- pResult->AddPoint(p2->GetX(),p2->GetY());
- }
- else if(p2->GetY()>=q2->GetY())
- {
- pResult->AddPoint(q1->GetX(),q1->GetY());
- pResult->AddPoint(q2->GetY(),q2->GetY());
- }
- }
- else if(*p1 == *q1 && *p2 == *q2) //两直线重合
- {
- pResult->AddPoint(p1->GetX(),p1->GetY());
- pResult->AddPoint(p2->GetX(),p2->GetY());
- }
- }
- }
- else if(p1->GetY() == p2->GetY() && q1->GetY() == q2->GetY()) //两条直线都与X轴平行
- {
- fx1 = min(p1->GetX(),p2->GetX());
- fx2 = max(p1->GetX(),p2->GetX());
- fx3 = min(q1->GetX(),q2->GetX());
- fx4 = max(q1->GetX(),q2->GetX());
- p1->SetPoint(fx1,p1->GetY());
- p2->SetPoint(fx2,p2->GetY());
- q1->SetPoint(fx3,q1->GetY());
- q2->SetPoint(fx4,q2->GetY());
- if(p2->GetX() < q1->GetX() || p1->GetX() > q2->GetX())
- {
- pResult = 0;
- }
- else if(q1->GetX()>p1->GetX() && q1->GetX()<p2->GetX())
- {
- if(p2->GetX()>q1->GetX() && p2->GetX()<q2->GetX())
- {
- pResult->AddPoint(q1->GetX(),q1->GetY());
- pResult->AddPoint(p2->GetX(),p2->GetY());
- }
- else if(p2->GetX()>=q2->GetX())
- {
- pResult->AddPoint(q1->GetX(),q1->GetY());
- pResult->AddPoint(q2->GetX(),q2->GetY());
- }
- }
- else if(p2->GetX() == q1->GetX())
- {
- pResult->AddPoint(p2->GetX(),p2->GetY());
- }
- else if(*p1 == *q1 && *p2 == *q2)
- {
- pResult->AddPoint(p1->GetX(),p2->GetY());
- pResult->AddPoint(p2->GetX(),p2->GetY());
- }
- }
- else //两条直线只是斜率相等
- {
- if(p1->GetX()>p2->GetX())
- {
- CQPoint tmPoint;
- tmPoint = *p1;
- *p1 = *p2;
- *p2 = tmPoint;
- }
- if(q1->GetX()>q2->GetX())
- {
- CQPoint tmPoint;
- tmPoint = *q1;
- *q1 = *q2;
- *q2 = tmPoint;
- }
- if(p2->GetX()<q1->GetX())
- {
- CQPoint tmPoint = *q1;
- *p1 = *q1;
- *q1 = tmPoint;
- tmPoint = *q2;
- *p2 = *q2;
- *q2 = tmPoint;
- }
- if(p2->GetX() < q1->GetX() || p1->GetX() > q2->GetX())
- {
- pResult = 0;
- return;
- }
- else if(q1->GetX()>p1->GetX() && q1->GetX()<p2->GetX())
- {
- if(p2->GetX()>q1->GetX() && p2->GetX()<q2->GetX())
- {
- pResult->AddPoint(q1->GetX(),q1->GetY());
- pResult->AddPoint(p2->GetX(),p2->GetY());
- }
- else if(p2->GetX()>=q2->GetX())
- {
- pResult->AddPoint(q1->GetX(),q1->GetY());
- pResult->AddPoint(q2->GetX(),q2->GetY());
- }
- }
- else if(p2->GetX() == q1->GetX())
- {
- pResult->AddPoint(p2->GetX(),p2->GetY());
- }
- else if(*p1 == *q1 && *p2 == *q2)
- {
- pResult->AddPoint(p1->GetX(),p1->GetY());
- pResult->AddPoint(p2->GetX(),p2->GetY());
- }
- }
- delete q2;
- delete q1;
- delete p2;
- delete p1;
- }
- //弧度转换为度单位
- double CQGISAlgorithmLib::RadianToDegree(double fRadian)
- {
- return fRadian*PIunder180;
- }
- double CQGISAlgorithmLib::DegreeToRadian(double fDegree)
- {
- return fDegree*PIover180;
- }
- ////////////////////////////////////////////////////////////////////////////
- // 参数: nBegin, 结点数
- // nEnd, 待插值点数
- // FromX, 一维数组, 结点的X坐标值( FromX0 < FromX1 < FromX2 < ... <FromXn-1 )
- // FromY, 一维数组, 结点的Y坐标值
- // ToX, 一维数组, 待插值点的X坐标值
- // ToY, 一维数组, 待插值点的Y坐标值
- // 返回: void
- void CQGISAlgorithmLib::Interpolation_curve(float * FromX,float * FromY,float * ToX,float * ToY,int nBeign,int nEnd)
- {
- for(int i=0, k=0; i<nEnd; i++)
- {
- k = 0;
- if(ToX[i]>=FromX[nBeign-1]) k=nBeign-2;
- else
- {
- while (ToX[i]>FromX[k+1]) k++;
- }
- ToY[i] = (FromX[k]*(FromX[k+1]-ToX[i])+FromX[k+1]*(ToX[i]-FromX[k]))/(FromX[k+1]-FromX[k]);
- }
- }
- ////////////////////////////////////////////////////////////////////////////
- // 参数: nBegin, 结点数
- // nEnd, 待插值点数
- // FromX, 一维数组, 结点的X坐标值( FromX0 < FromX1 < FromX2 < ... <FromXn-1 )
- // FromY, 一维数组, 结点的Y坐标值
- // ToX, 一维数组, 待插值点的X坐标值
- // ToY, 一维数组, 待插值点的Y坐标值
- // 返回: void
- void CQGISAlgorithmLib::Interpolation_curve(double * FromX,double * FromY,double * ToX,double * ToY,int nBeign,int nEnd)
- {
- for(int i=0, k=0; i<nEnd; i++)
- {
- k = 0;
- if(ToX[i]>=FromX[nBeign-1]) k=nBeign-2;
- else
- {
- while (ToX[i]>FromX[k+1]) k++;
- }
- ToY[i] = (FromX[k]*(FromX[k+1]-ToX[i])+FromX[k+1]*(ToX[i]-FromX[k]))/(FromX[k+1]-FromX[k]);
- }
- }
- // 函 数 名: B2_curves
- // 功 能: 二次B样条曲线
- // 参 数:
- // N, 结点的总数
- // m, 每段的分段数
- // x, 一维数组, 结点的X坐标值
- // y, 一维数组, 结点的Y坐标值
- // tx,一维数组, 待插值点(包括结点)的X坐标值
- // ty,一维数组, 待插值点(包括结点)的Y坐标值
- // (入口): float * x, float * y, float * tx, float * ty, int n, int k
- // (出口): float tx, float ty
- // 返 回: 无
- // 调用方法:
- void CQGISAlgorithmLib::B2_curves(float * x, float * y, float * tx, float * ty, int n, int k)
- {
- float t,t1,t2;
- float a,b,c;
- t = 1.0f/k;
- tx[0]=(x[0]+x[1])/2; //第一个点为原始一二两点的中点
- ty[0]=(y[0]+y[1])/2;
- int nCount = 1;
- for(int i=1;i<n-1;i++)
- for(int j=1;j<=k;j++)
- {
- t1=j*t;
- t2=t1*t1;
- a=(t2-2*t1+1)/2.0f; // 1/2*(t-1)(t-1)
- b=t1-t2+1/2.0f; // 1/2*(-2t*t+2t+1)
- c=t2/2.0f; // 1/2*t*t
- tx[nCount] =x[i-1]*a+x[i]*b+x[i+1]*c;
- ty[nCount] =y[i-1]*a+y[i]*b+y[i+1]*c;
- nCount++;
- }
- }
- // 函 数 名: B2_curves
- // 功 能: 二次B样条曲线
- // 参 数:
- // N, 结点的总数
- // m, 每段的分段数
- // x[], 一维数组, 结点的X坐标值
- // y[], 一维数组, 结点的Y坐标值
- // tx[],一维数组, 待插值点(包括结点)的X坐标值
- // ty[],一维数组, 待插值点(包括结点)的Y坐标值
- // (入口): double * x, double * y, double * tx, double * ty, int n, int k
- // (出口): double * tx, double * ty
- // 返 回: 无
- void CQGISAlgorithmLib::B2_curves(double * x, double * y, double * tx, double * ty, int n, int k)
- {
- double t,t1,t2;
- double a,b,c;
- t = 1.0/k;
- tx[0]=(x[0]+x[1])/2; //第一个点为原始一二两点的中点
- ty[0]=(y[0]+y[1])/2;
- int nCount = 1;
- for(int i=1;i<n-1;i++)
- for(int j=1;j<=k;j++)
- {
- t1=j*t;
- t2=t1*t1;
- a=(t2-2*t1+1)/2.0; // 1/2*(t-1)(t-1)
- b=t1-t2+1/2.0; // 1/2*(-2t*t+2t+1)
- c=t2/2.0; // 1/2*t*t
- tx[nCount] =x[i-1]*a+x[i]*b+x[i+1]*c;
- ty[nCount] =y[i-1]*a+y[i]*b+y[i+1]*c;
- nCount++;
- }
- }
- // 函 数 名: B3_curves
- // 功 能: 三次B样条曲线
- // 参 数:
- // n, 结点的总数
- // m, 每段的分段数
- // x, 一维数组, 结点的X坐标值
- // y, 一维数组, 结点的Y坐标值
- // tx,一维数组, 待插值点(包括结点)的X坐标值
- // ty,一维数组, 待插值点(包括结点)的Y坐标值
- // (入口): double * x, double * y, double * tx, double * ty, int n, int k
- // (出口): double * tx, double * ty
- // 返 回: 无
- void CQGISAlgorithmLib::B3_curves(double * x, double * y, double * tx, double * ty, int N, int k)
- {
- double t0,t1,t2,t3;
- x[0]=6.0*x[0]-4.0*x[1]-x[2]; //////////////////////////////
- y[0]=6.0*y[0]-4.0*y[1]-y[2]; //返回原曲线首尾点条件三次B样条曲线
- x[N-1]=6.0*x[N-1]-4.0*x[N-2]-x[N-3]; //如果不需要返回,屏蔽这四句话
- y[N-1]=6.0*y[N-1]-4.0*y[N-2]-y[N-3]; //////////////////////////////
- tx[0]=(x[0]+4.0*x[1]+x[2])/6.0; //第一个点
- ty[0]=(y[0]+4.0*y[1]+y[2])/6.0;
- int nCount = 1;
- for(int i=1;i<N-2;i++)
- for(int j=1;j<=k;j++)
- {
- t3=1.0*j/k;
- t0=1-t3;
- t0=t0*t0*t0/6.0; // 1/6*(1-t)*(1-t)*(1-t)
- t1=((3.0*t3-6.0)*t3*t3+4.0)/6.0;// 1/6*(3*t*t*t-6*t*t+4)
- t2=(((3-3*t3)*t3+3)*t3+1)/6.0; // 1/6*(-3*t*t*t+3*t*t*3*t+1)
- t3=1.0-t0-t1-t2; // 1/6*t*t*t
- tx[nCount] = x[i-1]*t0+x[i]*t1+x[i+1]*t2+x[i+2]*t3;
- ty[nCount] = y[i-1]*t0+y[i]*t1+y[i+1]*t2+y[i+2]*t3;
- nCount++;
- }
- }
- // 函 数 名: B3_curves
- // 功 能: 三次B样条曲线
- // 参 数:
- // n, 结点的总数
- // m, 每段的分段数
- // x, 一维数组, 结点的X坐标值
- // y, 一维数组, 结点的Y坐标值
- // tx,一维数组, 待插值点(包括结点)的X坐标值
- // ty,一维数组, 待插值点(包括结点)的Y坐标值
- // (入口): float * x, float * y, float * tx, float * ty, int n, int k
- // (出口): float * tx, float * ty
- // 返 回: 无
- void CQGISAlgorithmLib::B3_curves(float * x, float * y, float * tx, float * ty, int N, int k)
- {
- float t0,t1,t2,t3;
- x[0]=6.0f*x[0]-4.0f*x[1]-x[2]; //////////////////////////////
- y[0]=6.0f*y[0]-4.0f*y[1]-y[2]; //返回原曲线首尾点条件三次B样条曲线
- x[N-1]=6.0f*x[N-1]-4.0f*x[N-2]-x[N-3]; //如果不需要返回,屏蔽这四句话
- y[N-1]=6.0f*y[N-1]-4.0f*y[N-2]-y[N-3]; //////////////////////////////
- tx[0]=(x[0]+4.0f*x[1]+x[2])/6.0f; //第一个点
- ty[0]=(y[0]+4.0f*y[1]+y[2])/6.0f;
- int nCount = 1;
- for(int i=1;i<N-2;i++)
- for(int j=1;j<=k;j++)
- {
- t3=1.0f*j/k;
- t0=1-t3;
- t0=t0*t0*t0/6.0f;
- t1=((3.0f*t3-6.0f)*t3*t3+4.0f)/6.0f;
- t2=(((3-3*t3)*t3+3)*t3+1)/6.0f;
- t3=1.0f-t0-t1-t2;
- tx[nCount] = x[i-1]*t0+x[i]*t1+x[i+1]*t2+x[i+2]*t3;
- ty[nCount] = y[i-1]*t0+y[i]*t1+y[i+1]*t2+y[i+2]*t3;
- nCount++;
- }
- }
- ////////////////////////////////////////////////////////////////////////////
- // 参数: n, 结点数
- // m, 待插值点数
- // x[], 一维数组, 结点的X坐标值( X0 < X1 < X2 < ... < Xn-1 )
- // y[], 一维数组, 结点的Y坐标值
- // t[], 一维数组, 待插值点的X坐标值
- // z[], 一维数组, 待插值点的Y坐标值
- // 返回: float, 结点X轴围成的区域面积(积分)
- // 参考: 徐士良. C常用算法程序集(Edition 2). 北京: 清华大学出版社.1996
- // 时间: 2003-08-13.
- // 三次样条函数插值(第二种边界条件)
- double CQGISAlgorithmLib::Spline2D(double * x, double * y, double * t, double * z, int n, int m)
- {
- int i,j;
- double h0,h1,alpha,beta,g,*s, *dy, *ddy, *dz, *ddz;
- if(n==2)/// 如果结点为两个, 则直接线性插值
- {
- Interpolation_curve(x, y, t, z, n, m);
- return 0.0;
- }
- // 变量的意义:
- // g : 函数在 [X0, Xn-1] 上的积分(围成的面积)
- // dy : 函数在结点处的一阶导数值
- // ddy: 函数在结点处的二阶导数值
- // dz : 函数在待插值点处的一阶导数值
- // ddz: 函数在待插值点处的二阶导数值
- // 在徐中是作为输出的, 由于实际应用时, 没有必要知道导数值, 因此内含不输出
- s = (double*)malloc(n*sizeof(double));
- dy = (double*)malloc(n*sizeof(double));
- ddy = (double*)malloc(n*sizeof(double));
- // 原则上, 第二种边界条件中ddy[0]与ddy[n-1]是用户给定的, 本程序为了方便计算,
- // 设为0, 表示是光滑的, 这可以满足一般的曲线的样条光滑问题的条件
- ddy[0] = 0.0f;
- ddy[n-1] = 0.0f;
- dz = (double*)malloc(m*sizeof(double));
- ddz = (double*)malloc(m*sizeof(double));
- dy[0]=-0.5;
- h0=x[1]-x[0];
- s[0]=3.0f*(y[1]-y[0])/(2.0f*h0)-ddy[0]*h0/4.0f;
- for (j=1;j<=n-2;j++)
- {
- h1=x[j+1]-x[j];
- alpha=h0/(h0+h1);
- beta=(1.0f-alpha)*(y[j]-y[j-1])/h0;
- beta=3.0f*(beta+alpha*(y[j+1]-y[j])/h1);
- dy[j]=-alpha/(2.0f+(1.0f-alpha)*dy[j-1]);
- s[j]=(beta-(1.0f-alpha)*s[j-1]);
- s[j]=s[j]/(2.0f+(1.0f-alpha)*dy[j-1]);
- h0=h1;
- }
- dy[n-1]=(3.0f*(y[n-1]-y[n-2])/h1+ddy[n-1]*h1/2.0f-s[n-2])/(2.0f+dy[n-2]);
- for (j=n-2;j>=0;j--)
- dy[j]=dy[j]*dy[j+1]+s[j];
- for (j=0;j<=n-2;j++)
- s[j]=x[j+1]-x[j];
- for (j=0;j<=n-2;j++)
- {
- h1=s[j]*s[j];
- ddy[j]=6.0f*(y[j+1]-y[j])/h1-2.0f*(2.0f*dy[j]+dy[j+1])/s[j];
- }
- h1=s[n-2]*s[n-2];
- ddy[n-1]=6.f*(y[n-2]-y[n-1])/h1+2.f*(2.f*dy[n-1]+dy[n-2])/s[n-2];
- g=0.0;
- for (i=0;i<=n-2;i++)
- {
- h1=0.5f*s[i]*(y[i]+y[i+1]);
- h1=h1-s[i]*s[i]*s[i]*(ddy[i]+ddy[i+1])/24.0f;
- g=g+h1;
- }
- for (j=0;j<=m-1;j++)
- {
- if (t[j]>=x[n-1]) i=n-2;
- else
- {
- i=0;
- while (t[j]>x[i+1]) i=i+1;
- }
- h1=(x[i+1]-t[j])/s[i];
- h0=h1*h1;
- z[j]=(3.0f*h0-2.0f*h0*h1)*y[i];
- z[j]=z[j]+s[i]*(h0-h0*h1)*dy[i];
- dz[j]=6.0f*(h0-h1)*y[i]/s[i];
- dz[j]=dz[j]+(3.0f*h0-2.0f*h1)*dy[i];
- ddz[j]=(6.0f-12.0f*h1)*y[i]/(s[i]*s[i]);
- ddz[j]=ddz[j]+(2.0f-6.0f*h1)*dy[i]/s[i];
- h1=(t[j]-x[i])/s[i];
- h0=h1*h1;
- z[j]=z[j]+(3.0f*h0-2.0f*h0*h1)*y[i+1];
- z[j]=z[j]-s[i]*(h0-h0*h1)*dy[i+1];
- dz[j]=dz[j]-6.0f*(h0-h1)*y[i+1]/s[i];
- dz[j]=dz[j]+(3.0f*h0-2.0f*h1)*dy[i+1];
- ddz[j]=ddz[j]+(6.0f-12.0f*h1)*y[i+1]/(s[i]*s[i]);
- ddz[j]=ddz[j]-(2.0f-6.0f*h1)*dy[i+1]/s[i];
- }
- free(s);
- free(dy);
- free(ddy);
- free(dz);
- free(ddz);
- return(g);
- }
- ////////////////////////////////////////////////////////////////////////////
- // 参数: n, 结点数
- // m, 待插值点数
- // x, 一维数组, 结点的X坐标值( X0 < X1 < X2 < ... < Xn-1 )
- // y, 一维数组, 结点的Y坐标值
- // t, 一维数组, 待插值点的X坐标值
- // z, 一维数组, 待插值点的Y坐标值
- // 返回: float, 结点X轴围成的区域面积(积分)
- // 参考: 徐士良. C常用算法程序集(Edition 2). 北京: 清华大学出版社.1996
- // 时间: 2003-08-13.
- // 三次样条函数插值(第二种边界条件)
- float CQGISAlgorithmLib::Spline2D(float * x, float * y, float * t, float * z, int n, int m)
- {
- int i,j;
- float h0,h1,alpha,beta,g,*s, *dy, *ddy, *dz, *ddz;
- if(n==2)/// 如果结点为两个, 则直接线性插值
- {
- Interpolation_curve(x, y, t, z, n, m);
- return 0.0f;
- }
- // 变量的意义:
- // g : 函数在 [X0, Xn-1] 上的积分(围成的面积)
- // dy : 函数在结点处的一阶导数值
- // ddy: 函数在结点处的二阶导数值
- // dz : 函数在待插值点处的一阶导数值
- // ddz: 函数在待插值点处的二阶导数值
- // 在徐中是作为输出的, 由于实际应用时, 没有必要知道导数值, 因此内含不输出
- s = (float*)malloc(n*sizeof(float));
- dy = (float*)malloc(n*sizeof(float));
- ddy = (float*)malloc(n*sizeof(float));
- // 原则上, 第二种边界条件中ddy[0]与ddy[n-1]是用户给定的, 本程序为了方便计算,
- // 设为0, 表示是光滑的, 这可以满足一般的曲线的样条光滑问题的条件
- ddy[0] = 0.0f;
- ddy[n-1] = 0.0f;
- dz = (float*)malloc(m*sizeof(float));
- ddz = (float*)malloc(m*sizeof(float));
- dy[0]=-0.5;
- h0=x[1]-x[0];
- s[0]=3.0f*(y[1]-y[0])/(2.0f*h0)-ddy[0]*h0/4.0f;
- for (j=1;j<=n-2;j++)
- {
- h1=x[j+1]-x[j];
- alpha=h0/(h0+h1);
- beta=(1.0f-alpha)*(y[j]-y[j-1])/h0;
- beta=3.0f*(beta+alpha*(y[j+1]-y[j])/h1);
- dy[j]=-alpha/(2.0f+(1.0f-alpha)*dy[j-1]);
- s[j]=(beta-(1.0f-alpha)*s[j-1]);
- s[j]=s[j]/(2.0f+(1.0f-alpha)*dy[j-1]);
- h0=h1;
- }
- dy[n-1]=(3.0f*(y[n-1]-y[n-2])/h1+ddy[n-1]*h1/2.0f-s[n-2])/(2.0f+dy[n-2]);
- for (j=n-2;j>=0;j--)
- dy[j]=dy[j]*dy[j+1]+s[j];
- for (j=0;j<=n-2;j++)
- s[j]=x[j+1]-x[j];
- for (j=0;j<=n-2;j++)
- {
- h1=s[j]*s[j];
- ddy[j]=6.0f*(y[j+1]-y[j])/h1-2.0f*(2.0f*dy[j]+dy[j+1])/s[j];
- }
- h1=s[n-2]*s[n-2];
- ddy[n-1]=6.f*(y[n-2]-y[n-1])/h1+2.f*(2.f*dy[n-1]+dy[n-2])/s[n-2];
- g=0.0;
- for (i=0;i<=n-2;i++)
- {
- h1=0.5f*s[i]*(y[i]+y[i+1]);
- h1=h1-s[i]*s[i]*s[i]*(ddy[i]+ddy[i+1])/24.0f;
- g=g+h1;
- }
- for (j=0;j<=m-1;j++)
- {
- if (t[j]>=x[n-1]) i=n-2;
- else
- {
- i=0;
- while (t[j]>x[i+1]) i=i+1;
- }
- h1=(x[i+1]-t[j])/s[i];
- h0=h1*h1;
- z[j]=(3.0f*h0-2.0f*h0*h1)*y[i];
- z[j]=z[j]+s[i]*(h0-h0*h1)*dy[i];
- dz[j]=6.0f*(h0-h1)*y[i]/s[i];
- dz[j]=dz[j]+(3.0f*h0-2.0f*h1)*dy[i];
- ddz[j]=(6.0f-12.0f*h1)*y[i]/(s[i]*s[i]);
- ddz[j]=ddz[j]+(2.0f-6.0f*h1)*dy[i]/s[i];
- h1=(t[j]-x[i])/s[i];
- h0=h1*h1;
- z[j]=z[j]+(3.0f*h0-2.0f*h0*h1)*y[i+1];
- z[j]=z[j]-s[i]*(h0-h0*h1)*dy[i+1];
- dz[j]=dz[j]-6.0f*(h0-h1)*y[i+1]/s[i];
- dz[j]=dz[j]+(3.0f*h0-2.0f*h1)*dy[i+1];
- ddz[j]=ddz[j]+(6.0f-12.0f*h1)*y[i+1]/(s[i]*s[i]);
- ddz[j]=ddz[j]-(2.0f-6.0f*h1)*dy[i+1]/s[i];
- }
- free(s);
- free(dy);
- free(ddy);
- free(dz);
- free(ddz);
- return(g);
- }
- ////////////////////////////////////////////////////////////////////////
- // 参数:
- // n, 结点的总数
- // m, 每段的分段数
- // x[], 一维数组, 结点的X坐标值
- // y[], 一维数组, 结点的Y坐标值
- // tx[],一维数组, 待插值点(包括结点)的X坐标值
- // ty[],一维数组, 待插值点(包括结点)的Y坐标值
- // 出口:
- // tx, ty
- // 返回:
- // 无
- // 思路:
- // 以每个结点在折线上的距离D为因变量, X, Y分别作为D的函数进行二维的样条
- // 插值(第二种边界条件)
- // Notes:
- // 比如 n 个结点, 则有(n-1)段, 对每段平均分成 m 段, 则待插值点总数为 m(n-1)+1
- // Modification history:
- // 二维曲线的样条光滑
- void CQGISAlgorithmLib::SplineClean2D(double * x, double * y, double * tx, double * ty, int n, int m)
- {
- int nTotal, i, j, k;
- double *dis, *disT, deltaDis = 0.0f;
- nTotal= m*(n-1)+1;
- dis = (double*)malloc(n*sizeof(double));
- disT = (double*)malloc(nTotal*sizeof(double));
- dis[0] = disT[0] = 0.0f;
- for(i=1, k=1; i<n; i++)
- {
- deltaDis = (double)sqrt(( x[i]-x[i-1])*(x[i]-x[i-1]) +
- (y[i]-y[i-1])*(y[i]-y[i-1]));
- dis[i] = dis[i-1] + deltaDis;
- deltaDis = (double)(deltaDis/m);
- for(j=1; j<=m; j++, k++)
- {
- disT[k] = disT[k-1] + deltaDis;
- }
- }
- Spline2D(dis, x, disT, tx, n, nTotal);
- Spline2D(dis, y, disT, ty, n, nTotal);
- for(i=0, j=0; i<n; i++, j+=m)
- {
- tx[j] = x[i];
- ty[j] = y[i];
- }
- free(dis);
- free(disT);
- }
- ////////////////////////////////////////////////////////////////////////
- // 参数:
- // n, 结点的总数
- // m, 每段的分段数
- // x, 一维数组, 结点的X坐标值
- // y, 一维数组, 结点的Y坐标值
- // tx,一维数组, 待插值点(包括结点)的X坐标值
- // ty,一维数组, 待插值点(包括结点)的Y坐标值
- // 出口:
- // tx, ty
- // 返回:
- // 无
- // 思路:
- // 以每个结点在折线上的距离D为因变量, X, Y分别作为D的函数进行二维的样条
- // 插值(第二种边界条件)
- // Notes:
- // 比如 n 个结点, 则有(n-1)段, 对每段平均分成 m 段, 则待插值点总数为 m(n-1)+1
- // Modification history:
- // 二维曲线的样条光滑
- void CQGISAlgorithmLib::SplineClean2D(float * x, float * y, float * tx, float * ty, int n, int m)
- {
- int nTotal, i, j, k;
- float *dis, *disT, deltaDis = 0.0f;
- nTotal= m*(n-1)+1;
- dis = (float*)malloc(n*sizeof(float));
- disT = (float*)malloc(nTotal*sizeof(float));
- dis[0] = disT[0] = 0.0f;
- for(i=1, k=1; i<n; i++)
- {
- deltaDis = (float)sqrt(( x[i]-x[i-1])*(x[i]-x[i-1]) +
- (y[i]-y[i-1])*(y[i]-y[i-1]));
- dis[i] = dis[i-1] + deltaDis;
- deltaDis = (float)(deltaDis/m);
- for(j=1; j<=m; j++, k++)
- {
- disT[k] = disT[k-1] + deltaDis;
- }
- }
- Spline2D(dis, x, disT, tx, n, nTotal);
- Spline2D(dis, y, disT, ty, n, nTotal);
- for(i=0, j=0; i<n; i++, j+=m)
- {
- tx[j] = x[i];
- ty[j] = y[i];
- }
- free(dis);
- free(disT);
- }
- BOOL CQGISAlgorithmLib::PtListBeThin(CQPointArray & ptArray, double beThinElem)
- {
- int nCount = ptArray.GetSize();
- if(nCount<=2) return FALSE;
- int i=1;
- while(i<nCount)
- {
- double x1=0.0f,x2=0.0f,y1=0.0f,y2=0.0f;
- x1 = ptArray.GetPoint(i-1)->GetX();
- y1 = ptArray.GetPoint(i-1)->GetY();
- x2 = ptArray.GetPoint(i)->GetX();
- y2 = ptArray.GetPoint(i)->GetY();
- double dis = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
- if(dis<=beThinElem) //beThinElem抽稀因子
- {
- delete ptArray.RemoveAt(i);
- i--;
- }
- nCount = ptArray.GetSize();
- if(nCount<=2) break;
- i++;
- }
- return TRUE;
- }
- //道格拉斯-普克法算法描述
- //首先,将一条曲线首、末点连一条直线,求出其余各点到该直线的距离
- //选其最大者与规定的临界值相比较,若大于临界值,则离该直线距离最
- //大的点保留,否则将直线两端间各点全部舍去
- void CQGISAlgorithmLib::PtListLess(CQPointArray & ptArray,double beThin /* = 0.0001f */)
- {
- UINT ptCount = ptArray.GetSize();
- if(ptCount <= 2)
- return; // 假如传入的是一个空数组 就退出
- CQPointArray ptNewArray; //目标点数组
- //首、末两个点是肯定要的
- CQPoint ptFirst = *ptArray.GetPoint(0);
- CQPoint ptLast = *ptArray.GetPoint(ptCount-1);
- ptNewArray.AddPoint(ptFirst.GetX(),ptFirst.GetY());
- //通过计算将符合要求的点都添加到目标点数组中并最终返回
- UINT i = 1;
- while(i<ptCount-1)
- {
- CQPoint * pPt = ptArray.GetPoint(i++);
- if(pPt != NULL)
- {
- double fDis = pPt->Distance(ptFirst,ptLast);
- if(fDis-beThin>=0.000001f)
- {
- ptNewArray.AddPoint(pPt->GetX(),pPt->GetY());
- }
- }
- }
- ptNewArray.AddPoint(ptLast.GetX(),ptLast.GetY());
- ptArray.DeleteAll();
- ptArray.Copy(ptNewArray);
- }
- double CQGISAlgorithmLib::ConvertFontPttoMM(double pt)
- {
- return pt*0.35146;
- }