QGISAlgorithmLib.cpp
上传用户:oybseng
上传日期:2015-04-27
资源大小:7831k
文件大小:26k
源码类别:

GDI/图象编程

开发平台:

Visual C++

  1. // QGISAlgorithmLib->cpp: implementation of the CQGISAlgorithmLib class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "..stdafx.h"
  5. #include "....QObjectsincludeResource.h"
  6. #include "..includeResource.h"
  7. #include "..includeQGISAlgorithmLib.h"
  8. #include "....QObjectsincludeQLineObj.h"
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char THIS_FILE[]=__FILE__;
  12. #define new DEBUG_NEW
  13. #endif
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. CQGISAlgorithmLib::CQGISAlgorithmLib()
  18. {
  19. }
  20. CQGISAlgorithmLib::~CQGISAlgorithmLib()
  21. {
  22. }
  23. //////////////////////////////////////////
  24. ///***************CQGIS****************///
  25. ///函数名称:IsLineCross
  26. ///返回类型:BOOL
  27. ///入口参数:CQPoint p1,CQPoint p2,CQPoint q1,CQPoint q2
  28. ///出口参数:无
  29. ///思路说明:边界矩形,矢量跨立实验
  30. ///***************CQGIS****************///
  31. //////////////////////////////////////////
  32. BOOL CQGISAlgorithmLib::IsLineCross(CQPoint p1,CQPoint p2,CQPoint q1,CQPoint q2)
  33. {
  34. //创建两条直线对象 用于进行边界矩形的判断
  35. if(p1 == q1 || p1 == q2 || p2 == q1 || p2 == q2)
  36. return TRUE; //直接得出直线相交
  37. CQLineObj * pLine1 = new CQLineObj;
  38. pLine1->m_PtList.AddPoint(&p1);
  39. pLine1->m_PtList.AddPoint(&p2);
  40. CQLineObj * pLine2 = new CQLineObj;
  41. pLine2->m_PtList.AddPoint(&q1);
  42. pLine2->m_PtList.AddPoint(&q2);
  43. CBoundaryRect * pRect1 = new CBoundaryRect;
  44. pLine1->GetBoundingRect(pRect1);
  45. CBoundaryRect * pRect2 = new CBoundaryRect;
  46. pLine2->GetBoundingRect(pRect2);
  47. if(!pRect1->IsCross(pRect2))
  48. {
  49. //假如两个边界矩形不相交
  50. delete pRect2;
  51. delete pRect1;
  52. delete pLine2;
  53. delete pLine1;
  54. return FALSE; //不相交
  55. }
  56. //进行跨立实验
  57. double p1q1x = p1.GetX() - q1.GetX();
  58. double p1q1y = p1.GetY() - q1.GetY();
  59. double q2q1x = q2.GetX() - q1.GetX();
  60. double q2q1y = q2.GetY() - q1.GetY();
  61. double p2q1x = p2.GetX() - q1.GetX();
  62. double p2q1y = p2.GetY() - q1.GetY();
  63. double fResult;  //运算结果
  64. double fpq = p1q1x*q2q1y - q2q1x*p1q1y;
  65. double fqp = q2q1x*p2q1y - p2q1x*q2q1y;
  66. fResult = fpq*fqp;
  67. if(fResult>=0)
  68. {
  69. delete pRect2;
  70. delete pRect1;
  71. delete pLine2;
  72. delete pLine1;
  73. return TRUE;
  74. }
  75. delete pRect2;
  76. delete pRect1;
  77. delete pLine2;
  78. delete pLine1;
  79. return FALSE;
  80. }
  81. //////////////////////////////////////////
  82. ///***************CQGIS****************///
  83. ///函数名称:CalLineCrossPoint
  84. ///返回类型:无
  85. ///入口参数:CQPoint p1,CQPoint p2,CQPoint q1,CQPoint q2
  86. ///出口参数:CQPointArray * pResult
  87. ///思路说明:判断两条直线是否相交,若相交则返回其交点
  88. ///***************CQGIS****************///
  89. //////////////////////////////////////////
  90. void CQGISAlgorithmLib::CalLineCrossPoint(CQPoint pp1,CQPoint pp2,CQPoint qq1,CQPoint qq2,CQPointArray * pResult)
  91. {
  92. if(!IsLineCross(pp1,pp2,qq1,qq2))
  93. {
  94. pResult = 0;
  95. return;
  96. }
  97. CQPoint * p1 = new CQPoint(pp1);
  98. CQPoint * p2 = new CQPoint(pp2);
  99. CQPoint * q1 = new CQPoint(qq1);
  100. CQPoint * q2 = new CQPoint(qq2);
  101. //计算两条直线的斜率
  102. //double k1 = (p2.GetY()-p1.GetY())/(p2.GetX()-p1.GetX());
  103. //double k2 = (q2.GetY()-q1.GetY())/(q2.GetX()-q1.GetX());
  104. //L0(p1,p2),L1(q1,q2);
  105. //情况1 L0平行于Y轴
  106. //分两种情况 当L1也与Y轴平行时,则两条直线共线 
  107. //若L1与Y轴不平行,则直接代入方程求解
  108. if(p1->GetX() == p2->GetX())
  109. {
  110. if(q1->GetX() == q2->GetX()) //L1也与Y轴平行
  111. {
  112. CalSameLineCrossPoint(*p1,*p2,*q1,*q2,pResult);
  113. return;
  114. }
  115. else      //L1与Y轴不平行
  116. {
  117. double k2 = (q2->GetY()-q1->GetY())/(q2->GetX()-q1->GetX());
  118. double x2 = p1->GetX();
  119. //y2 = k2x2-k2x1+y1;x1 = q1->GetX(),y1 = q1->getY();
  120. double y2 = k2*x2-k2*q1->GetX()+q1->GetY();
  121. pResult->AddPoint(x2,y2);
  122. delete q2;
  123. }
  124. }
  125. else if(q1->GetX() == q2->GetX())
  126. {
  127. double k1 = (p2->GetY()-p1->GetY())/(p2->GetX()-p1->GetX());
  128. double x1 = q1->GetX(),y1;
  129. y1 = k1*x1-k1*p1->GetX()+p1->GetY();
  130. pResult->AddPoint(x1,y1);
  131. }
  132. else if(p1->GetY() == p2->GetY()) //平行与X 轴
  133. {
  134. if(q1->GetY() == q2->GetY())  //L1也平行与X轴
  135. {
  136. CalSameLineCrossPoint(*p1,*p2,*q1,*q2,pResult);
  137. }
  138. else
  139. {
  140. double k2 = (q2->GetY()-q1->GetY())/(q2->GetX()-q1->GetX());
  141. double y2 = p1->GetY();
  142. double x2 = (y2+k2*q1->GetX()-q1->GetY())/k2;
  143. pResult->AddPoint(x2,y2);
  144. }
  145. }
  146. else if(q1->GetY() == q2->GetY())
  147. {
  148. double k1 = (p2->GetY()-p1->GetY())/(p2->GetX()-p1->GetX());
  149. double y1 = q1->GetY();
  150. double x1 = (y1+k1*p1->GetX()-p1->GetY())/k1;
  151. pResult->AddPoint(x1,y1);
  152. }
  153. else
  154. {
  155. double k1 = (p2->GetY()-p1->GetY())/(p2->GetX()-p1->GetX());
  156. double k2 = (q2->GetY()-q1->GetY())/(q2->GetX()-q1->GetX());
  157. if(k1-k2 == SMALL_NUMBER)
  158. {
  159. CalSameLineCrossPoint(*p1,*p2,*q1,*q1,pResult);
  160. }
  161. else
  162. {
  163. double xResult = k1*p1->GetX()-k2*q1->GetX()+q1->GetY()-p1->GetY();
  164. xResult = xResult/(k1-k2);
  165. double yResult = k1*xResult-k1*p1->GetX()+p1->GetY();
  166. pResult->AddPoint(xResult,yResult);
  167. }
  168. }
  169. delete q2;
  170. delete q1;
  171. delete p2;
  172. delete p1;
  173. }
  174. //////////////////////////////////////////
  175. ///***************CQGIS****************///
  176. ///函数名称:CalSameLineCrossPoint
  177. ///返回类型:无
  178. ///入口参数:CQPoint p1,CQPoint p2,CQPoint q1,CQPoint q2
  179. ///出口参数:CQPointArray * pResult
  180. ///思路说明:
  181. ///***************CQGIS****************///
  182. //////////////////////////////////////////
  183. void CQGISAlgorithmLib::CalSameLineCrossPoint(CQPoint pp1,CQPoint pp2,CQPoint qq1,CQPoint qq2,CQPointArray * pResult)
  184. {
  185. //直接计算 不做条件判断 在调用之前一定要确保两直线是相交的
  186. //共线计算只考虑垂直于X,Y轴的情形
  187. double fy1,fy2;
  188. double fy3,fy4;
  189. double fx1,fx2;
  190. double fx3,fx4;
  191. CQPoint * p1 = new CQPoint(pp1);
  192. CQPoint * p2 = new CQPoint(pp2);
  193. CQPoint * q1 = new CQPoint(qq1);
  194. CQPoint * q2 = new CQPoint(qq2);
  195. //先找出较长的直线
  196. double dd1 = p1->Distance(*p2);
  197. double dd2 = q1->Distance(*q2);
  198. //始终用较长的线段为基准进行判断
  199. if(dd1<dd2)
  200. {
  201. CQPoint tmPoint = *p1;
  202. *p1 = *q1;
  203. *q1 = tmPoint;
  204. tmPoint = *p2;
  205. *p2 = *q2;
  206. *q2 = tmPoint;
  207. }
  208. if(p1->GetX() == p2->GetX() && q1->GetX() == q2->GetX())  //两条直线都与Y轴平行 
  209. {
  210. fy1 = min(p1->GetY(),p2->GetY());
  211. fy2 = max(p1->GetY(),p2->GetY());
  212. fy3 = min(q1->GetY(),q2->GetY());
  213. fy4 = max(q1->GetY(),q2->GetY());
  214. p1->SetPoint(p1->GetX(),fy1);  //Y较小的点
  215. p2->SetPoint(p2->GetX(),fy2);  //Y较大的点
  216. q1->SetPoint(q1->GetX(),fy3);
  217. q2->SetPoint(q2->GetX(),fy4);
  218. if(p1->GetY() > q2->GetY() || p2->GetY() < q1->GetY())
  219. {
  220. pResult = 0;
  221. }
  222. else
  223. {
  224. if(p2->GetY() == q1->GetY())
  225. {
  226. pResult->AddPoint(p2->GetX(),p2->GetY());
  227. }
  228. else if(q1->GetY()<p2->GetY() && q1->GetY() >p1->GetY())
  229. {
  230. if(p2->GetY()>q1->GetY() && p2->GetY()<q2->GetY())
  231. {
  232. pResult->AddPoint(q1->GetX(),q1->GetY());
  233. pResult->AddPoint(p2->GetX(),p2->GetY());
  234. }
  235. else if(p2->GetY()>=q2->GetY())
  236. {
  237. pResult->AddPoint(q1->GetX(),q1->GetY());
  238. pResult->AddPoint(q2->GetY(),q2->GetY());
  239. }
  240. }
  241. else if(*p1 == *q1 && *p2 == *q2)  //两直线重合
  242. {
  243. pResult->AddPoint(p1->GetX(),p1->GetY());
  244. pResult->AddPoint(p2->GetX(),p2->GetY());
  245. }
  246. }
  247. }
  248. else if(p1->GetY() == p2->GetY() && q1->GetY() == q2->GetY())  //两条直线都与X轴平行 
  249. {
  250. fx1 = min(p1->GetX(),p2->GetX());
  251. fx2 = max(p1->GetX(),p2->GetX());
  252. fx3 = min(q1->GetX(),q2->GetX());
  253. fx4 = max(q1->GetX(),q2->GetX());
  254. p1->SetPoint(fx1,p1->GetY());
  255. p2->SetPoint(fx2,p2->GetY());
  256. q1->SetPoint(fx3,q1->GetY());
  257. q2->SetPoint(fx4,q2->GetY());
  258. if(p2->GetX() < q1->GetX() || p1->GetX() > q2->GetX())
  259. {
  260. pResult = 0;
  261. }
  262. else if(q1->GetX()>p1->GetX() && q1->GetX()<p2->GetX())
  263. {
  264. if(p2->GetX()>q1->GetX() && p2->GetX()<q2->GetX())
  265. {
  266. pResult->AddPoint(q1->GetX(),q1->GetY());
  267. pResult->AddPoint(p2->GetX(),p2->GetY());
  268. }
  269. else if(p2->GetX()>=q2->GetX())
  270. {
  271. pResult->AddPoint(q1->GetX(),q1->GetY());
  272. pResult->AddPoint(q2->GetX(),q2->GetY());
  273. }
  274. }
  275. else if(p2->GetX() == q1->GetX())
  276. {
  277. pResult->AddPoint(p2->GetX(),p2->GetY());
  278. }
  279. else if(*p1 == *q1 && *p2 == *q2)
  280. {
  281. pResult->AddPoint(p1->GetX(),p2->GetY());
  282. pResult->AddPoint(p2->GetX(),p2->GetY());
  283. }
  284. }
  285. else   //两条直线只是斜率相等
  286. {
  287. if(p1->GetX()>p2->GetX())
  288. {
  289. CQPoint tmPoint;
  290. tmPoint = *p1;
  291. *p1 = *p2;
  292. *p2 = tmPoint;
  293. }
  294. if(q1->GetX()>q2->GetX())
  295. {
  296. CQPoint tmPoint;
  297. tmPoint = *q1;
  298. *q1 = *q2;
  299. *q2 = tmPoint;
  300. }
  301. if(p2->GetX()<q1->GetX())
  302. {
  303. CQPoint tmPoint = *q1;
  304. *p1 = *q1;
  305. *q1 = tmPoint;
  306. tmPoint = *q2;
  307. *p2 = *q2;
  308. *q2 = tmPoint;
  309. }
  310. if(p2->GetX() < q1->GetX() || p1->GetX() > q2->GetX())
  311. {
  312. pResult = 0;
  313. return;
  314. }
  315. else if(q1->GetX()>p1->GetX() && q1->GetX()<p2->GetX())
  316. {
  317. if(p2->GetX()>q1->GetX() && p2->GetX()<q2->GetX())
  318. {
  319. pResult->AddPoint(q1->GetX(),q1->GetY());
  320. pResult->AddPoint(p2->GetX(),p2->GetY());
  321. }
  322. else if(p2->GetX()>=q2->GetX())
  323. {
  324. pResult->AddPoint(q1->GetX(),q1->GetY());
  325. pResult->AddPoint(q2->GetX(),q2->GetY());
  326. }
  327. }
  328. else if(p2->GetX() == q1->GetX())
  329. {
  330. pResult->AddPoint(p2->GetX(),p2->GetY());
  331. }
  332. else if(*p1 == *q1 && *p2 == *q2)
  333. {
  334. pResult->AddPoint(p1->GetX(),p1->GetY());
  335. pResult->AddPoint(p2->GetX(),p2->GetY());
  336. }
  337. }
  338. delete q2;
  339. delete q1;
  340. delete p2;
  341. delete p1;
  342. }
  343. //弧度转换为度单位
  344. double CQGISAlgorithmLib::RadianToDegree(double fRadian)
  345. {
  346. return fRadian*PIunder180;
  347. }
  348. double CQGISAlgorithmLib::DegreeToRadian(double fDegree)
  349. {
  350. return fDegree*PIover180;
  351. }
  352. ////////////////////////////////////////////////////////////////////////////
  353. // 参数: nBegin, 结点数
  354. // nEnd,   待插值点数
  355. // FromX,  一维数组, 结点的X坐标值( FromX0 < FromX1 < FromX2 < ... <FromXn-1 )
  356. // FromY,  一维数组, 结点的Y坐标值
  357. // ToX,    一维数组, 待插值点的X坐标值
  358. // ToY,    一维数组, 待插值点的Y坐标值
  359. // 返回:    void
  360. void CQGISAlgorithmLib::Interpolation_curve(float * FromX,float * FromY,float * ToX,float * ToY,int nBeign,int nEnd)
  361. {
  362. for(int i=0, k=0; i<nEnd; i++)
  363. {
  364. k = 0;
  365. if(ToX[i]>=FromX[nBeign-1]) k=nBeign-2;
  366. else
  367. {
  368. while (ToX[i]>FromX[k+1]) k++;
  369. }
  370. ToY[i] = (FromX[k]*(FromX[k+1]-ToX[i])+FromX[k+1]*(ToX[i]-FromX[k]))/(FromX[k+1]-FromX[k]);
  371. }
  372. }
  373. ////////////////////////////////////////////////////////////////////////////
  374. // 参数: nBegin, 结点数
  375. // nEnd,   待插值点数
  376. // FromX,  一维数组, 结点的X坐标值( FromX0 < FromX1 < FromX2 < ... <FromXn-1 )
  377. // FromY,  一维数组, 结点的Y坐标值
  378. // ToX,    一维数组, 待插值点的X坐标值
  379. // ToY,    一维数组, 待插值点的Y坐标值
  380. // 返回:    void
  381. void CQGISAlgorithmLib::Interpolation_curve(double * FromX,double * FromY,double * ToX,double * ToY,int nBeign,int nEnd)
  382. {
  383. for(int i=0, k=0; i<nEnd; i++)
  384. {
  385. k = 0;
  386. if(ToX[i]>=FromX[nBeign-1]) k=nBeign-2;
  387. else
  388. {
  389. while (ToX[i]>FromX[k+1]) k++;
  390. }
  391. ToY[i] = (FromX[k]*(FromX[k+1]-ToX[i])+FromX[k+1]*(ToX[i]-FromX[k]))/(FromX[k+1]-FromX[k]);
  392. }
  393. }
  394. // 函 数 名: B2_curves
  395. // 功    能: 二次B样条曲线
  396. // 参    数:
  397. // N, 结点的总数
  398. // m, 每段的分段数
  399. // x, 一维数组, 结点的X坐标值
  400. // y, 一维数组, 结点的Y坐标值
  401. // tx,一维数组, 待插值点(包括结点)的X坐标值
  402. // ty,一维数组, 待插值点(包括结点)的Y坐标值
  403. //   (入口): float * x, float * y, float * tx, float * ty, int n, int k
  404. //   (出口): float tx, float ty
  405. // 返    回: 无
  406. // 调用方法:
  407. void CQGISAlgorithmLib::B2_curves(float * x, float * y, float * tx, float * ty, int n, int k)
  408. {
  409. float t,t1,t2;
  410. float a,b,c;
  411. t = 1.0f/k;
  412. tx[0]=(x[0]+x[1])/2; //第一个点为原始一二两点的中点
  413. ty[0]=(y[0]+y[1])/2;
  414. int nCount = 1; 
  415. for(int i=1;i<n-1;i++)
  416. for(int j=1;j<=k;j++)
  417. {
  418. t1=j*t; 
  419. t2=t1*t1; 
  420. a=(t2-2*t1+1)/2.0f; // 1/2*(t-1)(t-1)
  421. b=t1-t2+1/2.0f; // 1/2*(-2t*t+2t+1) 
  422. c=t2/2.0f; // 1/2*t*t
  423. tx[nCount] =x[i-1]*a+x[i]*b+x[i+1]*c;
  424. ty[nCount] =y[i-1]*a+y[i]*b+y[i+1]*c;
  425. nCount++;
  426. }
  427. }
  428. // 函 数 名: B2_curves
  429. // 功    能: 二次B样条曲线
  430. // 参    数:
  431. // N, 结点的总数
  432. // m, 每段的分段数
  433. // x[], 一维数组, 结点的X坐标值
  434. // y[], 一维数组, 结点的Y坐标值
  435. // tx[],一维数组, 待插值点(包括结点)的X坐标值
  436. // ty[],一维数组, 待插值点(包括结点)的Y坐标值
  437. //   (入口): double * x, double * y, double * tx, double * ty, int n, int k
  438. //   (出口): double * tx, double * ty
  439. // 返    回: 无
  440. void CQGISAlgorithmLib::B2_curves(double * x, double * y, double * tx, double * ty, int n, int k)
  441. {
  442. double t,t1,t2;
  443. double a,b,c;
  444. t = 1.0/k;
  445. tx[0]=(x[0]+x[1])/2; //第一个点为原始一二两点的中点
  446. ty[0]=(y[0]+y[1])/2;
  447. int nCount = 1; 
  448. for(int i=1;i<n-1;i++)
  449. for(int j=1;j<=k;j++)
  450. {
  451. t1=j*t; 
  452. t2=t1*t1; 
  453. a=(t2-2*t1+1)/2.0; // 1/2*(t-1)(t-1)
  454. b=t1-t2+1/2.0; // 1/2*(-2t*t+2t+1) 
  455. c=t2/2.0; // 1/2*t*t
  456. tx[nCount] =x[i-1]*a+x[i]*b+x[i+1]*c;
  457. ty[nCount] =y[i-1]*a+y[i]*b+y[i+1]*c;
  458. nCount++;
  459. }
  460. }
  461. // 函 数 名: B3_curves
  462. // 功    能: 三次B样条曲线
  463. // 参    数:
  464. // n, 结点的总数
  465. // m, 每段的分段数
  466. // x, 一维数组, 结点的X坐标值
  467. // y, 一维数组, 结点的Y坐标值
  468. // tx,一维数组, 待插值点(包括结点)的X坐标值
  469. // ty,一维数组, 待插值点(包括结点)的Y坐标值
  470. //   (入口): double * x, double * y, double * tx, double * ty, int n, int k
  471. //   (出口): double * tx, double * ty
  472. // 返    回: 无
  473. void CQGISAlgorithmLib::B3_curves(double * x, double * y, double * tx, double * ty, int N, int k)
  474. {
  475. double t0,t1,t2,t3;
  476. x[0]=6.0*x[0]-4.0*x[1]-x[2]; //////////////////////////////
  477. y[0]=6.0*y[0]-4.0*y[1]-y[2]; //返回原曲线首尾点条件三次B样条曲线
  478. x[N-1]=6.0*x[N-1]-4.0*x[N-2]-x[N-3]; //如果不需要返回,屏蔽这四句话
  479. y[N-1]=6.0*y[N-1]-4.0*y[N-2]-y[N-3]; //////////////////////////////
  480. tx[0]=(x[0]+4.0*x[1]+x[2])/6.0; //第一个点
  481. ty[0]=(y[0]+4.0*y[1]+y[2])/6.0; 
  482. int nCount = 1; 
  483. for(int i=1;i<N-2;i++)
  484. for(int j=1;j<=k;j++)
  485. {
  486. t3=1.0*j/k;
  487. t0=1-t3;
  488. t0=t0*t0*t0/6.0; // 1/6*(1-t)*(1-t)*(1-t)
  489. t1=((3.0*t3-6.0)*t3*t3+4.0)/6.0;// 1/6*(3*t*t*t-6*t*t+4)
  490. t2=(((3-3*t3)*t3+3)*t3+1)/6.0; // 1/6*(-3*t*t*t+3*t*t*3*t+1)
  491. t3=1.0-t0-t1-t2; // 1/6*t*t*t
  492. tx[nCount] = x[i-1]*t0+x[i]*t1+x[i+1]*t2+x[i+2]*t3;
  493. ty[nCount] = y[i-1]*t0+y[i]*t1+y[i+1]*t2+y[i+2]*t3;
  494. nCount++;
  495. }
  496. }
  497. // 函 数 名: B3_curves
  498. // 功    能: 三次B样条曲线
  499. // 参    数:
  500. // n, 结点的总数
  501. // m, 每段的分段数
  502. // x, 一维数组, 结点的X坐标值
  503. // y, 一维数组, 结点的Y坐标值
  504. // tx,一维数组, 待插值点(包括结点)的X坐标值
  505. // ty,一维数组, 待插值点(包括结点)的Y坐标值
  506. //   (入口): float * x, float * y, float * tx, float * ty, int n, int k
  507. //   (出口): float * tx, float * ty
  508. // 返    回: 无
  509. void CQGISAlgorithmLib::B3_curves(float * x, float * y, float * tx, float * ty, int N, int k)
  510. {
  511. float t0,t1,t2,t3;
  512. x[0]=6.0f*x[0]-4.0f*x[1]-x[2]; //////////////////////////////
  513. y[0]=6.0f*y[0]-4.0f*y[1]-y[2]; //返回原曲线首尾点条件三次B样条曲线
  514. x[N-1]=6.0f*x[N-1]-4.0f*x[N-2]-x[N-3]; //如果不需要返回,屏蔽这四句话
  515. y[N-1]=6.0f*y[N-1]-4.0f*y[N-2]-y[N-3]; //////////////////////////////
  516. tx[0]=(x[0]+4.0f*x[1]+x[2])/6.0f; //第一个点
  517. ty[0]=(y[0]+4.0f*y[1]+y[2])/6.0f; 
  518. int nCount = 1; 
  519. for(int i=1;i<N-2;i++)
  520. for(int j=1;j<=k;j++)
  521. {
  522. t3=1.0f*j/k;
  523. t0=1-t3;
  524. t0=t0*t0*t0/6.0f;
  525. t1=((3.0f*t3-6.0f)*t3*t3+4.0f)/6.0f;
  526. t2=(((3-3*t3)*t3+3)*t3+1)/6.0f;
  527. t3=1.0f-t0-t1-t2;
  528. tx[nCount] = x[i-1]*t0+x[i]*t1+x[i+1]*t2+x[i+2]*t3;
  529. ty[nCount] = y[i-1]*t0+y[i]*t1+y[i+1]*t2+y[i+2]*t3;
  530. nCount++;
  531. }
  532. }
  533. ////////////////////////////////////////////////////////////////////////////
  534. // 参数: n, 结点数
  535. // m, 待插值点数
  536. // x[], 一维数组, 结点的X坐标值( X0 < X1 < X2 < ... < Xn-1 )
  537. // y[], 一维数组, 结点的Y坐标值
  538. // t[], 一维数组, 待插值点的X坐标值
  539. // z[], 一维数组, 待插值点的Y坐标值
  540. // 返回:    float, 结点X轴围成的区域面积(积分)
  541. // 参考: 徐士良. C常用算法程序集(Edition 2). 北京: 清华大学出版社.1996
  542. // 时间: 2003-08-13.
  543. // 三次样条函数插值(第二种边界条件)
  544. double CQGISAlgorithmLib::Spline2D(double * x, double * y, double * t, double * z, int n, int m)
  545. {
  546. int i,j;
  547. double h0,h1,alpha,beta,g,*s, *dy, *ddy, *dz, *ddz;
  548. if(n==2)/// 如果结点为两个, 则直接线性插值
  549. {
  550. Interpolation_curve(x, y, t, z, n, m);
  551. return 0.0;
  552. }
  553. // 变量的意义:
  554. // g  : 函数在 [X0, Xn-1] 上的积分(围成的面积)
  555. // dy : 函数在结点处的一阶导数值
  556. // ddy: 函数在结点处的二阶导数值
  557. // dz : 函数在待插值点处的一阶导数值
  558. // ddz: 函数在待插值点处的二阶导数值
  559. // 在徐中是作为输出的, 由于实际应用时, 没有必要知道导数值, 因此内含不输出
  560. s = (double*)malloc(n*sizeof(double));
  561. dy = (double*)malloc(n*sizeof(double));
  562. ddy = (double*)malloc(n*sizeof(double));
  563. // 原则上, 第二种边界条件中ddy[0]与ddy[n-1]是用户给定的, 本程序为了方便计算, 
  564. // 设为0, 表示是光滑的, 这可以满足一般的曲线的样条光滑问题的条件
  565. ddy[0] = 0.0f;
  566. ddy[n-1] = 0.0f;
  567. dz = (double*)malloc(m*sizeof(double));
  568. ddz = (double*)malloc(m*sizeof(double));
  569. dy[0]=-0.5;
  570. h0=x[1]-x[0];
  571. s[0]=3.0f*(y[1]-y[0])/(2.0f*h0)-ddy[0]*h0/4.0f;
  572. for (j=1;j<=n-2;j++)
  573. h1=x[j+1]-x[j];
  574. alpha=h0/(h0+h1);
  575. beta=(1.0f-alpha)*(y[j]-y[j-1])/h0;
  576. beta=3.0f*(beta+alpha*(y[j+1]-y[j])/h1);
  577. dy[j]=-alpha/(2.0f+(1.0f-alpha)*dy[j-1]);
  578. s[j]=(beta-(1.0f-alpha)*s[j-1]);
  579. s[j]=s[j]/(2.0f+(1.0f-alpha)*dy[j-1]);
  580. h0=h1;
  581. }
  582. 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]);
  583. for (j=n-2;j>=0;j--)
  584. dy[j]=dy[j]*dy[j+1]+s[j];
  585. for (j=0;j<=n-2;j++) 
  586. s[j]=x[j+1]-x[j];
  587. for (j=0;j<=n-2;j++)
  588. {
  589. h1=s[j]*s[j];
  590. ddy[j]=6.0f*(y[j+1]-y[j])/h1-2.0f*(2.0f*dy[j]+dy[j+1])/s[j];
  591. }
  592. h1=s[n-2]*s[n-2];
  593. 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];
  594. g=0.0;
  595. for (i=0;i<=n-2;i++)
  596. h1=0.5f*s[i]*(y[i]+y[i+1]);
  597. h1=h1-s[i]*s[i]*s[i]*(ddy[i]+ddy[i+1])/24.0f;
  598. g=g+h1;
  599. }
  600. for (j=0;j<=m-1;j++)
  601. if (t[j]>=x[n-1]) i=n-2;
  602. else
  603. {
  604. i=0;
  605. while (t[j]>x[i+1]) i=i+1;
  606. }
  607. h1=(x[i+1]-t[j])/s[i];
  608. h0=h1*h1;
  609. z[j]=(3.0f*h0-2.0f*h0*h1)*y[i];
  610. z[j]=z[j]+s[i]*(h0-h0*h1)*dy[i];
  611. dz[j]=6.0f*(h0-h1)*y[i]/s[i];
  612. dz[j]=dz[j]+(3.0f*h0-2.0f*h1)*dy[i];
  613. ddz[j]=(6.0f-12.0f*h1)*y[i]/(s[i]*s[i]);
  614. ddz[j]=ddz[j]+(2.0f-6.0f*h1)*dy[i]/s[i];
  615. h1=(t[j]-x[i])/s[i];
  616. h0=h1*h1;
  617. z[j]=z[j]+(3.0f*h0-2.0f*h0*h1)*y[i+1];
  618. z[j]=z[j]-s[i]*(h0-h0*h1)*dy[i+1];
  619. dz[j]=dz[j]-6.0f*(h0-h1)*y[i+1]/s[i];
  620. dz[j]=dz[j]+(3.0f*h0-2.0f*h1)*dy[i+1];
  621. ddz[j]=ddz[j]+(6.0f-12.0f*h1)*y[i+1]/(s[i]*s[i]);
  622. ddz[j]=ddz[j]-(2.0f-6.0f*h1)*dy[i+1]/s[i];
  623. }
  624. free(s);
  625. free(dy);
  626. free(ddy);
  627. free(dz);
  628. free(ddz);
  629. return(g);
  630. }
  631. ////////////////////////////////////////////////////////////////////////////
  632. // 参数: n, 结点数
  633. // m, 待插值点数
  634. // x, 一维数组, 结点的X坐标值( X0 < X1 < X2 < ... < Xn-1 )
  635. // y, 一维数组, 结点的Y坐标值
  636. // t, 一维数组, 待插值点的X坐标值
  637. // z, 一维数组, 待插值点的Y坐标值
  638. // 返回:    float, 结点X轴围成的区域面积(积分)
  639. // 参考: 徐士良. C常用算法程序集(Edition 2). 北京: 清华大学出版社.1996
  640. // 时间: 2003-08-13.
  641. // 三次样条函数插值(第二种边界条件)
  642. float CQGISAlgorithmLib::Spline2D(float * x, float * y, float * t, float * z, int n, int m)
  643. {
  644. int i,j;
  645. float h0,h1,alpha,beta,g,*s, *dy, *ddy, *dz, *ddz;
  646. if(n==2)/// 如果结点为两个, 则直接线性插值
  647. {
  648. Interpolation_curve(x, y, t, z, n, m);
  649. return 0.0f;
  650. }
  651. // 变量的意义:
  652. // g  : 函数在 [X0, Xn-1] 上的积分(围成的面积)
  653. // dy : 函数在结点处的一阶导数值
  654. // ddy: 函数在结点处的二阶导数值
  655. // dz : 函数在待插值点处的一阶导数值
  656. // ddz: 函数在待插值点处的二阶导数值
  657. // 在徐中是作为输出的, 由于实际应用时, 没有必要知道导数值, 因此内含不输出
  658. s = (float*)malloc(n*sizeof(float));
  659. dy = (float*)malloc(n*sizeof(float));
  660. ddy = (float*)malloc(n*sizeof(float));
  661. // 原则上, 第二种边界条件中ddy[0]与ddy[n-1]是用户给定的, 本程序为了方便计算, 
  662. // 设为0, 表示是光滑的, 这可以满足一般的曲线的样条光滑问题的条件
  663. ddy[0] = 0.0f;
  664. ddy[n-1] = 0.0f;
  665. dz = (float*)malloc(m*sizeof(float));
  666. ddz = (float*)malloc(m*sizeof(float));
  667. dy[0]=-0.5;
  668. h0=x[1]-x[0];
  669. s[0]=3.0f*(y[1]-y[0])/(2.0f*h0)-ddy[0]*h0/4.0f;
  670. for (j=1;j<=n-2;j++)
  671. h1=x[j+1]-x[j];
  672. alpha=h0/(h0+h1);
  673. beta=(1.0f-alpha)*(y[j]-y[j-1])/h0;
  674. beta=3.0f*(beta+alpha*(y[j+1]-y[j])/h1);
  675. dy[j]=-alpha/(2.0f+(1.0f-alpha)*dy[j-1]);
  676. s[j]=(beta-(1.0f-alpha)*s[j-1]);
  677. s[j]=s[j]/(2.0f+(1.0f-alpha)*dy[j-1]);
  678. h0=h1;
  679. }
  680. 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]);
  681. for (j=n-2;j>=0;j--)
  682. dy[j]=dy[j]*dy[j+1]+s[j];
  683. for (j=0;j<=n-2;j++) 
  684. s[j]=x[j+1]-x[j];
  685. for (j=0;j<=n-2;j++)
  686. {
  687. h1=s[j]*s[j];
  688. ddy[j]=6.0f*(y[j+1]-y[j])/h1-2.0f*(2.0f*dy[j]+dy[j+1])/s[j];
  689. }
  690. h1=s[n-2]*s[n-2];
  691. 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];
  692. g=0.0;
  693. for (i=0;i<=n-2;i++)
  694. h1=0.5f*s[i]*(y[i]+y[i+1]);
  695. h1=h1-s[i]*s[i]*s[i]*(ddy[i]+ddy[i+1])/24.0f;
  696. g=g+h1;
  697. }
  698. for (j=0;j<=m-1;j++)
  699. if (t[j]>=x[n-1]) i=n-2;
  700. else
  701. {
  702. i=0;
  703. while (t[j]>x[i+1]) i=i+1;
  704. }
  705. h1=(x[i+1]-t[j])/s[i];
  706. h0=h1*h1;
  707. z[j]=(3.0f*h0-2.0f*h0*h1)*y[i];
  708. z[j]=z[j]+s[i]*(h0-h0*h1)*dy[i];
  709. dz[j]=6.0f*(h0-h1)*y[i]/s[i];
  710. dz[j]=dz[j]+(3.0f*h0-2.0f*h1)*dy[i];
  711. ddz[j]=(6.0f-12.0f*h1)*y[i]/(s[i]*s[i]);
  712. ddz[j]=ddz[j]+(2.0f-6.0f*h1)*dy[i]/s[i];
  713. h1=(t[j]-x[i])/s[i];
  714. h0=h1*h1;
  715. z[j]=z[j]+(3.0f*h0-2.0f*h0*h1)*y[i+1];
  716. z[j]=z[j]-s[i]*(h0-h0*h1)*dy[i+1];
  717. dz[j]=dz[j]-6.0f*(h0-h1)*y[i+1]/s[i];
  718. dz[j]=dz[j]+(3.0f*h0-2.0f*h1)*dy[i+1];
  719. ddz[j]=ddz[j]+(6.0f-12.0f*h1)*y[i+1]/(s[i]*s[i]);
  720. ddz[j]=ddz[j]-(2.0f-6.0f*h1)*dy[i+1]/s[i];
  721. }
  722. free(s);
  723. free(dy);
  724. free(ddy);
  725. free(dz);
  726. free(ddz);
  727. return(g);
  728. }
  729. ////////////////////////////////////////////////////////////////////////
  730. // 参数:
  731. // n, 结点的总数
  732. // m, 每段的分段数
  733. // x[], 一维数组, 结点的X坐标值
  734. // y[], 一维数组, 结点的Y坐标值
  735. // tx[],一维数组, 待插值点(包括结点)的X坐标值
  736. // ty[],一维数组, 待插值点(包括结点)的Y坐标值
  737. // 出口:
  738. // tx, ty
  739. // 返回:
  740. // 无
  741. // 思路:
  742. // 以每个结点在折线上的距离D为因变量, X, Y分别作为D的函数进行二维的样条
  743. // 插值(第二种边界条件)
  744. // Notes:
  745. // 比如 n 个结点, 则有(n-1)段, 对每段平均分成 m 段, 则待插值点总数为 m(n-1)+1
  746. // Modification history:
  747. // 二维曲线的样条光滑
  748. void CQGISAlgorithmLib::SplineClean2D(double * x, double * y, double * tx, double * ty, int n, int m)
  749. {
  750. int nTotal, i, j, k;
  751. double *dis, *disT, deltaDis = 0.0f;
  752. nTotal= m*(n-1)+1;
  753. dis = (double*)malloc(n*sizeof(double));
  754. disT = (double*)malloc(nTotal*sizeof(double));
  755. dis[0] = disT[0] = 0.0f;
  756. for(i=1, k=1; i<n; i++)
  757. {
  758. deltaDis = (double)sqrt(( x[i]-x[i-1])*(x[i]-x[i-1]) + 
  759. (y[i]-y[i-1])*(y[i]-y[i-1]));
  760. dis[i] = dis[i-1] + deltaDis;
  761. deltaDis = (double)(deltaDis/m);
  762. for(j=1; j<=m; j++, k++)
  763. {
  764. disT[k] = disT[k-1] + deltaDis;
  765. }
  766. }
  767. Spline2D(dis, x, disT, tx, n, nTotal);
  768. Spline2D(dis, y, disT, ty, n, nTotal);
  769. for(i=0, j=0; i<n; i++, j+=m)
  770. {
  771. tx[j] = x[i];
  772. ty[j] = y[i];
  773. }
  774. free(dis);
  775. free(disT);
  776. }
  777. ////////////////////////////////////////////////////////////////////////
  778. // 参数:
  779. // n, 结点的总数
  780. // m, 每段的分段数
  781. // x, 一维数组, 结点的X坐标值
  782. // y, 一维数组, 结点的Y坐标值
  783. // tx,一维数组, 待插值点(包括结点)的X坐标值
  784. // ty,一维数组, 待插值点(包括结点)的Y坐标值
  785. // 出口:
  786. // tx, ty
  787. // 返回:
  788. // 无
  789. // 思路:
  790. // 以每个结点在折线上的距离D为因变量, X, Y分别作为D的函数进行二维的样条
  791. // 插值(第二种边界条件)
  792. // Notes:
  793. // 比如 n 个结点, 则有(n-1)段, 对每段平均分成 m 段, 则待插值点总数为 m(n-1)+1
  794. // Modification history:
  795. // 二维曲线的样条光滑
  796. void CQGISAlgorithmLib::SplineClean2D(float * x, float * y, float * tx, float * ty, int n, int m)
  797. {
  798. int nTotal, i, j, k;
  799. float *dis, *disT, deltaDis = 0.0f;
  800. nTotal= m*(n-1)+1;
  801. dis = (float*)malloc(n*sizeof(float));
  802. disT = (float*)malloc(nTotal*sizeof(float));
  803. dis[0] = disT[0] = 0.0f;
  804. for(i=1, k=1; i<n; i++)
  805. {
  806. deltaDis = (float)sqrt(( x[i]-x[i-1])*(x[i]-x[i-1]) + 
  807. (y[i]-y[i-1])*(y[i]-y[i-1]));
  808. dis[i] = dis[i-1] + deltaDis;
  809. deltaDis = (float)(deltaDis/m);
  810. for(j=1; j<=m; j++, k++)
  811. {
  812. disT[k] = disT[k-1] + deltaDis;
  813. }
  814. }
  815. Spline2D(dis, x, disT, tx, n, nTotal);
  816. Spline2D(dis, y, disT, ty, n, nTotal);
  817. for(i=0, j=0; i<n; i++, j+=m)
  818. {
  819. tx[j] = x[i];
  820. ty[j] = y[i];
  821. }
  822. free(dis);
  823. free(disT);
  824. }
  825. BOOL CQGISAlgorithmLib::PtListBeThin(CQPointArray & ptArray, double beThinElem)
  826. {
  827. int nCount = ptArray.GetSize();
  828. if(nCount<=2) return FALSE;
  829. int i=1;
  830. while(i<nCount)
  831. {
  832. double x1=0.0f,x2=0.0f,y1=0.0f,y2=0.0f;
  833. x1 = ptArray.GetPoint(i-1)->GetX();
  834. y1 = ptArray.GetPoint(i-1)->GetY();
  835. x2 = ptArray.GetPoint(i)->GetX();
  836. y2 = ptArray.GetPoint(i)->GetY();
  837. double dis = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
  838. if(dis<=beThinElem) //beThinElem抽稀因子
  839. {
  840. delete ptArray.RemoveAt(i);
  841. i--;
  842. }
  843. nCount = ptArray.GetSize();
  844. if(nCount<=2) break;
  845. i++;
  846. }
  847. return TRUE;
  848. }
  849. //道格拉斯-普克法算法描述 
  850. //首先,将一条曲线首、末点连一条直线,求出其余各点到该直线的距离
  851. //选其最大者与规定的临界值相比较,若大于临界值,则离该直线距离最
  852. //大的点保留,否则将直线两端间各点全部舍去
  853. void CQGISAlgorithmLib::PtListLess(CQPointArray & ptArray,double beThin /* = 0.0001f */)
  854. {
  855. UINT ptCount = ptArray.GetSize();
  856. if(ptCount <= 2)
  857. return; // 假如传入的是一个空数组 就退出
  858. CQPointArray ptNewArray; //目标点数组
  859. //首、末两个点是肯定要的
  860. CQPoint ptFirst = *ptArray.GetPoint(0);
  861. CQPoint ptLast = *ptArray.GetPoint(ptCount-1);
  862. ptNewArray.AddPoint(ptFirst.GetX(),ptFirst.GetY());
  863. //通过计算将符合要求的点都添加到目标点数组中并最终返回
  864. UINT i = 1;
  865. while(i<ptCount-1)
  866. {
  867. CQPoint * pPt = ptArray.GetPoint(i++);
  868. if(pPt != NULL)
  869. {
  870. double fDis = pPt->Distance(ptFirst,ptLast);
  871. if(fDis-beThin>=0.000001f)
  872. {
  873. ptNewArray.AddPoint(pPt->GetX(),pPt->GetY());
  874. }
  875. }
  876. }
  877. ptNewArray.AddPoint(ptLast.GetX(),ptLast.GetY());
  878. ptArray.DeleteAll();
  879. ptArray.Copy(ptNewArray);
  880. }
  881. double CQGISAlgorithmLib::ConvertFontPttoMM(double pt)
  882. {
  883. return pt*0.35146;
  884. }