Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

464 lines
11 KiB

  1. //
  2. // Copyright (c) 1997-1999 Microsoft Corporation.
  3. //
  4. #include "stdafx.h"
  5. #include "vdata.h"
  6. #include "extfunc.h"
  7. #define sign(n) (n < 0 ? 1 : 0)
  8. #define fpow(f) ((double)f*f)
  9. #define lpow(f) ((long)f*f)
  10. #define SPLINE_ATR 0x0001
  11. #define SMOOTHANCHOR 0x80
  12. #define SABUNMIN (1*16)
  13. int FitConic(int inLst,int outLst,int level,int ufp);
  14. static int SetConic(struct VDATA *svp,int nElm,int outLst,int level);
  15. static int CurvTerm(struct VDATA *svp,int nElm,struct VDATA * *term,int level);
  16. static void sabun2(struct VDATA *vp,struct vecdata *vd);
  17. static int Fitting(struct VDATA *sp,struct VDATA *ep,int nElm,int outLst);
  18. static void onecurve(struct VDATA *sp,struct VDATA *midp,struct VDATA *ep,struct vecdata *cp);
  19. static int twocurve(struct VDATA *sp,struct VDATA *ep,int nElm,struct vecdata *cp,struct vecdata *mid,struct vecdata *cp2);
  20. static long getdist(struct vecdata *lp1,struct vecdata *lp2,struct vecdata *p);
  21. static int CrsPnt(struct vecdata *p1,struct vecdata *p2,struct vecdata *p3,struct vecdata *p4,struct vecdata *crsp);
  22. static long plen(struct vecdata *p1,struct vecdata *p2);
  23. static int isbind(struct vecdata *v1,struct vecdata *v2,struct vecdata *v3);
  24. static long GetCurveHeight(struct VDATA *sp,struct VDATA *ep,int nelm,struct VDATA * *rvp,int *pos);
  25. static int underFP;
  26. /***********************************************************************
  27. * Fit Conic Spline to Short Vector
  28. */
  29. /* */ int
  30. /* */ FitConic(
  31. /* */ int inLst,
  32. /* */ int outLst,
  33. /* */ int level, /* Smoothing Level 0-SMOOTHLEVELMAX-1 */
  34. /* */ int ufp)
  35. /*
  36. * returns : 0, -1
  37. ***********************************************************************/
  38. {
  39. struct VHEAD *vhd;
  40. int sts;
  41. struct VDATA *svp, *evp;
  42. int sp, ep;
  43. int ncont;
  44. underFP = ufp;
  45. if ( (sts = VDGetHead( inLst, &vhd))!=0)
  46. goto RET;
  47. VDNew( outLst);
  48. ncont=0;
  49. while ( vhd->next != NIL) {
  50. svp = vhd->headp;
  51. if ((sp=searchanchor(0,svp,&svp,vhd->nPoints))<vhd->nPoints){
  52. while(sp<vhd->nPoints) {
  53. ep = searchanchor(sp+1, svp->next,&evp, vhd->nPoints);
  54. if ((sts = SetConic( svp, ep-sp, outLst, level))<0)
  55. goto RET;
  56. if ( ep >= vhd->nPoints)
  57. break;
  58. sp = ep;
  59. svp = evp;
  60. }
  61. }
  62. ncont++;
  63. if ((sts = VDClose( outLst))<0)
  64. goto RET;
  65. vhd = vhd->next;
  66. }
  67. RET:
  68. return( sts);
  69. }
  70. /***********************************************************************
  71. * Set Conic Curves to specified category
  72. */
  73. /* */ static int
  74. /* */ SetConic ( struct VDATA *svp, int nElm, int outLst, int level)
  75. /*
  76. * returns : 0, -1
  77. ***********************************************************************/
  78. {
  79. struct VDATA *vp;
  80. int nPart;
  81. int sts;
  82. sts = 0;
  83. while ( nElm > 0) {
  84. /* Divide non contigus */
  85. nPart = CurvTerm( svp, nElm, &vp , level);
  86. sts = Fitting( svp, vp, nPart, outLst);
  87. svp = vp;
  88. nElm -= nPart;
  89. }
  90. return sts;
  91. }
  92. /***********************************************************************
  93. * Determine the part which is described with one Conic
  94. */
  95. /* */ static int
  96. /* */ CurvTerm(
  97. /* */ struct VDATA *svp,
  98. /* */ int nElm,
  99. /* */ struct VDATA **term,
  100. /* */ int level)
  101. /*
  102. * returns: none
  103. ***********************************************************************/
  104. {
  105. struct vecdata sub1, sub2;
  106. int ecnt;
  107. if ( nElm < 3) {
  108. for ( ecnt=0; ecnt < nElm; ecnt++)
  109. svp = svp->next;
  110. *term = svp;
  111. return( nElm);
  112. }
  113. sabun2( svp, &sub1);
  114. for ( ecnt = 2; ecnt < nElm; ecnt++) {
  115. svp = svp->next;
  116. sabun2( svp, &sub2);
  117. if ((sign(sub1.x)!=sign(sub2.x)
  118. && abs(sub1.x)+abs(sub2.x)> SABUNMIN*(level+1))
  119. || (sign(sub1.y)!=sign(sub2.y)
  120. &&abs(sub1.y)+abs(sub2.y)> SABUNMIN*(level+1))) {
  121. *term = svp->next;
  122. return ecnt;
  123. }
  124. sub1 = sub2;
  125. }
  126. *term = svp->next->next;
  127. return nElm;
  128. }
  129. /***********************************************************************
  130. * 2nd Sabun
  131. */
  132. /* */ static void
  133. /* */ sabun2( struct VDATA *vp, struct vecdata *vd)
  134. /*
  135. * returns : none
  136. ***********************************************************************/
  137. {
  138. vd->x = vp->vd.x - vp->next->vd.x*2 + vp->next->next->vd.x;
  139. vd->y = vp->vd.y - vp->next->vd.y*2 + vp->next->next->vd.y;
  140. return;
  141. }
  142. /***********************************************************************
  143. * Curve fit and set data
  144. */
  145. /* */ static int
  146. /* */ Fitting(
  147. /* */ struct VDATA *sp, /* Conic Start Point */
  148. /* */ struct VDATA *ep, /* Conic End Point */
  149. /* */ int nElm,
  150. /* */ int outLst)
  151. /*
  152. * returns : 0, -1
  153. ***********************************************************************/
  154. {
  155. struct vecdata vd;
  156. struct vecdata cp, mid, cp2;
  157. int sts;
  158. if ( nElm==0)
  159. return 0;
  160. else if ( nElm == 1) {
  161. vd = sp->vd;
  162. if ((sts = VDSetData( outLst, &vd))<0)
  163. goto RET;
  164. }
  165. else if ( nElm == 2) {
  166. onecurve( sp , sp->next, ep, &cp );
  167. vd = sp->vd;
  168. if ((sts = VDSetData( outLst, &vd))<0)
  169. goto RET;
  170. cp.atr = SPLINE_ATR;
  171. if ((sts = VDSetData( outLst, &cp))<0)
  172. goto RET;
  173. }
  174. else {
  175. if ( twocurve( sp, ep, nElm, &cp, &mid, &cp2)) {
  176. vd = sp->vd;
  177. if ((sts = VDSetData( outLst, &vd))<0)
  178. goto RET;
  179. cp.atr = SPLINE_ATR;
  180. if ((sts = VDSetData( outLst, &cp))<0)
  181. goto RET;
  182. mid.atr = 0;
  183. if ((sts = VDSetData( outLst, &mid))<0)
  184. goto RET;
  185. cp2.atr = SPLINE_ATR;
  186. if ((sts = VDSetData( outLst, &cp2))<0)
  187. goto RET;
  188. }
  189. else {
  190. vd = sp->vd;
  191. if ((sts = VDSetData( outLst, &vd))<0)
  192. goto RET;
  193. cp.atr = SPLINE_ATR;
  194. if ((sts = VDSetData( outLst, &cp))<0)
  195. goto RET;
  196. }
  197. }
  198. RET:
  199. return sts;
  200. }
  201. /***********************************************************************
  202. * Fit One Curve
  203. */
  204. /* */ static void
  205. /* */ onecurve(
  206. /* */ struct VDATA *sp,
  207. /* */ struct VDATA *midp,
  208. /* */ struct VDATA *ep,
  209. /* */ struct vecdata *cp)
  210. /*
  211. * returns : none
  212. ***********************************************************************/
  213. {
  214. struct vecdata p;
  215. p.x = (midp->vd.x*4 - sp->vd.x - ep->vd.x)/2;
  216. p.y = (midp->vd.y*4 - sp->vd.y - ep->vd.y)/2;
  217. if ( sp->vd.x < ep->vd.x) {
  218. if ( p.x > ep->vd.x) p.x = ep->vd.x;
  219. if ( p.x < sp->vd.x) p.x = sp->vd.x;
  220. }
  221. else {
  222. if ( p.x < ep->vd.x) p.x = ep->vd.x;
  223. if ( p.x > sp->vd.x) p.x = sp->vd.x;
  224. }
  225. if ( sp->vd.y < ep->vd.y) {
  226. if ( p.y > ep->vd.y) p.y = ep->vd.y;
  227. if ( p.y < sp->vd.y) p.y = sp->vd.y;
  228. }
  229. else {
  230. if ( p.y < ep->vd.y) p.y = ep->vd.y;
  231. if ( p.y > sp->vd.y) p.y = sp->vd.y;
  232. }
  233. *cp = p;
  234. }
  235. /**********************************************************************
  236. * Fit with a pair of Conic
  237. */
  238. /* */ static int
  239. /* */ twocurve(
  240. /* */ struct VDATA *sp,
  241. /* */ struct VDATA *ep,
  242. /* */ int nElm,
  243. /* */ struct vecdata *cp,
  244. /* */ struct vecdata *mid,
  245. /* */ struct vecdata *cp2)
  246. /*
  247. * returns : 0, 1( pair)
  248. **********************************************************************/
  249. {
  250. struct VDATA *midvp, *maxvp;
  251. long maxlen;
  252. int twin;
  253. long sclen, eclen;
  254. int pos;
  255. int cp1pos, cp2pos;
  256. /* Get Curve Peak */
  257. maxlen = GetCurveHeight( sp, ep, nElm, &maxvp, &pos);
  258. /*
  259. if ( plen( &sp->vd, &ep->vd)/25 > maxlen) {
  260. onecurve( sp , maxvp, ep, cp );
  261. twin = 0;
  262. }
  263. else {
  264. */
  265. onecurve( sp , maxvp, ep, cp );
  266. sclen = plen( &sp->vd, cp);
  267. eclen = plen( &ep->vd, cp);
  268. midvp = maxvp;
  269. if ( sclen > eclen*4
  270. || sclen*4 < eclen
  271. || (long)(maxvp->vd.x - sp->vd.x)*(cp->x-sp->vd.x)<0L
  272. || (long)(maxvp->vd.y - sp->vd.y)*(cp->y-sp->vd.y)<0L
  273. || ( plen( &sp->vd, &ep->vd)>25L*25*underFP
  274. && plen( &sp->vd, &ep->vd)<maxlen*64)) {
  275. maxlen=GetCurveHeight(sp, midvp, pos, &maxvp, &cp1pos);
  276. onecurve( sp, maxvp, midvp, cp );
  277. maxlen=GetCurveHeight(midvp,ep,nElm-pos,&maxvp,&cp2pos);
  278. onecurve( midvp , maxvp, ep, cp2 );
  279. *mid = midvp->vd;
  280. twin = 1;
  281. }
  282. else {
  283. twin = 0;
  284. }
  285. /*
  286. }
  287. */
  288. return( twin);
  289. }
  290. /**********************************************************************
  291. * distance of point from line
  292. */
  293. /* */ static long
  294. /* */ getdist(
  295. /* */ struct vecdata *lp1,
  296. /* */ struct vecdata *lp2, /* Line p1, p2 */
  297. /* */ struct vecdata *p) /* Point */
  298. /*
  299. * return : Disttance 2nd Value
  300. **********************************************************************/
  301. {
  302. long a, b, c;
  303. long height;
  304. a = - ( lp2->y - lp1->y);
  305. b = lp2->x - lp1->x;
  306. c = (long)(-lp1->y) * lp2->x + (long)(lp1->x) * lp2->y;
  307. if ( a==0 && b==0)
  308. height = c;
  309. else {
  310. height = a*p->x + b*p->y+c;
  311. if ( labs(height)>46340L)
  312. height = (long)(fpow(height)/(fpow(a)+fpow(b)));
  313. else
  314. height = lpow(height)/(lpow(a)+lpow(b));
  315. }
  316. return( height);
  317. }
  318. /**********************************************************************
  319. * Cross Point
  320. */
  321. /* */ static int
  322. /* */ CrsPnt(
  323. /* */ struct vecdata *p1, /* vector point p1 to p2 */
  324. /* */ struct vecdata *p2,
  325. /* */ struct vecdata *p3, /* vector point p3 to p4 */
  326. /* */ struct vecdata *p4,
  327. /* */ struct vecdata *crsp)
  328. /*
  329. * returns : 0, -1(no cross)
  330. **********************************************************************/
  331. {
  332. int rel1x, rel1y, rel2x, rel2y;
  333. long cmul, cmul2;
  334. int sts;
  335. rel1x = p2->x - p1->x;
  336. rel1y = p2->y - p1->y;
  337. rel2x = p4->x - p3->x;
  338. rel2y = p4->y - p3->y;
  339. cmul = (long)rel1y*rel2x - (long)rel2y*rel1x;
  340. if (cmul == 0L)
  341. sts = -1;
  342. else {
  343. cmul2 = (long)rel2x * (p3->y - p1->y) -
  344. (long)rel2y * (p3->x - p1->x);
  345. crsp->x = (int)(cmul2*rel1x/cmul) + p1->x;
  346. crsp->y = (int)(cmul2*rel1y/cmul) + p1->y;
  347. if ( (long)rel1x*(crsp->x-p1->x)<0
  348. || (long)rel1y*(crsp->y-p1->y)<0
  349. || (long)rel2x*(crsp->x-p4->x)<0
  350. || (long)rel2y*(crsp->y-p4->y)<0)
  351. sts = -1;
  352. else sts = 0;
  353. }
  354. return sts;
  355. }
  356. /**********************************************************************
  357. * distance of points
  358. */
  359. /* */ static long
  360. /* */ plen(
  361. /* */ struct vecdata *p1,
  362. /* */ struct vecdata *p2)
  363. /*
  364. * return : Disttance 2nd Value
  365. **********************************************************************/
  366. {
  367. return( lpow((long)(p2->x-p1->x)) + lpow((long)(p2->y - p1->y)));
  368. }
  369. /**********************************************************************
  370. * bind two conic to one
  371. */
  372. /* */ static int
  373. /* */ isbind(
  374. /* */ struct vecdata *v1,
  375. /* */ struct vecdata *v2,
  376. /* */ struct vecdata *v3)
  377. /*
  378. * returns : 0, 1
  379. **********************************************************************/
  380. {
  381. int l12, l23;
  382. l12 = v1->x - v2->x;
  383. l23 = v2->x - v3->x;
  384. if ( sign( l12)!=sign(l23))
  385. goto NORET;
  386. l12 = abs( l12);
  387. l23 = abs( l23);
  388. if ( (l12-l23)!=0) {
  389. if ( l12 / abs(l12 - l23) <10)
  390. goto NORET;
  391. }
  392. l12 = v1->y - v2->y;
  393. l23 = v2->y - v3->y;
  394. if ( sign( l12)!=sign(l23))
  395. goto NORET;
  396. l12 = abs( l12);
  397. l23 = abs( l23);
  398. if ( (l12-l23)!=0) {
  399. if ( l12 / abs(l12 - l23) <10)
  400. goto NORET;
  401. }
  402. return 1;
  403. NORET:
  404. return 0;
  405. }
  406. /**********************************************************************
  407. * Get Curve liaison Peak height
  408. */
  409. /* */ static long
  410. /* */ GetCurveHeight(
  411. /* */ struct VDATA *sp,
  412. /* */ struct VDATA *ep,
  413. /* */ int nelm,
  414. /* */ struct VDATA * * rvp,
  415. /* */ int *pos)
  416. /*
  417. * returns : maxlength( 2nd value)
  418. **********************************************************************/
  419. {
  420. int ecnt;
  421. struct VDATA *vp, *maxvp;
  422. long maxlen, len;
  423. int maxpos;
  424. /* Get Curve Peak */
  425. vp = sp->next;
  426. maxvp = vp;
  427. maxlen = 0;
  428. maxpos = 0;
  429. for ( ecnt = 0; ecnt < nelm-1; ecnt++, vp = vp->next) {
  430. len = getdist( &sp->vd, &ep->vd, &vp->vd);
  431. if ( len > maxlen) {
  432. maxlen = len;
  433. maxvp = vp;
  434. maxpos = ecnt;
  435. }
  436. }
  437. *rvp = maxvp;
  438. *pos = maxpos;
  439. return maxlen;
  440. }
  441. /* EOF */