1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/spline.c,v 1.45 2011/05/16 16:21:59 william Exp $
19 */
20
21 #define _INCLUDE_FROM_SPLINE_C_
22
23 #include "tgifdefs.h"
24
25 #include "dialog.e"
26 #include "file.e"
27 #include "msg.e"
28 #include "poly.e"
29 #include "polygon.e"
30 #include "ps.e"
31 #include "raster.e"
32 #include "rect.e"
33 #include "setup.e"
34 #include "spline.e"
35 #include "strtbl.e"
36
37 #define SUM_MINUS_2 (theSum-((double)2.0))
38 #define HALF ((double)0.5)
39
40 int intSplineTension=3;
41 int splineTol=9;
42 int tighterStructSplines=TRUE;
43
44 #define curveToFactor (((double)2.0)/((double)3.0))
45 #define compCurveToFactor (((double)1.0)/((double)3.0))
46
47 static double theSum=(double)6.0;
48
ReadSplineTightness(buf)49 int ReadSplineTightness(buf)
50 char *buf;
51 {
52 int tighter=TRUE;
53 char *psz=NULL;
54
55 if (importingFile) return TRUE;
56
57 psz = FindChar((int)'(', buf);
58 InitScan(psz, "\t\n, ");
59 if (GETINT("spline_tightness", tighter, "tighter_splines") == INVALID) {
60 return FALSE;
61 }
62 tighterStructSplines = tighter;
63
64 return TRUE;
65 }
66
CalcAutoRetractedArrowAttrBend(Style,X0,Y0,X2,Y2,X1,Y1)67 void CalcAutoRetractedArrowAttrBend(Style, X0, Y0, X2, Y2, X1, Y1)
68 int Style, X0, Y0, X2, Y2, *X1, *Y1;
69 {
70 double dx, dy, len, new_x, new_y;
71
72 dx = (double)(X2 - X0);
73 dy = (double)(Y2 - Y0);
74 len = (double)(sqrt(((double)dx)*((double)dx)+((double)dy)*((double)dy)));
75 if (Style == LS_RIGHT) {
76 new_x = ((double)((X0+X2)>>1)) + dy/((double)8.0);
77 new_y = ((double)((Y0+Y2)>>1)) - dx/((double)8.0);
78 } else {
79 new_x = ((double)((X0+X2)>>1)) - dy/((double)8.0);
80 new_y = ((double)((Y0+Y2)>>1)) + dx/((double)8.0);
81 }
82 *X1 = (int)round(new_x);
83 *Y1 = (int)round(new_y);
84 }
85
86 static
MidPoint(X1,Y1,X2,Y2,pd_mx,pd_my)87 void MidPoint(X1, Y1, X2, Y2, pd_mx, pd_my)
88 double X1, Y1, X2, Y2, *pd_mx, *pd_my;
89 {
90 *pd_mx = HALF*X1+HALF*X2;
91 *pd_my = HALF*Y1+HALF*Y2;
92 }
93
94 static
SetAStructuredSplineTickMark(vs,num_pts,target_vs)95 void SetAStructuredSplineTickMark(vs, num_pts, target_vs)
96 IntPoint *vs, *target_vs;
97 int num_pts;
98 {
99 double x, y, x0, y0, x1, y1, x2, y2, x3, y3;
100 double mx1, my1, mx2, my2, mx3, my3, mx12, my12, mx23, my23;
101
102 switch (num_pts) {
103 case 1:
104 target_vs[0].x = vs[0].x;
105 target_vs[0].y = vs[0].y;
106 break;
107 case 3:
108 x0 = (double)(vs[0].x); y0 = (double)(vs[0].y);
109 x1 = (double)(vs[1].x); y1 = (double)(vs[1].y);
110 x2 = (double)(vs[2].x); y2 = (double)(vs[2].y);
111 MidPoint(x0, y0, x1, y1, &mx1, &my1);
112 MidPoint(x2, y2, x1, y1, &mx2, &my2);
113 MidPoint(mx1, my1, mx2, my2, &x, &y);
114 target_vs[0].x = (int)x;
115 target_vs[0].y = (int)y;
116 break;
117 case 4:
118 x0 = (double)(vs[0].x); y0 = (double)(vs[0].y);
119 x1 = (double)(vs[1].x); y1 = (double)(vs[1].y);
120 x2 = (double)(vs[2].x); y2 = (double)(vs[2].y);
121 x3 = (double)(vs[3].x); y3 = (double)(vs[3].y);
122 MidPoint(x0, y0, x1, y1, &mx1, &my1);
123 MidPoint(x1, y1, x2, y2, &mx2, &my2);
124 MidPoint(x2, y2, x3, y3, &mx3, &my3);
125 MidPoint(mx1, my1, mx2, my2, &mx12, &my12);
126 MidPoint(mx2, my2, mx3, my3, &mx23, &my23);
127 MidPoint(mx12, my12, mx23, my23, &x, &y);
128 target_vs[0].x = (int)x;
129 target_vs[0].y = (int)y;
130 break;
131 }
132 }
133
GetStructuredSplinePolyTickMarkVs(pn_N,obj_ptr,poly_ptr,polygon_ptr)134 IntPoint *GetStructuredSplinePolyTickMarkVs(pn_N, obj_ptr, poly_ptr,
135 polygon_ptr)
136 int *pn_N;
137 struct ObjRec *obj_ptr;
138 struct PolyRec *poly_ptr;
139 struct PolygonRec *polygon_ptr;
140 {
141 int i=0, j=0, n=0, num_hinge_vs=0, num_vs=0, index=0;
142 int last_was_smooth=FALSE;
143 IntPoint *vs=NULL, *vlist=NULL, tmp_vs[4], *xformed_vs=NULL;
144
145 if (poly_ptr != NULL) {
146 n = poly_ptr->n;
147 vlist = poly_ptr->vlist;
148 } else if (polygon_ptr != NULL) {
149 n = polygon_ptr->n;
150 vlist = polygon_ptr->vlist;
151 }
152 if (obj_ptr->ctm != NULL) {
153 xformed_vs = (IntPoint*)malloc((n+1)*sizeof(IntPoint));
154 if (xformed_vs == NULL) FailAllocMessage();
155 memset(xformed_vs, 0, (n+1)*sizeof(IntPoint));
156 for (i=0; i < n; i++) {
157 int tmp_x=0, tmp_y=0;
158
159 TransformPointThroughCTM(vlist[i].x-obj_ptr->x, vlist[i].y-obj_ptr->y,
160 obj_ptr->ctm, &tmp_x, &tmp_y);
161 xformed_vs[i].x = tmp_x + obj_ptr->x;
162 xformed_vs[i].y = tmp_y + obj_ptr->y;
163 }
164 }
165 num_hinge_vs = (n+2)/3;
166 #ifdef _TGIF_DBG /* debug, do not translate */
167 TgAssert((n+2)%3 == 0,
168 "invalid n in GetStructuredSplinePolyTickMarkVs()", NULL);
169 #endif /* _TGIF_DBG */
170 num_vs = num_hinge_vs;
171 for (i=0, j=0; i < num_hinge_vs; i++, j+=3) {
172 if (i == 0) {
173 if (vlist[0].x != vlist[1].x || vlist[0].y != vlist[1].y) {
174 last_was_smooth = TRUE;
175 }
176 } else if (i == num_hinge_vs-1) {
177 if (vlist[n-1].x != vlist[n-2].x || vlist[n-1].y != vlist[n-2].y) {
178 num_vs++;
179 last_was_smooth = TRUE;
180 } else if (last_was_smooth) {
181 num_vs++;
182 last_was_smooth = FALSE;
183 }
184 } else {
185 if (vlist[j-1].x != vlist[j].x || vlist[j-1].y != vlist[j].y) {
186 #ifdef _TGIF_DBG /* debug, do not translate */
187 TgAssert(vlist[j+1].x != vlist[j].x || vlist[j+1].y != vlist[j].y,
188 "half smooth detected in GetStructuredSplinePolyTickMarkVs()",
189 NULL);
190 #endif /* _TGIF_DBG */
191 num_vs++;
192 last_was_smooth = TRUE;
193 } else if (last_was_smooth) {
194 num_vs++;
195 last_was_smooth = FALSE;
196 }
197 }
198 }
199 vs = (IntPoint*)malloc((num_vs+1)*sizeof(IntPoint));
200 if (vs == NULL) FailAllocMessage();
201 memset(vs, 0, (num_vs+1)*sizeof(IntPoint));
202
203 if (xformed_vs != NULL) {
204 vs[0].x = xformed_vs[0].x;
205 vs[0].y = xformed_vs[0].y;
206 } else {
207 vs[0].x = vlist[0].x;
208 vs[0].y = vlist[0].y;
209 }
210 index = 1;
211 last_was_smooth = FALSE;
212 for (i=0, j=0; i < num_hinge_vs; i++, j+=3) {
213 int num_pts_in_seg=0;
214
215 if (i == 0) {
216 if (xformed_vs != NULL) {
217 tmp_vs[0].x = xformed_vs[0].x;
218 tmp_vs[0].y = xformed_vs[0].y;
219 } else {
220 tmp_vs[0].x = vlist[0].x;
221 tmp_vs[0].y = vlist[0].y;
222 }
223 if (vlist[0].x != vlist[1].x || vlist[0].y != vlist[1].y) {
224 last_was_smooth = TRUE;
225 if (xformed_vs != NULL) {
226 tmp_vs[1].x = xformed_vs[1].x;
227 tmp_vs[1].y = xformed_vs[1].y;
228 } else {
229 tmp_vs[1].x = vlist[1].x;
230 tmp_vs[1].y = vlist[1].y;
231 }
232 }
233 } else if (i == num_hinge_vs-1) {
234 if (vlist[n-1].x != vlist[n-2].x || vlist[n-1].y != vlist[n-2].y) {
235 if (last_was_smooth) {
236 num_pts_in_seg = 4;
237 } else {
238 num_pts_in_seg = 3;
239 }
240 if (xformed_vs != NULL) {
241 tmp_vs[num_pts_in_seg-2].x = xformed_vs[j-1].x;
242 tmp_vs[num_pts_in_seg-2].y = xformed_vs[j-1].y;
243 tmp_vs[num_pts_in_seg-1].x = xformed_vs[j].x;
244 tmp_vs[num_pts_in_seg-1].y = xformed_vs[j].y;
245 } else {
246 tmp_vs[num_pts_in_seg-2].x = vlist[j-1].x;
247 tmp_vs[num_pts_in_seg-2].y = vlist[j-1].y;
248 tmp_vs[num_pts_in_seg-1].x = vlist[j].x;
249 tmp_vs[num_pts_in_seg-1].y = vlist[j].y;
250 }
251 SetAStructuredSplineTickMark(tmp_vs, num_pts_in_seg, &vs[index++]);
252 } else if (last_was_smooth) {
253 if (xformed_vs != NULL) {
254 tmp_vs[2].x = xformed_vs[j].x;
255 tmp_vs[2].y = xformed_vs[j].y;
256 } else {
257 tmp_vs[2].x = vlist[j].x;
258 tmp_vs[2].y = vlist[j].y;
259 }
260 SetAStructuredSplineTickMark(tmp_vs, 3, &vs[index++]);
261 }
262 if (poly_ptr != NULL) {
263 if (xformed_vs != NULL) {
264 SetAStructuredSplineTickMark(&xformed_vs[j], 1, &vs[index++]);
265 } else {
266 SetAStructuredSplineTickMark(&vlist[j], 1, &vs[index++]);
267 }
268 }
269 /* all done */
270 } else {
271 if (vlist[j-1].x != vlist[j].x || vlist[j-1].y != vlist[j].y) {
272 if (last_was_smooth) {
273 num_pts_in_seg = 4;
274 } else {
275 num_pts_in_seg = 3;
276 }
277 if (xformed_vs != NULL) {
278 tmp_vs[num_pts_in_seg-2].x = xformed_vs[j-1].x;
279 tmp_vs[num_pts_in_seg-2].y = xformed_vs[j-1].y;
280 tmp_vs[num_pts_in_seg-1].x = xformed_vs[j].x;
281 tmp_vs[num_pts_in_seg-1].y = xformed_vs[j].y;
282 } else {
283 tmp_vs[num_pts_in_seg-2].x = vlist[j-1].x;
284 tmp_vs[num_pts_in_seg-2].y = vlist[j-1].y;
285 tmp_vs[num_pts_in_seg-1].x = vlist[j].x;
286 tmp_vs[num_pts_in_seg-1].y = vlist[j].y;
287 }
288 SetAStructuredSplineTickMark(tmp_vs, num_pts_in_seg, &vs[index++]);
289
290 last_was_smooth = TRUE;
291 if (xformed_vs != NULL) {
292 tmp_vs[1].x = xformed_vs[j+1].x;
293 tmp_vs[1].y = xformed_vs[j+1].y;
294 } else {
295 tmp_vs[1].x = vlist[j+1].x;
296 tmp_vs[1].y = vlist[j+1].y;
297 }
298 } else if (last_was_smooth) {
299 if (xformed_vs != NULL) {
300 tmp_vs[2].x = xformed_vs[j].x;
301 tmp_vs[2].y = xformed_vs[j].y;
302 } else {
303 tmp_vs[2].x = vlist[j].x;
304 tmp_vs[2].y = vlist[j].y;
305 }
306 SetAStructuredSplineTickMark(tmp_vs, 3, &vs[index++]);
307
308 last_was_smooth = FALSE;
309 }
310 if (xformed_vs != NULL) {
311 tmp_vs[0].x = xformed_vs[j].x;
312 tmp_vs[0].y = xformed_vs[j].y;
313 SetAStructuredSplineTickMark(&xformed_vs[j], 1, &vs[index++]);
314 } else {
315 tmp_vs[0].x = vlist[j].x;
316 tmp_vs[0].y = vlist[j].y;
317 SetAStructuredSplineTickMark(&vlist[j], 1, &vs[index++]);
318 }
319 }
320 }
321 if (xformed_vs != NULL) free(xformed_vs);
322 *pn_N = num_vs;
323
324 return vs;
325 }
326
MakeStructuredSplinePolyVertex(pn_N,ppszSmooth,NumVs,Vs)327 IntPoint *MakeStructuredSplinePolyVertex(pn_N, ppszSmooth, NumVs, Vs)
328 int *pn_N, NumVs; /* NumVs is poly_ptr->n */
329 char **ppszSmooth;
330 IntPoint *Vs; /* Vs is poly_ptr->vlist */
331 {
332 int i=0, j=0, k=0, num_hinge_vs=(NumVs+2)/3, num_vs=0;
333 IntPoint *vs=NULL;
334 char *ssmooth=NULL;
335
336 #ifdef _TGIF_DBG /* debug, do not translate */
337 TgAssert((NumVs+2)%3 == 0,
338 "invalid NumVs in MakeStructuredSplineVertex()", NULL);
339 #endif /* _TGIF_DBG */
340 num_vs = num_hinge_vs;
341 for (i=0, j=0; i < num_hinge_vs; i++, j+=3) {
342 if (i == 0) {
343 if (Vs[0].x != Vs[1].x || Vs[0].y != Vs[1].y) {
344 num_vs++;
345 }
346 } else if (i == num_hinge_vs-1) {
347 if (Vs[NumVs-1].x != Vs[NumVs-2].x || Vs[NumVs-1].y != Vs[NumVs-2].y) {
348 num_vs++;
349 }
350 } else {
351 if (Vs[j-1].x != Vs[j].x || Vs[j-1].y != Vs[j].y) {
352 num_vs++;
353 }
354 if (Vs[j+1].x != Vs[j].x || Vs[j+1].y != Vs[j].y) {
355 num_vs++;
356 }
357 }
358 }
359 vs = (IntPoint*)malloc((num_vs+2)*sizeof(IntPoint));
360 if (vs == NULL) FailAllocMessage();
361 ssmooth = (char*)malloc((num_vs+2)*sizeof(char));
362 if (ssmooth == NULL) FailAllocMessage();
363 memset(ssmooth, 0, (num_vs+2)*sizeof(char));
364
365 for (i=0, j=0, k=0; i < num_hinge_vs; i++, j+=3, k++) {
366 if (i == 0) {
367 vs[k].x = Vs[0].x;
368 vs[k].y = Vs[0].y;
369 ssmooth[k] = FALSE;
370 if (Vs[0].x != Vs[1].x || Vs[0].y != Vs[1].y) {
371 k++;
372 vs[k].x = Vs[1].x;
373 vs[k].y = Vs[1].y;
374 ssmooth[k] = TRUE;
375 }
376 } else if (i == num_hinge_vs-1) {
377 if (Vs[NumVs-1].x != Vs[NumVs-2].x || Vs[NumVs-1].y != Vs[NumVs-2].y) {
378 vs[k].x = Vs[NumVs-2].x;
379 vs[k].y = Vs[NumVs-2].y;
380 ssmooth[k] = TRUE;
381 k++;
382 }
383 vs[k].x = Vs[NumVs-1].x;
384 vs[k].y = Vs[NumVs-1].y;
385 ssmooth[k] = FALSE;
386 } else {
387 if (Vs[j-1].x != Vs[j].x || Vs[j-1].y != Vs[j].y) {
388 vs[k].x = Vs[j-1].x;
389 vs[k].y = Vs[j-1].y;
390 ssmooth[k] = TRUE;
391 k++;
392 }
393 vs[k].x = Vs[j].x;
394 vs[k].y = Vs[j].y;
395 ssmooth[k] = FALSE;
396 if (Vs[j+1].x != Vs[j].x || Vs[j+1].y != Vs[j].y) {
397 k++;
398 vs[k].x = Vs[j+1].x;
399 vs[k].y = Vs[j+1].y;
400 ssmooth[k] = TRUE;
401 }
402 }
403 }
404 #ifdef _TGIF_DBG /* debug, do not translate */
405 TgAssert(k == num_vs,
406 "k != num_vs in MakeStructuredSplineVertex()", NULL);
407 #endif /* _TGIF_DBG */
408 *pn_N = num_vs;
409 *ppszSmooth = ssmooth;
410
411 return vs;
412 }
413
MakeStructuredSplinePolygonVertex(pn_N,ppszSmooth,NumVs,Vs)414 IntPoint *MakeStructuredSplinePolygonVertex(pn_N, ppszSmooth, NumVs, Vs)
415 int *pn_N, NumVs;
416 char **ppszSmooth;
417 IntPoint *Vs;
418 {
419 int i=0, j=0, k=0, num_hinge_vs=(NumVs+2)/3, num_vs=0;
420 IntPoint *vs=NULL;
421 char *ssmooth=NULL;
422
423 #ifdef _TGIF_DBG /* debug, do not translate */
424 TgAssert((NumVs+2)%3 == 0,
425 "invalid NumVs in MakeStructuredSplinePolygonVertex()", NULL);
426 TgAssert(Vs[0].x == Vs[NumVs-1].x && Vs[0].y == Vs[NumVs-1].y,
427 "first and last points not identical in MakeStructuredSplinePolygonVertex()",
428 NULL);
429 #endif /* _TGIF_DBG */
430 num_vs = num_hinge_vs;
431 for (i=0, j=0; i < num_hinge_vs; i++, j+=3) {
432 if (i == 0) {
433 if (Vs[0].x != Vs[1].x || Vs[0].y != Vs[1].y) {
434 num_vs++;
435 }
436 } else if (i == num_hinge_vs-1) {
437 if (Vs[NumVs-1].x != Vs[NumVs-2].x || Vs[NumVs-1].y != Vs[NumVs-2].y) {
438 num_vs++;
439 }
440 } else {
441 if (Vs[j-1].x != Vs[j].x || Vs[j-1].y != Vs[j].y) {
442 num_vs++;
443 }
444 if (Vs[j+1].x != Vs[j].x || Vs[j+1].y != Vs[j].y) {
445 num_vs++;
446 }
447 }
448 }
449 vs = (IntPoint*)malloc((num_vs+2)*sizeof(IntPoint));
450 if (vs == NULL) FailAllocMessage();
451 ssmooth = (char*)malloc((num_vs+2)*sizeof(char));
452 if (ssmooth == NULL) FailAllocMessage();
453 memset(ssmooth, 0, (num_vs+2)*sizeof(char));
454
455 for (i=0, j=0, k=0; i < num_hinge_vs; i++, j+=3, k++) {
456 if (i == 0) {
457 vs[k].x = Vs[0].x;
458 vs[k].y = Vs[0].y;
459 ssmooth[k] = FALSE;
460 if (Vs[0].x != Vs[1].x || Vs[0].y != Vs[1].y) {
461 k++;
462 vs[k].x = Vs[1].x;
463 vs[k].y = Vs[1].y;
464 ssmooth[k] = TRUE;
465 }
466 } else if (i == num_hinge_vs-1) {
467 if (Vs[NumVs-1].x != Vs[NumVs-2].x || Vs[NumVs-1].y != Vs[NumVs-2].y) {
468 vs[k].x = Vs[NumVs-2].x;
469 vs[k].y = Vs[NumVs-2].y;
470 ssmooth[k] = TRUE;
471 k++;
472 }
473 vs[k].x = Vs[NumVs-1].x;
474 vs[k].y = Vs[NumVs-1].y;
475 ssmooth[k] = FALSE;
476 } else {
477 if (Vs[j-1].x != Vs[j].x || Vs[j-1].y != Vs[j].y) {
478 vs[k].x = Vs[j-1].x;
479 vs[k].y = Vs[j-1].y;
480 ssmooth[k] = TRUE;
481 k++;
482 }
483 vs[k].x = Vs[j].x;
484 vs[k].y = Vs[j].y;
485 ssmooth[k] = FALSE;
486 if (Vs[j+1].x != Vs[j].x || Vs[j+1].y != Vs[j].y) {
487 k++;
488 vs[k].x = Vs[j+1].x;
489 vs[k].y = Vs[j+1].y;
490 ssmooth[k] = TRUE;
491 }
492 }
493 }
494 #ifdef _TGIF_DBG /* debug, do not translate */
495 TgAssert(k == num_vs,
496 "k != num_vs in MakeStructuredSplinePolygonVertex()", NULL);
497 #endif /* _TGIF_DBG */
498 *pn_N = num_vs;
499 *ppszSmooth = ssmooth;
500
501 return vs;
502 }
503
504 static XPoint *splineVs=NULL;
505 static DoublePoint *splineDoubleVs=NULL;
506
507 static
AddSplinePt(N,MaxN,X,Y)508 int AddSplinePt(N, MaxN, X, Y)
509 int *N, *MaxN, X, Y;
510 {
511 if (*N == *MaxN) {
512 splineVs = (XPoint*)realloc(splineVs, (*MaxN)*2*sizeof(XPoint)+1);
513 if (splineVs == NULL) {
514 return FailAllocMessage();
515 }
516 *MaxN = (*MaxN) * 2;
517 }
518 splineVs[*N].x = X;
519 splineVs[*N].y = Y;
520 (*N)++;
521 return TRUE;
522 }
523
524 static
AddDoubleSplinePt(N,MaxN,X,Y)525 int AddDoubleSplinePt(N, MaxN, X, Y)
526 int *N, *MaxN;
527 double X, Y;
528 {
529 if (*N == *MaxN) {
530 splineDoubleVs = (DoublePoint*)realloc(splineDoubleVs,
531 (*MaxN)*2*sizeof(DoublePoint)+1);
532 if (splineDoubleVs == NULL) {
533 return FailAllocMessage();
534 }
535 *MaxN = (*MaxN) << 1;
536 }
537 splineDoubleVs[*N].x = X;
538 splineDoubleVs[*N].y = Y;
539 (*N)++;
540 return TRUE;
541 }
542
543 static
SetSplineVs(N,MaxN,X1,Y1,X2,Y2,X3,Y3,X4,Y4)544 void SetSplineVs(N, MaxN, X1, Y1, X2, Y2, X3, Y3, X4, Y4)
545 int *N, *MaxN;
546 double X1, Y1, X2, Y2, X3, Y3, X4, Y4;
547 /* X1, Y1, X2, Y2, X3, Y3, X4, Y4 are screen offsets */
548 {
549 if (tighterStructSplines) {
550 double mx1, my1, mx2, my2, mx3, my3, mx12, my12, mx23, my23, mx4, my4;
551
552 MidPoint(X1, Y1, X2, Y2, &mx1, &my1);
553 MidPoint(X2, Y2, X3, Y3, &mx2, &my2);
554 MidPoint(X3, Y3, X4, Y4, &mx3, &my3);
555
556 MidPoint(mx1, my1, mx2, my2, &mx12, &my12);
557 MidPoint(mx2, my2, mx3, my3, &mx23, &my23);
558
559 MidPoint(mx12, my12, mx23, my23, &mx4, &my4);
560
561 if (fabs(X1 - mx4) < splineTol && fabs(Y1 - my4) < splineTol) {
562 AddSplinePt(N, MaxN, round(mx4), round(my4));
563 } else {
564 SetSplineVs(N, MaxN, X1, Y1, mx1, my1, mx12, my12, mx4, my4);
565 }
566 if (fabs(mx4 - X4) < splineTol && fabs(my4 - Y4) < splineTol) {
567 AddSplinePt(N, MaxN, round(X4), round(Y4));
568 } else {
569 SetSplineVs(N, MaxN, mx4, my4, mx23, my23, mx3, my3, X4, Y4);
570 }
571 } else {
572 double x, y;
573
574 x = (X2 + X3) / 2.0;
575 y = (Y2 + Y3) / 2.0;
576 if (fabs(X1 - x) < splineTol && fabs(Y1 - y) < splineTol) {
577 AddSplinePt(N, MaxN, round(x), round(y));
578 } else {
579 SetSplineVs(N, MaxN, X1, Y1, ((X1+X2)/2.0), ((Y1+Y2)/2.0),
580 ((3.0*X2+X3)/4.0), ((3.0*Y2+Y3)/4.0), x, y);
581 }
582 if (fabs(x - X4) < splineTol && fabs(y - Y4) < splineTol) {
583 AddSplinePt(N, MaxN, round(X4), round(Y4));
584 } else {
585 SetSplineVs(N, MaxN, x, y, ((X2+3.0*X3)/4.0), ((Y2+3.0*Y3)/4.0),
586 ((X3+X4)/2.0), ((Y3+Y4)/2.0), X4, Y4);
587 }
588 }
589 }
590
591 static
SetDoubleSplineVs(N,MaxN,X1,Y1,X2,Y2,X3,Y3,X4,Y4)592 void SetDoubleSplineVs(N, MaxN, X1, Y1, X2, Y2, X3, Y3, X4, Y4)
593 int *N, *MaxN;
594 double X1, Y1, X2, Y2, X3, Y3, X4, Y4;
595 /* X1, Y1, X2, Y2, X3, Y3, X4, Y4 are screen offsets */
596 {
597 if (tighterStructSplines) {
598 double mx1, my1, mx2, my2, mx3, my3, mx12, my12, mx23, my23, mx4, my4;
599
600 MidPoint(X1, Y1, X2, Y2, &mx1, &my1);
601 MidPoint(X2, Y2, X3, Y3, &mx2, &my2);
602 MidPoint(X3, Y3, X4, Y4, &mx3, &my3);
603
604 MidPoint(mx1, my1, mx2, my2, &mx12, &my12);
605 MidPoint(mx2, my2, mx3, my3, &mx23, &my23);
606
607 MidPoint(mx12, my12, mx23, my23, &mx4, &my4);
608
609 if (fabs(X1 - mx4) < splineTol && fabs(Y1 - my4) < splineTol) {
610 AddDoubleSplinePt(N, MaxN, mx4, my4);
611 } else {
612 SetDoubleSplineVs(N, MaxN, X1, Y1, mx1, my1, mx12, my12, mx4, my4);
613 }
614 if (fabs(mx4 - X4) < splineTol && fabs(my4 - Y4) < splineTol) {
615 AddDoubleSplinePt(N, MaxN, round(X4), round(Y4));
616 } else {
617 SetDoubleSplineVs(N, MaxN, mx4, my4, mx23, my23, mx3, my3, X4, Y4);
618 }
619 } else {
620 double x, y;
621
622 x = (X2 + X3) / 2.0;
623 y = (Y2 + Y3) / 2.0;
624 if (fabs(X1 - x) < splineTol && fabs(Y1 - y) < splineTol) {
625 AddDoubleSplinePt(N, MaxN, x, y);
626 } else {
627 SetDoubleSplineVs(N, MaxN, X1, Y1, ((X1+X2)/2.0), ((Y1+Y2)/2.0),
628 ((3.0*X2+X3)/4.0), ((3.0*Y2+Y3)/4.0), x, y);
629 }
630 if (fabs(x - X4) < splineTol && fabs(y - Y4) < splineTol) {
631 AddDoubleSplinePt(N, MaxN, X4, Y4);
632 } else {
633 SetDoubleSplineVs(N, MaxN, x, y, ((X2+3.0*X3)/4.0), ((Y2+3.0*Y3)/4.0),
634 ((X3+X4)/2.0), ((Y3+Y4)/2.0), X4, Y4);
635 }
636 }
637 }
638
MakeSplinePolyVertex(Level,Curved,N,XOff,YOff,NumVs,Vs)639 XPoint *MakeSplinePolyVertex(Level, Curved, N, XOff, YOff, NumVs, Vs)
640 int Level, Curved, *N, XOff, YOff, NumVs;
641 IntPoint *Vs;
642 {
643 double mx1, my1, mx2, my2, mx3, my3, mx4, my4;
644 double x0, y0, x1, y1, x2, y2, x3, y3;
645 int i, x_off, y_off, max_n, saved_tighter_splines=tighterStructSplines;
646
647 if (Level == 0 && Curved != LT_STRUCT_SPLINE && saved_tighter_splines) {
648 tighterStructSplines = FALSE;
649 }
650 x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
651 y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
652
653 splineVs = NULL;
654
655 switch (NumVs) {
656 case 0:
657 case 1:
658 break;
659 case 2:
660 splineVs = (XPoint*)malloc((NumVs+1)*sizeof(XPoint));
661 if (splineVs == NULL) {
662 FailAllocMessage();
663 *N = 0;
664 tighterStructSplines = saved_tighter_splines;
665 return splineVs;
666 }
667 memset(splineVs, 0, (NumVs+1)*sizeof(XPoint));
668 splineVs[0].x = ZOOMED_SIZE(Vs[0].x-x_off);
669 splineVs[0].y = ZOOMED_SIZE(Vs[0].y-y_off);
670 splineVs[1].x = ZOOMED_SIZE(Vs[1].x-x_off);
671 splineVs[1].y = ZOOMED_SIZE(Vs[1].y-y_off);
672 *N = 2;
673 break;
674 case 3:
675 if (tighterStructSplines) {
676 mx1 = ZOOMED_SIZE(Vs->x-x_off); my1 = ZOOMED_SIZE((Vs++)->y-y_off);
677 x1 = ZOOMED_SIZE(Vs->x-x_off); y1 = ZOOMED_SIZE((Vs++)->y-y_off);
678 mx2 = (mx1+2.0*x1)/3.0; my2 = (my1+2.0*y1)/3.0;
679 mx4 = ZOOMED_SIZE(Vs->x-x_off); my4 = ZOOMED_SIZE(Vs->y-y_off);
680 mx3 = (2.0*x1+mx4)/3.0; my3 = (2.0*y1+my4)/3.0;
681 max_n = 100;
682 splineVs = (XPoint*)malloc((max_n+1)*sizeof(XPoint));
683 if (splineVs == NULL) {
684 FailAllocMessage();
685 *N = 0;
686 tighterStructSplines = saved_tighter_splines;
687 return splineVs;
688 }
689 memset(splineVs, 0, (max_n+1)*sizeof(XPoint));
690 splineVs[0].x = mx1;
691 splineVs[0].y = my1;
692 *N = 1;
693 SetSplineVs(N, &max_n, mx1, my1, mx2, my2, mx3, my3, mx4, my4);
694 } else {
695 mx1 = ZOOMED_SIZE(Vs->x-x_off); my1 = ZOOMED_SIZE((Vs++)->y-y_off);
696 x1 = ZOOMED_SIZE(Vs->x-x_off); y1 = ZOOMED_SIZE((Vs++)->y-y_off);
697 mx2 = (mx1+x1)/2.0; my2 = (my1+y1)/2.0;
698 mx4 = ZOOMED_SIZE(Vs->x-x_off); my4 = ZOOMED_SIZE(Vs->y-y_off);
699 mx3 = (x1+mx4)/2.0; my3 = (y1+my4)/2.0;
700 max_n = 100;
701 splineVs = (XPoint*)malloc((max_n+1)*sizeof(XPoint));
702 if (splineVs == NULL) {
703 FailAllocMessage();
704 *N = 0;
705 tighterStructSplines = saved_tighter_splines;
706 return splineVs;
707 }
708 memset(splineVs, 0, (max_n+1)*sizeof(XPoint));
709 splineVs[0].x = mx1;
710 splineVs[0].y = my1;
711 *N = 1;
712 SetSplineVs(N, &max_n, mx1, my1, mx2, my2, mx3, my3, mx4, my4);
713 }
714 break;
715 default:
716 if (tighterStructSplines) {
717 /* must only have 4 points */
718 double mx1, my1, mx2, my2, mx3, my3, mx12, my12, mx23, my23, mx4, my4;
719
720 x0 = ZOOMED_SIZE(Vs->x-x_off); y0 = ZOOMED_SIZE((Vs++)->y-y_off);
721 x1 = ZOOMED_SIZE(Vs->x-x_off); y1 = ZOOMED_SIZE((Vs++)->y-y_off);
722 x2 = ZOOMED_SIZE(Vs->x-x_off); y2 = ZOOMED_SIZE((Vs++)->y-y_off);
723 x3 = ZOOMED_SIZE(Vs->x-x_off); y3 = ZOOMED_SIZE(Vs->y-y_off);
724
725 MidPoint(x0, y0, x1, y1, &mx1, &my1);
726 MidPoint(x1, y1, x2, y2, &mx2, &my2);
727 MidPoint(x2, y2, x3, y3, &mx3, &my3);
728
729 MidPoint(mx1, my1, mx2, my2, &mx12, &my12);
730 MidPoint(mx2, my2, mx3, my3, &mx23, &my23);
731
732 MidPoint(mx12, my12, mx23, my23, &mx4, &my4);
733
734 max_n = 100;
735 splineVs = (XPoint *)malloc((max_n+1)*sizeof(XPoint));
736 if (splineVs == NULL) {
737 FailAllocMessage();
738 *N = 0;
739 tighterStructSplines = saved_tighter_splines;
740 return splineVs;
741 }
742 memset(splineVs, 0, (max_n+1)*sizeof(XPoint));
743 splineVs[0].x = x0;
744 splineVs[0].y = y0;
745 *N = 1;
746 SetSplineVs(N, &max_n, x0, y0, mx1, my1, mx12, my12, mx4, my4);
747 SetSplineVs(N, &max_n, mx4, my4, mx23, my23, mx3, my3, x3, y3);
748 } else {
749 mx1 = ZOOMED_SIZE(Vs->x-x_off); my1 = ZOOMED_SIZE((Vs++)->y-y_off);
750 x1 = ZOOMED_SIZE(Vs->x-x_off); y1 = ZOOMED_SIZE((Vs++)->y-y_off);
751 x2 = ZOOMED_SIZE(Vs->x-x_off); y2 = ZOOMED_SIZE((Vs++)->y-y_off);
752 mx2 = (mx1+x1)/2.0; my2 = (my1+y1)/2.0;
753 mx3 = (3.0*x1+x2)/4.0; my3 = (3.0*y1+y2)/4.0;
754 mx4 = (x1+x2)/2.0; my4 = (y1+y2)/2.0;
755 max_n = 100;
756 splineVs = (XPoint *)malloc((max_n+1)*sizeof(XPoint));
757 if (splineVs == NULL) {
758 FailAllocMessage();
759 *N = 0;
760 tighterStructSplines = saved_tighter_splines;
761 return splineVs;
762 }
763 memset(splineVs, 0, (max_n+1)*sizeof(XPoint));
764 splineVs[0].x = mx1;
765 splineVs[0].y = my1;
766 *N = 1;
767 SetSplineVs(N, &max_n, mx1, my1, mx2, my2, mx3, my3, mx4, my4);
768
769 for (i=2; i < NumVs-2; i++, Vs++) {
770 mx1 = mx4; my1 = my4;
771 mx2 = (x1 + 3.0*x2) / 4.0; my2 = (y1 + 3.0*y2) / 4.0;
772 x1 = x2; y1 = y2;
773 x2 = ZOOMED_SIZE(Vs->x-x_off); y2 = ZOOMED_SIZE(Vs->y-y_off);
774 mx3 = (3.0*x1 + x2) / 4.0; my3 = (3.0*y1 + y2) / 4.0;
775 mx4 = (x1 + x2) / 2.0; my4 = (y1 + y2) / 2.0;
776 SetSplineVs(N, &max_n, mx1, my1, mx2, my2, mx3, my3, mx4, my4);
777 }
778 mx1 = mx4; my1 = my4;
779 mx2 = (x1 + 3.0*x2) / 4.0; my2 = (y1 + 3.0*y2) / 4.0;
780 x1 = x2; y1 = y2;
781 mx4 = ZOOMED_SIZE(Vs->x-x_off); my4 = ZOOMED_SIZE(Vs->y-y_off);
782 mx3 = (x1 + mx4) / 2.0; my3 = (y1 + my4) / 2.0;
783 SetSplineVs(N, &max_n, mx1, my1, mx2, my2, mx3, my3, mx4, my4);
784 }
785 break;
786 }
787 tighterStructSplines = saved_tighter_splines;
788
789 return splineVs;
790 }
791
792 typedef struct MultiSplineRec {
793 XPoint *vlist;
794 int n;
795 } *MultiSplineRecPtr;
796
MakeMultiSplinePolyVertex(Curved,N,Smooth,XOff,YOff,NumVs,Vs)797 XPoint *MakeMultiSplinePolyVertex(Curved, N, Smooth, XOff, YOff, NumVs, Vs)
798 int *N, XOff, YOff, NumVs;
799 char *Smooth;
800 IntPoint *Vs;
801 {
802 register int i, j;
803 int segments=1, has_smooth_point=FALSE, start_index, seg_index;
804 int total=0;
805 XPoint *xpptr=NULL;
806 struct MultiSplineRec *msptr=NULL;
807
808 if (Smooth == NULL) {
809 return MakeSplinePolyVertex(0, Curved, N, XOff, YOff, NumVs, Vs);
810 }
811 if (Smooth[0] || Smooth[NumVs-1]) {
812 FatalUnexpectedError(
813 TgLoadCachedString(CSTID_CORRUPTED_POLY_MKMULTISPLINE),
814 TgLoadCachedString(CSTID_FIX_ATTEMPTED));
815 Smooth[0] = Smooth[NumVs-1] = FALSE;
816 }
817 for (i=1; i < NumVs-1; i++) {
818 if (Smooth[i]) {
819 has_smooth_point = TRUE;
820 } else {
821 segments++;
822 }
823 }
824 if (!has_smooth_point) {
825 *N = NumVs;
826 return MakePolyVertex(XOff, YOff, NumVs, Vs);
827 }
828 if (segments == 1) {
829 return MakeSplinePolyVertex(0, Curved, N, XOff, YOff, NumVs, Vs);
830 }
831 msptr = (struct MultiSplineRec *)malloc(segments *
832 sizeof(struct MultiSplineRec));
833 if (msptr == NULL) {
834 FailAllocMessage();
835 return NULL;
836 }
837 memset(msptr, 0, segments*sizeof(struct MultiSplineRec));
838
839 start_index = 0;
840 seg_index = 0;
841 for (i=1; i <= NumVs-1; i++) {
842 if (!Smooth[i]) {
843 msptr[seg_index].vlist = MakeSplinePolyVertex(0, Curved,
844 &msptr[seg_index].n, XOff, YOff, i-start_index+1,
845 &Vs[start_index]);
846 total += msptr[seg_index].n-1;
847 seg_index++;
848 start_index = i;
849 }
850 }
851 if (total > 0) total++;
852 splineVs = (XPoint *)malloc((total+2)*sizeof(XPoint));
853 if (splineVs == NULL) FailAllocMessage();
854 memset(splineVs, 0, (total+2)*sizeof(XPoint));
855 xpptr = splineVs;
856 for (i=0; i < segments; i++) {
857 if (msptr[i].vlist != NULL) {
858 for (j=0; j < msptr[i].n; j++) {
859 xpptr->x = msptr[i].vlist[j].x;
860 xpptr->y = msptr[i].vlist[j].y;
861 xpptr++;
862 }
863 xpptr--;
864 free(msptr[i].vlist);
865 }
866 }
867 free(msptr);
868 *N = total;
869 return splineVs;
870 }
871
MakeSplinePolygonVertex(Level,Curved,N,XOff,YOff,NumVs,Vs)872 XPoint *MakeSplinePolygonVertex(Level, Curved, N, XOff, YOff, NumVs, Vs)
873 int Level, Curved, *N, XOff, YOff, NumVs;
874 IntPoint *Vs;
875 {
876 double mx1, my1, mx2, my2, mx3, my3, mx4, my4, x1, y1, x2, y2;
877 int i, x_off, y_off, max_n, saved_tighter_splines=tighterStructSplines;
878
879 #ifdef _TGIF_DBG /* debug, do not translate */
880 TgAssert(Curved != LT_STRUCT_SPLINE,
881 "Curved == LT_STRUCT_SPLINE in MakeSplinePolygonVertex()", NULL);
882 #endif /* _TGIF_DBG */
883
884 if (Level == 0 && Curved != LT_STRUCT_SPLINE && saved_tighter_splines) {
885 tighterStructSplines = FALSE;
886 }
887 x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
888 y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
889
890 splineVs = NULL;
891
892 if (NumVs <= 3) {
893 splineVs = (XPoint *)malloc(5*sizeof(XPoint));
894 if (splineVs == NULL) {
895 FailAllocMessage();
896 *N = 0;
897 tighterStructSplines = saved_tighter_splines;
898 return splineVs;
899 }
900 memset(splineVs, 0, 5*sizeof(XPoint));
901 splineVs[0].x = ZOOMED_SIZE(Vs[0].x-x_off);
902 splineVs[0].y = ZOOMED_SIZE(Vs[0].y-y_off);
903 splineVs[1].x = ZOOMED_SIZE(Vs[1].x-x_off);
904 splineVs[1].y = ZOOMED_SIZE(Vs[1].y-y_off);
905 *N = 2;
906 tighterStructSplines = saved_tighter_splines;
907 return splineVs;
908 }
909 Vs[NumVs].x = Vs[1].x; Vs[NumVs].y = Vs[1].y;
910 x1 = ZOOMED_SIZE(Vs->x-x_off); y1 = ZOOMED_SIZE((Vs++)->y-y_off);
911 x2 = ZOOMED_SIZE(Vs->x-x_off); y2 = ZOOMED_SIZE((Vs++)->y-y_off);
912 mx4 = (x1 + x2) / 2.0; my4 = (y1 + y2) / 2.0;
913
914 max_n = 100;
915 splineVs = (XPoint*)malloc((max_n+1)*sizeof(XPoint));
916 if (splineVs == NULL) {
917 FailAllocMessage();
918 *N = 0;
919 tighterStructSplines = saved_tighter_splines;
920 return splineVs;
921 }
922 memset(splineVs, 0, (max_n+1)*sizeof(XPoint));
923 splineVs[0].x = mx4;
924 splineVs[0].y = my4;
925 *N = 1;
926
927 for (i=1; i < NumVs; i++, Vs++) {
928 mx1 = mx4; my1 = my4;
929 mx2 = (x1+3.0*x2)/4.0; my2 = (y1+3.0*y2)/4.0;
930 x1 = x2; y1 = y2;
931 x2 = ZOOMED_SIZE(Vs->x-x_off); y2 = ZOOMED_SIZE(Vs->y-y_off);
932 mx3 = (3.0*x1+x2)/4.0; my3 = (3.0*y1+y2)/4.0;
933 mx4 = (x1+x2)/2.0; my4 = (y1+y2)/2.0;
934 SetSplineVs(N, &max_n, mx1, my1, mx2, my2, mx3, my3, mx4, my4);
935 }
936 tighterStructSplines = saved_tighter_splines;
937
938 return splineVs;
939 }
940
941 static
DoMakeDoubleIntSplinePolygonVertex(N,XOff,YOff,NumVs,Vs)942 XPoint *DoMakeDoubleIntSplinePolygonVertex(N, XOff, YOff, NumVs, Vs)
943 int *N, XOff, YOff, NumVs;
944 DoublePoint *Vs;
945 {
946 double mx1, my1, mx2, my2, mx3, my3, mx4, my4, x1, y1, x2, y2, x, y;
947 double dx_off, dy_off;
948 int i, max_n, x_off, y_off;
949
950 x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
951 y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
952
953 dx_off = (double)x_off;
954 dy_off = (double)y_off;
955
956 splineVs = NULL;
957
958 if (NumVs <= 3) {
959 splineVs = (XPoint *)malloc(5*sizeof(XPoint));
960 if (splineVs == NULL) {
961 FailAllocMessage();
962 *N = 0;
963 return splineVs;
964 }
965 memset(splineVs, 0, 5*sizeof(XPoint));
966 x = ZOOMED_DOUBLE_SIZE(Vs[0].x-dx_off);
967 y = ZOOMED_DOUBLE_SIZE(Vs[0].y-dy_off);
968 splineVs[0].x = round(x);
969 splineVs[0].y = round(y);
970 x = ZOOMED_DOUBLE_SIZE(Vs[1].x-dx_off);
971 y = ZOOMED_DOUBLE_SIZE(Vs[1].y-dy_off);
972 splineVs[1].x = round(x);
973 splineVs[1].y = round(y);
974 *N = 2;
975 return splineVs;
976 }
977
978 Vs[NumVs].x = Vs[1].x; Vs[NumVs].y = Vs[1].y;
979 x1 = ZOOMED_DOUBLE_SIZE(Vs->x-dx_off);
980 y1 = ZOOMED_DOUBLE_SIZE((Vs++)->y-dy_off);
981 x2 = ZOOMED_DOUBLE_SIZE(Vs->x-dx_off);
982 y2 = ZOOMED_DOUBLE_SIZE((Vs++)->y-dy_off);
983 mx4 = (x1 + x2) / 2.0;
984 my4 = (y1 + y2) / 2.0;
985
986 max_n = 100;
987 splineDoubleVs = (DoublePoint*)malloc((max_n+1)*sizeof(DoublePoint));
988 if (splineDoubleVs == NULL) {
989 FailAllocMessage();
990 *N = 0;
991 return NULL;
992 }
993 memset(splineDoubleVs, 0, (max_n+1)*sizeof(DoublePoint));
994 splineDoubleVs[0].x = mx4;
995 splineDoubleVs[0].y = my4;
996 *N = 1;
997
998 for (i=1; i < NumVs; i++, Vs++) {
999 mx1 = mx4; my1 = my4;
1000 mx2 = (x1+3.0*x2)/4.0; my2 = (y1+3.0*y2)/4.0;
1001 x1 = x2; y1 = y2;
1002 x2 = ZOOMED_DOUBLE_SIZE(Vs->x-dx_off); y2 = ZOOMED_DOUBLE_SIZE(Vs->y-dy_off);
1003 mx3 = (3.0*x1+x2)/4.0; my3 = (3.0*y1+y2)/4.0;
1004 mx4 = (x1+x2)/2.0; my4 = (y1+y2)/2.0;
1005 SetDoubleSplineVs(N, &max_n, mx1, my1, mx2, my2, mx3, my3, mx4, my4);
1006 }
1007 splineVs = (XPoint*)malloc(((*N)+2)*sizeof(XPoint));
1008 if (splineVs == NULL) {
1009 FailAllocMessage();
1010 free(splineDoubleVs);
1011 splineDoubleVs = NULL;
1012 *N = 0;
1013 return NULL;
1014 }
1015 memset(splineVs, 0, ((*N)+2)*sizeof(XPoint));
1016 for (i=0; i < *N; i++) {
1017 splineVs[i].x = round(splineDoubleVs[i].x);
1018 splineVs[i].y = round(splineDoubleVs[i].y);
1019 }
1020 free(splineDoubleVs);
1021 splineDoubleVs = NULL;
1022 return splineVs;
1023 }
1024
MakeMultiSplinePolygonVertex(Curved,N,Smooth,XOff,YOff,NumVs,Vs)1025 XPoint *MakeMultiSplinePolygonVertex(Curved, N, Smooth, XOff, YOff, NumVs, Vs)
1026 int Curved, *N, XOff, YOff, NumVs;
1027 char *Smooth;
1028 IntPoint *Vs;
1029 {
1030 register int i, j;
1031 int num_smooth_points=0, num_hinge_points=0;
1032 int start_index, seg_index, tmp_index;
1033 int total=0, once_around=FALSE;
1034 XPoint *xpptr=NULL;
1035 IntPoint *tmp_vs=NULL;
1036 struct MultiSplineRec *msptr=NULL;
1037
1038 if (Smooth == NULL) {
1039 return MakeSplinePolygonVertex(0, Curved, N, XOff, YOff, NumVs, Vs);
1040 }
1041 for (i=1; i < NumVs; i++) {
1042 if (Smooth[i]) {
1043 num_smooth_points++;
1044 } else {
1045 num_hinge_points++;
1046 }
1047 }
1048 if (num_smooth_points == 0) {
1049 *N = NumVs;
1050 return MakePolygonVertex(XOff, YOff, NumVs, Vs);
1051 }
1052 if (num_hinge_points == 0) {
1053 return MakeSplinePolygonVertex(0, Curved, N, XOff, YOff, NumVs, Vs);
1054 }
1055 msptr = (struct MultiSplineRec *)malloc(num_hinge_points *
1056 sizeof(struct MultiSplineRec));
1057 if (msptr == NULL) FailAllocMessage();
1058 memset(msptr, 0, num_hinge_points*sizeof(struct MultiSplineRec));
1059
1060 for (i=0; i < NumVs; i++) {
1061 if (!Smooth[i]) {
1062 break;
1063 }
1064 }
1065 tmp_vs = (IntPoint*)malloc((NumVs+1)*sizeof(IntPoint));
1066 if (tmp_vs == NULL) FailAllocMessage();
1067 memset(tmp_vs, 0, (NumVs+1)*sizeof(IntPoint));
1068 start_index = i;
1069 seg_index = 0;
1070
1071 tmp_vs[0].x = Vs[start_index].x;
1072 tmp_vs[0].y = Vs[start_index].y;
1073 tmp_index = 1;
1074 for (i=start_index+1; !(once_around && i==start_index+1); i++, tmp_index++) {
1075 tmp_vs[tmp_index].x = Vs[i].x;
1076 tmp_vs[tmp_index].y = Vs[i].y;
1077 if (!Smooth[i]) {
1078 msptr[seg_index].vlist = MakeSplinePolyVertex(0, Curved,
1079 &msptr[seg_index].n, XOff, YOff, tmp_index+1, tmp_vs);
1080 total += msptr[seg_index].n-1;
1081 seg_index++;
1082 start_index = (i==NumVs-1 ? 0 : i);
1083 tmp_vs[0].x = Vs[start_index].x;
1084 tmp_vs[0].y = Vs[start_index].y;
1085 tmp_index = 0;
1086 }
1087 if (i == NumVs-1) {
1088 i = 0;
1089 once_around = TRUE;
1090 }
1091 }
1092 if (tmp_vs != NULL) free(tmp_vs);
1093 if (total > 0) total++;
1094 splineVs = (XPoint*)malloc((total+2)*sizeof(XPoint));
1095 if (splineVs == NULL) FailAllocMessage();
1096 memset(splineVs, 0, (total+2)*sizeof(XPoint));
1097 xpptr = splineVs;
1098 for (i=0; i < num_hinge_points; i++) {
1099 if (msptr[i].vlist != NULL) {
1100 for (j=0; j < msptr[i].n; j++) {
1101 xpptr->x = msptr[i].vlist[j].x;
1102 xpptr->y = msptr[i].vlist[j].y;
1103 xpptr++;
1104 }
1105 xpptr--;
1106 free(msptr[i].vlist);
1107 }
1108 }
1109 free(msptr);
1110 *N = total;
1111 return splineVs;
1112 }
1113
1114 struct MtxRec {
1115 double *x, *y, *dx, *dy;
1116 double **mtx;
1117 } mtxInfo;
1118
1119 static
OpenSetupMatrix(NumPts,Vs)1120 void OpenSetupMatrix(NumPts, Vs)
1121 int NumPts;
1122 IntPoint *Vs;
1123 {
1124 register int i;
1125
1126 mtxInfo.x = (double*)malloc(NumPts*sizeof(double));
1127 mtxInfo.y = (double*)malloc(NumPts*sizeof(double));
1128 mtxInfo.dx = (double*)malloc(NumPts*sizeof(double));
1129 mtxInfo.dy = (double*)malloc(NumPts*sizeof(double));
1130 if (mtxInfo.x == NULL || mtxInfo.y == NULL || mtxInfo.dx == NULL ||
1131 mtxInfo.dy == NULL) {
1132 FailAllocMessage();
1133 }
1134 for (i=0; i < NumPts; i++) {
1135 mtxInfo.x[i] = mtxInfo.dx[i] = ((double)(Vs[i].x))*((double)theSum);
1136 mtxInfo.y[i] = mtxInfo.dy[i] = ((double)(Vs[i].y))*((double)theSum);
1137 }
1138 mtxInfo.mtx = (double**)malloc(NumPts*sizeof(double*));
1139 if (mtxInfo.mtx == NULL) FailAllocMessage();
1140 memset(mtxInfo.mtx, 0, NumPts*sizeof(double*));
1141 for (i=0; i < NumPts; i++) {
1142 mtxInfo.mtx[i] = (double*)malloc(3*sizeof(double));
1143 if (mtxInfo.mtx[i] == NULL) FailAllocMessage();
1144 memset(mtxInfo.mtx[i], 0, 3*sizeof(double));
1145 }
1146 mtxInfo.mtx[0][0] = mtxInfo.mtx[NumPts-1][2] = (double)0.0;
1147 mtxInfo.mtx[0][1] = mtxInfo.mtx[NumPts-1][1] = (double)theSum;
1148 mtxInfo.mtx[0][2] = mtxInfo.mtx[NumPts-1][0] = (double)0.0;
1149 for (i=1; i < NumPts-1; i++) {
1150 mtxInfo.mtx[i][0] = (double)1.0;
1151 mtxInfo.mtx[i][1] = (double)SUM_MINUS_2;
1152 mtxInfo.mtx[i][2] = (double)1.0;
1153 }
1154 }
1155
1156 static
TriGaussian(NumPts)1157 void TriGaussian(NumPts)
1158 int NumPts;
1159 {
1160 register int i;
1161 register double val;
1162
1163 for (i=1; i<NumPts-1; i++) {
1164 val = (-mtxInfo.mtx[i-1][1]);
1165 mtxInfo.mtx[i][0] = (double)0.0;
1166 mtxInfo.mtx[i][1] = (mtxInfo.mtx[i][1]*val+mtxInfo.mtx[i-1][2])/theSum;
1167 mtxInfo.mtx[i][2] = val/theSum;
1168 mtxInfo.x[i] = (mtxInfo.x[i]*val+mtxInfo.x[i-1])/theSum;
1169 mtxInfo.y[i] = (mtxInfo.y[i]*val+mtxInfo.y[i-1])/theSum;
1170 }
1171 mtxInfo.x[i] = mtxInfo.x[i]/mtxInfo.mtx[i][1];
1172 mtxInfo.y[i] = mtxInfo.y[i]/mtxInfo.mtx[i][1];
1173 for (i--; i>=0; i--) {
1174 mtxInfo.x[i] = (mtxInfo.x[i]-mtxInfo.x[i+1]*mtxInfo.mtx[i][2]) /
1175 mtxInfo.mtx[i][1];
1176 mtxInfo.y[i] = (mtxInfo.y[i]-mtxInfo.y[i+1]*mtxInfo.mtx[i][2]) /
1177 mtxInfo.mtx[i][1];
1178 }
1179 }
1180
1181 static
FreeMtxInfo(NumPts)1182 void FreeMtxInfo(NumPts)
1183 int NumPts;
1184 {
1185 register int i;
1186
1187 if (mtxInfo.x != NULL) free(mtxInfo.x);
1188 if (mtxInfo.y != NULL) free(mtxInfo.y);
1189 if (mtxInfo.dx != NULL) free(mtxInfo.dx);
1190 if (mtxInfo.dy != NULL) free(mtxInfo.dy);
1191 if (mtxInfo.mtx != NULL) {
1192 for (i=0; i < NumPts; i++) {
1193 if (mtxInfo.mtx[i] != NULL) free(mtxInfo.mtx[i]);
1194 }
1195 free(mtxInfo.mtx);
1196 }
1197 memset(&mtxInfo, 0, sizeof(struct MtxRec));
1198 }
1199
1200 static
OpenControlPts(NumPts,N)1201 IntPoint *OpenControlPts(NumPts, N)
1202 int NumPts, *N;
1203 {
1204 register int i;
1205 int index=0;
1206 double half=theSum/((double)2.0);
1207 double weight=half-((double)1.0);
1208 IntPoint *v;
1209
1210 v = (IntPoint*)malloc((((NumPts-2)<<1)+2)*sizeof(IntPoint));
1211 if (v == NULL) FailAllocMessage();
1212 memset(v, 0, (((NumPts-2)<<1)+2)*sizeof(IntPoint));
1213
1214 v[index].x = (int)(mtxInfo.x[0]);
1215 v[index].y = (int)(mtxInfo.y[0]);
1216 index++;
1217 v[index].x = (int)((mtxInfo.x[0]+weight*mtxInfo.x[1])/half);
1218 v[index].y = (int)((mtxInfo.y[0]+weight*mtxInfo.y[1])/half);
1219 index++;
1220 for (i=1; i<NumPts-2; i++) {
1221 v[index].x = (int)((weight*mtxInfo.x[i]+mtxInfo.x[i+1])/half);
1222 v[index].y = (int)((weight*mtxInfo.y[i]+mtxInfo.y[i+1])/half);
1223 index++;
1224 v[index].x = (int)((mtxInfo.x[i]+weight*mtxInfo.x[i+1])/half);
1225 v[index].y = (int)((mtxInfo.y[i]+weight*mtxInfo.y[i+1])/half);
1226 index++;
1227 }
1228 v[index].x = (int)((weight*mtxInfo.x[i]+mtxInfo.x[i+1])/half);
1229 v[index].y = (int)((weight*mtxInfo.y[i]+mtxInfo.y[i+1])/half);
1230 index++;
1231 v[index].x = (int)(mtxInfo.x[NumPts-1]);
1232 v[index].y = (int)(mtxInfo.y[NumPts-1]);
1233 index++;
1234
1235 FreeMtxInfo(NumPts);
1236
1237 *N = index;
1238 return v;
1239 }
1240
MakeIntSplinePolyVertex(N,CntrlN,CntrlVs,XOff,YOff,NumVs,Vs)1241 XPoint *MakeIntSplinePolyVertex(N, CntrlN, CntrlVs, XOff, YOff, NumVs, Vs)
1242 int *N, *CntrlN, XOff, YOff, NumVs;
1243 IntPoint **CntrlVs, *Vs;
1244 {
1245 int x_off, y_off;
1246
1247 x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
1248 y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
1249
1250 splineVs = NULL;
1251
1252 switch (NumVs) {
1253 case 0:
1254 case 1:
1255 break;
1256 case 2:
1257 *CntrlVs = (IntPoint*)malloc((NumVs+1)*sizeof(IntPoint));
1258 if (*CntrlVs == NULL) FailAllocMessage();
1259 memset(*CntrlVs, 0, (NumVs+1)*sizeof(IntPoint));
1260 splineVs = (XPoint*)malloc((NumVs+1)*sizeof(XPoint));
1261 if (splineVs == NULL) {
1262 FailAllocMessage();
1263 *N = 0;
1264 return splineVs;
1265 }
1266 memset(splineVs, 0, (NumVs+1)*sizeof(XPoint));
1267 splineVs[0].x = ZOOMED_SIZE(Vs[0].x-x_off);
1268 splineVs[0].y = ZOOMED_SIZE(Vs[0].y-y_off);
1269 splineVs[1].x = ZOOMED_SIZE(Vs[1].x-x_off);
1270 splineVs[1].y = ZOOMED_SIZE(Vs[1].y-y_off);
1271 (*CntrlVs)[0].x = Vs[0].x;
1272 (*CntrlVs)[0].y = Vs[0].y;
1273 (*CntrlVs)[1].x = Vs[1].x;
1274 (*CntrlVs)[1].y = Vs[1].y;
1275 *N = *CntrlN = 2;
1276 break;
1277 default:
1278 OpenSetupMatrix(NumVs, Vs);
1279 TriGaussian(NumVs);
1280 *CntrlVs = OpenControlPts(NumVs, CntrlN);
1281
1282 return MakeSplinePolyVertex(0, LT_INTSPLINE, N, XOff, YOff, *CntrlN,
1283 *CntrlVs);
1284 }
1285 return splineVs;
1286 }
1287
1288 static
ClosedSetupMatrix(NumPts,Vs)1289 void ClosedSetupMatrix(NumPts, Vs)
1290 int NumPts;
1291 IntPoint *Vs;
1292 {
1293 register int i;
1294 register double val;
1295
1296 mtxInfo.x = (double*)malloc(NumPts*sizeof(double));
1297 mtxInfo.y = (double*)malloc(NumPts*sizeof(double));
1298 mtxInfo.dx = (double*)malloc(NumPts*sizeof(double));
1299 mtxInfo.dy = (double*)malloc(NumPts*sizeof(double));
1300 if (mtxInfo.x == NULL || mtxInfo.y == NULL || mtxInfo.dx == NULL ||
1301 mtxInfo.dy == NULL) {
1302 FailAllocMessage();
1303 }
1304 for (i=0; i < NumPts; i++) {
1305 mtxInfo.x[i] = mtxInfo.dx[i] = ((double)(Vs[i].x))*((double)theSum);
1306 mtxInfo.y[i] = mtxInfo.dy[i] = ((double)(Vs[i].y))*((double)theSum);
1307 }
1308 /* the first NumPts-2 rows have an extra column */
1309 mtxInfo.mtx = (double**)malloc(NumPts*sizeof(double*));
1310 if (mtxInfo.mtx == NULL) FailAllocMessage();
1311 memset(mtxInfo.mtx, 0, NumPts*sizeof(double*));
1312 for (i=0; i < NumPts; i++) {
1313 mtxInfo.mtx[i] = (double*)malloc(4*sizeof(double));
1314 if (mtxInfo.mtx[i] == NULL) FailAllocMessage();
1315 memset(mtxInfo.mtx[i], 0, 4*sizeof(double));
1316 }
1317 mtxInfo.mtx[0][0] = mtxInfo.mtx[NumPts-1][2] = (double)1.0;
1318 mtxInfo.mtx[0][1] = mtxInfo.mtx[NumPts-1][1] = (double)SUM_MINUS_2;
1319 mtxInfo.mtx[0][2] = mtxInfo.mtx[NumPts-1][0] = (double)1.0;
1320 mtxInfo.mtx[0][3] = (double)1.0;
1321 /* use mtx[NumPts-1][3] as mtx[NumPts-1][i] where i is moving to right */
1322 mtxInfo.mtx[NumPts-1][3] = (double)0.0;
1323 for (i=1; i < NumPts-1; i++) {
1324 mtxInfo.mtx[i][0] = (double)1.0;
1325 mtxInfo.mtx[i][1] = (double)SUM_MINUS_2;
1326 mtxInfo.mtx[i][2] = (double)1.0;
1327 mtxInfo.mtx[i][3] = (double)0.0;
1328 }
1329 val = (-mtxInfo.mtx[0][1]);
1330 if (NumPts == 3) {
1331 mtxInfo.mtx[NumPts-1][0] =
1332 (mtxInfo.mtx[NumPts-1][0]*val+mtxInfo.mtx[0][2])/theSum;
1333 } else {
1334 mtxInfo.mtx[NumPts-1][0] = mtxInfo.mtx[NumPts-1][0]*val/theSum;
1335 }
1336 mtxInfo.mtx[NumPts-1][1] =
1337 (mtxInfo.mtx[NumPts-1][1]*val+mtxInfo.mtx[0][3])/theSum;
1338 /* use mtx[NumPts-1][3] as mtx[NumPts-1][i] where i moves to right */
1339 mtxInfo.mtx[NumPts-1][3] = mtxInfo.mtx[0][2]/theSum;
1340 mtxInfo.x[NumPts-1] = (mtxInfo.x[NumPts-1]*val+mtxInfo.x[0])/theSum;
1341 mtxInfo.y[NumPts-1] = (mtxInfo.y[NumPts-1]*val+mtxInfo.y[0])/theSum;
1342 }
1343
1344 static
DoubleClosedSetupMatrix(NumPts,Vs)1345 void DoubleClosedSetupMatrix(NumPts, Vs)
1346 int NumPts;
1347 DoublePoint *Vs;
1348 {
1349 register int i;
1350 register double val;
1351
1352 mtxInfo.x = (double*)malloc(NumPts*sizeof(double));
1353 mtxInfo.y = (double*)malloc(NumPts*sizeof(double));
1354 mtxInfo.dx = (double*)malloc(NumPts*sizeof(double));
1355 mtxInfo.dy = (double*)malloc(NumPts*sizeof(double));
1356 if (mtxInfo.x == NULL || mtxInfo.y == NULL || mtxInfo.dx == NULL ||
1357 mtxInfo.dy == NULL) {
1358 FailAllocMessage();
1359 }
1360 for (i=0; i < NumPts; i++) {
1361 mtxInfo.x[i] = mtxInfo.dx[i] = ((double)(Vs[i].x))*((double)theSum);
1362 mtxInfo.y[i] = mtxInfo.dy[i] = ((double)(Vs[i].y))*((double)theSum);
1363 }
1364 /* the first NumPts-2 rows have an extra column */
1365 mtxInfo.mtx = (double**)malloc(NumPts*sizeof(double*));
1366 if (mtxInfo.mtx == NULL) FailAllocMessage();
1367 memset(mtxInfo.mtx, 0, NumPts*sizeof(double*));
1368 for (i=0; i < NumPts; i++) {
1369 mtxInfo.mtx[i] = (double*)malloc(4*sizeof(double));
1370 if (mtxInfo.mtx[i] == NULL) FailAllocMessage();
1371 memset(mtxInfo.mtx[i], 0, 4*sizeof(double));
1372 }
1373 mtxInfo.mtx[0][0] = mtxInfo.mtx[NumPts-1][2] = (double)1.0;
1374 mtxInfo.mtx[0][1] = mtxInfo.mtx[NumPts-1][1] = (double)SUM_MINUS_2;
1375 mtxInfo.mtx[0][2] = mtxInfo.mtx[NumPts-1][0] = (double)1.0;
1376 mtxInfo.mtx[0][3] = (double)1.0;
1377 /* use mtx[NumPts-1][3] as mtx[NumPts-1][i] where i is moving to right */
1378 mtxInfo.mtx[NumPts-1][3] = (double)0.0;
1379 for (i=1; i < NumPts-1; i++) {
1380 mtxInfo.mtx[i][0] = (double)1.0;
1381 mtxInfo.mtx[i][1] = (double)SUM_MINUS_2;
1382 mtxInfo.mtx[i][2] = (double)1.0;
1383 mtxInfo.mtx[i][3] = (double)0.0;
1384 }
1385 val = (-mtxInfo.mtx[0][1]);
1386 if (NumPts == 3) {
1387 mtxInfo.mtx[NumPts-1][0] =
1388 (mtxInfo.mtx[NumPts-1][0]*val+mtxInfo.mtx[0][2])/theSum;
1389 } else {
1390 mtxInfo.mtx[NumPts-1][0] = mtxInfo.mtx[NumPts-1][0]*val/theSum;
1391 }
1392 mtxInfo.mtx[NumPts-1][1] =
1393 (mtxInfo.mtx[NumPts-1][1]*val+mtxInfo.mtx[0][3])/theSum;
1394 /* use mtx[NumPts-1][3] as mtx[NumPts-1][i] where i moves to right */
1395 mtxInfo.mtx[NumPts-1][3] = mtxInfo.mtx[0][2]/theSum;
1396 mtxInfo.x[NumPts-1] = (mtxInfo.x[NumPts-1]*val+mtxInfo.x[0])/theSum;
1397 mtxInfo.y[NumPts-1] = (mtxInfo.y[NumPts-1]*val+mtxInfo.y[0])/theSum;
1398 }
1399
1400 static int gaussIteration=0;
1401
1402 #ifdef NOT_DEFINED
1403 #ifdef _TGIF_DBG
1404 static
DebugClosedMatrix(NumPts)1405 void DebugClosedMatrix(NumPts)
1406 int NumPts;
1407 {
1408 int j, i;
1409
1410 /* mtxInfo.mtx[0][3] is actually mtxInfo.mtx[0][NumPts-1] */
1411 /* mtxInfo.mtx[NumPts-1][3] is actually mtxInfo.mtx[NumPts-1][i+1] */
1412 /* where i is the current iteration in gaussian elimincation; */
1413 /* before gaussian() is called, i is 0 */
1414 printf("| %+8.2f %+8.2f ", mtxInfo.mtx[0][1], mtxInfo.mtx[0][2]);
1415 for (j=2; j<NumPts-1; j++) printf(" ");
1416 printf("%+8.2f | (%+8.2f,%+8.2f)\n", mtxInfo.mtx[0][3],
1417 mtxInfo.x[0], mtxInfo.y[0]);
1418 for (i=1; i<NumPts-1; i++) {
1419 if (i == NumPts-2) {
1420 printf("| ");
1421 for (j=1; j<i; j++) printf(" ");
1422 printf("%+8.2f %+8.2f %+8.2f ", mtxInfo.mtx[i][0],
1423 mtxInfo.mtx[i][1], mtxInfo.mtx[i][2]);
1424 for (j=i+2; j<NumPts; j++) printf(" ");
1425 printf("| (%+8.2f,%+8.2f)\n", mtxInfo.x[i], mtxInfo.y[i]);
1426 } else {
1427 printf("| ");
1428 for (j=1; j<i; j++) printf(" ");
1429 printf("%+8.2f %+8.2f %+8.2f ", mtxInfo.mtx[i][0],
1430 mtxInfo.mtx[i][1], mtxInfo.mtx[i][2]);
1431 for (j=i+2; j<NumPts-1; j++) printf(" ");
1432 printf("%+8.2f | (%+8.2f,%+8.2f)\n", mtxInfo.mtx[i][3],
1433 mtxInfo.x[i], mtxInfo.y[i]);
1434 }
1435 }
1436 printf("| ");
1437 if (gaussIteration+2 < i) {
1438 for (j=1; j<gaussIteration+2; j++) printf(" ");
1439 printf("%+8.2f ", mtxInfo.mtx[i][3]);
1440 for (j=gaussIteration+3; j<i; j++) printf(" ");
1441 } else {
1442 for (j=1; j<i; j++) printf(" ");
1443 }
1444 printf("%+8.2f %+8.2f ", mtxInfo.mtx[i][0], mtxInfo.mtx[i][1]);
1445 printf("| (%+8.2f,%+8.2f)\n", mtxInfo.x[i], mtxInfo.y[i]);
1446 }
1447 #endif /* _TGIF_DBG */
1448 #endif /* NOT_DEFINED */
1449
1450 static
Gaussian(NumPts)1451 void Gaussian(NumPts)
1452 int NumPts;
1453 {
1454 register int i;
1455 register double val;
1456
1457 gaussIteration = 0;
1458 #ifdef _TGIF_DBG
1459 /* DebugClosedMatrix(NumPts); */
1460 #endif /* _TGIF_DBG */
1461 for (i=1; i<NumPts-1; i++) {
1462 val = (-mtxInfo.mtx[i-1][1]);
1463 mtxInfo.mtx[i][0] = (double)0.0;
1464 mtxInfo.mtx[i][1] = (mtxInfo.mtx[i][1]*val+mtxInfo.mtx[i-1][2])/theSum;
1465 if (i == NumPts-2) {
1466 mtxInfo.mtx[i][2] = (mtxInfo.mtx[i][2]*val+mtxInfo.mtx[i-1][3])/theSum;
1467 } else {
1468 mtxInfo.mtx[i][2] = val/theSum;
1469 }
1470 mtxInfo.x[i] = (mtxInfo.x[i]*val+mtxInfo.x[i-1])/theSum;
1471 mtxInfo.y[i] = (mtxInfo.y[i]*val+mtxInfo.y[i-1])/theSum;
1472 if (i != NumPts-2) {
1473 mtxInfo.mtx[i][3] = mtxInfo.mtx[i-1][3]/theSum;;
1474 }
1475 val = (-mtxInfo.mtx[i][1])/mtxInfo.mtx[NumPts-1][3];
1476 if (i < NumPts-2) {
1477 if (i < NumPts-3) {
1478 mtxInfo.mtx[NumPts-1][0] = mtxInfo.mtx[NumPts-1][0]*val/theSum;
1479 } else {
1480 mtxInfo.mtx[NumPts-1][0] =
1481 (mtxInfo.mtx[NumPts-1][0]*val+mtxInfo.mtx[i][2])/theSum;
1482 }
1483 mtxInfo.mtx[NumPts-1][1] =
1484 (mtxInfo.mtx[NumPts-1][1]*val+mtxInfo.mtx[i][3])/theSum;
1485 mtxInfo.mtx[NumPts-1][3] = mtxInfo.mtx[i][2]/theSum;
1486 mtxInfo.x[NumPts-1] = (mtxInfo.x[NumPts-1]*val+mtxInfo.x[i])/theSum;
1487 mtxInfo.y[NumPts-1] = (mtxInfo.y[NumPts-1]*val+mtxInfo.y[i])/theSum;
1488 }
1489 gaussIteration++;
1490 #ifdef _TGIF_DBG
1491 /* DebugClosedMatrix(NumPts); */
1492 #endif /* _TGIF_DBG */
1493 }
1494 val = (-mtxInfo.mtx[i-1][1])/mtxInfo.mtx[i][0];
1495 mtxInfo.mtx[i][0] = (double)0.0;
1496 mtxInfo.mtx[i][1] = (mtxInfo.mtx[i][1]*val+mtxInfo.mtx[i-1][2])/theSum;
1497 mtxInfo.x[i] = (mtxInfo.x[i]*val+mtxInfo.x[i-1])/theSum;
1498 mtxInfo.y[i] = (mtxInfo.y[i]*val+mtxInfo.y[i-1])/theSum;
1499
1500 mtxInfo.x[i] = mtxInfo.x[i]/mtxInfo.mtx[i][1];
1501 mtxInfo.y[i] = mtxInfo.y[i]/mtxInfo.mtx[i][1];
1502 for (i--; i>=0; i--) {
1503 if (i == NumPts-2) {
1504 mtxInfo.x[i] = (mtxInfo.x[i]-mtxInfo.x[i+1]*mtxInfo.mtx[i][2]) /
1505 mtxInfo.mtx[i][1];
1506 mtxInfo.y[i] = (mtxInfo.y[i]-mtxInfo.y[i+1]*mtxInfo.mtx[i][2]) /
1507 mtxInfo.mtx[i][1];
1508 } else {
1509 mtxInfo.x[i] = (mtxInfo.x[i]-mtxInfo.x[i+1]*mtxInfo.mtx[i][2] -
1510 mtxInfo.x[NumPts-1]*mtxInfo.mtx[i][3])/mtxInfo.mtx[i][1];
1511 mtxInfo.y[i] = (mtxInfo.y[i]-mtxInfo.y[i+1]*mtxInfo.mtx[i][2] -
1512 mtxInfo.y[NumPts-1]*mtxInfo.mtx[i][3])/mtxInfo.mtx[i][1];
1513 }
1514 }
1515 #ifdef _TGIF_DBG
1516 /* DebugClosedMatrix(NumPts); */
1517 #endif /* _TGIF_DBG */
1518 }
1519
1520 static
ClosedControlPts(NumPts,N)1521 IntPoint *ClosedControlPts(NumPts, N)
1522 int NumPts, *N;
1523 {
1524 register int i;
1525 int index=0;
1526 double half=theSum/((double)2.0);
1527 double weight=half-((double)1.0);
1528 IntPoint *v;
1529
1530 v = (IntPoint*)malloc(((NumPts<<1)+2)*sizeof(IntPoint));
1531 if (v == NULL) FailAllocMessage();
1532 memset(v, 0, ((NumPts<<1)+2)*sizeof(IntPoint));
1533 for (i=0; i<NumPts; i++) {
1534 v[index].x = (int)((weight*mtxInfo.x[i]+mtxInfo.x[(i+1) % NumPts])/half);
1535 v[index].y = (int)((weight*mtxInfo.y[i]+mtxInfo.y[(i+1) % NumPts])/half);
1536 index++;
1537 v[index].x = (int)((mtxInfo.x[i]+weight*mtxInfo.x[(i+1) % NumPts])/half);
1538 v[index].y = (int)((mtxInfo.y[i]+weight*mtxInfo.y[(i+1) % NumPts])/half);
1539 index++;
1540 }
1541 v[index].x = (int)((weight*mtxInfo.x[0]+mtxInfo.x[1])/half);
1542 v[index].y = (int)((weight*mtxInfo.y[0]+mtxInfo.y[1])/half);
1543 index++;
1544
1545 FreeMtxInfo(NumPts);
1546
1547 *N = index;
1548 return v;
1549 }
1550
1551 static
DoubleClosedControlPts(NumPts,N)1552 DoublePoint *DoubleClosedControlPts(NumPts, N)
1553 int NumPts, *N;
1554 {
1555 register int i;
1556 int index=0;
1557 double half=theSum/((double)2.0);
1558 double weight=half-((double)1.0);
1559 DoublePoint *v;
1560
1561 v = (DoublePoint*)malloc(((NumPts<<1)+2)*sizeof(DoublePoint));
1562 if (v == NULL) FailAllocMessage();
1563 memset(v, 0, ((NumPts<<1)+2)*sizeof(DoublePoint));
1564 for (i=0; i<NumPts; i++) {
1565 v[index].x = ((weight*mtxInfo.x[i]+mtxInfo.x[(i+1) % NumPts])/half);
1566 v[index].y = ((weight*mtxInfo.y[i]+mtxInfo.y[(i+1) % NumPts])/half);
1567 index++;
1568 v[index].x = ((mtxInfo.x[i]+weight*mtxInfo.x[(i+1) % NumPts])/half);
1569 v[index].y = ((mtxInfo.y[i]+weight*mtxInfo.y[(i+1) % NumPts])/half);
1570 index++;
1571 }
1572 v[index].x = ((weight*mtxInfo.x[0]+mtxInfo.x[1])/half);
1573 v[index].y = ((weight*mtxInfo.y[0]+mtxInfo.y[1])/half);
1574 index++;
1575
1576 FreeMtxInfo(NumPts);
1577
1578 *N = index;
1579 return v;
1580 }
1581
MakeIntSplinePolygonVertex(N,CntrlN,CntrlVs,XOff,YOff,NumVs,Vs)1582 XPoint *MakeIntSplinePolygonVertex(N, CntrlN, CntrlVs, XOff, YOff, NumVs, Vs)
1583 int *N, *CntrlN, XOff, YOff, NumVs;
1584 IntPoint **CntrlVs, *Vs;
1585 {
1586 int x_off, y_off;
1587
1588 x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
1589 y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
1590
1591 splineVs = NULL;
1592
1593 if (NumVs <= 3) {
1594 splineVs = (XPoint *)malloc(5*sizeof(XPoint));
1595 if (splineVs == NULL) {
1596 FailAllocMessage();
1597 *N = 0;
1598 return (splineVs);
1599 }
1600 memset(splineVs, 0, 5*sizeof(XPoint));
1601 splineVs[0].x = ZOOMED_SIZE(Vs[0].x-x_off);
1602 splineVs[0].y = ZOOMED_SIZE(Vs[0].y-y_off);
1603 splineVs[1].x = ZOOMED_SIZE(Vs[1].x-x_off);
1604 splineVs[1].y = ZOOMED_SIZE(Vs[1].y-y_off);
1605 *N = *CntrlN = 2;
1606 return splineVs;
1607 }
1608 gaussIteration = 0;
1609 NumVs--; /* drop the duplicated end point */
1610 ClosedSetupMatrix(NumVs, Vs);
1611 Gaussian(NumVs);
1612 *CntrlVs = ClosedControlPts(NumVs, CntrlN);
1613
1614 return MakeSplinePolygonVertex(0, LT_INTSPLINE, N, XOff, YOff, *CntrlN,
1615 *CntrlVs);
1616 }
1617
MakeDoubleIntSplinePolygonVertex(N,CntrlN,CntrlVs,XOff,YOff,NumVs,Vs)1618 XPoint *MakeDoubleIntSplinePolygonVertex(N, CntrlN, CntrlVs, XOff, YOff,
1619 NumVs, Vs)
1620 int *N, *CntrlN, XOff, YOff, NumVs;
1621 DoublePoint **CntrlVs, *Vs;
1622 {
1623 int x_off=0, y_off=0;
1624 int saved_tighter_splines=tighterStructSplines;
1625 XPoint *pxp=NULL;
1626
1627 x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
1628 y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
1629
1630 splineVs = NULL;
1631
1632 if (NumVs <= 3) {
1633 double x, y;
1634
1635 splineVs = (XPoint *)malloc(5*sizeof(XPoint));
1636 if (splineVs == NULL) {
1637 FailAllocMessage();
1638 *N = 0;
1639 return splineVs;
1640 }
1641 memset(splineVs, 0, 5*sizeof(XPoint));
1642 x = ZOOMED_DOUBLE_SIZE(Vs[0].x-((double)x_off));
1643 y = ZOOMED_DOUBLE_SIZE(Vs[0].y-((double)y_off));
1644 splineVs[0].x = round(x);
1645 splineVs[0].y = round(y);
1646 x = ZOOMED_DOUBLE_SIZE(Vs[1].x-((double)x_off));
1647 y = ZOOMED_DOUBLE_SIZE(Vs[1].y-((double)y_off));
1648 splineVs[1].x = round(x);
1649 splineVs[1].y = round(y);
1650 *N = *CntrlN = 2;
1651 return splineVs;
1652 }
1653 gaussIteration = 0;
1654 NumVs--; /* drop the duplicated end point */
1655 DoubleClosedSetupMatrix(NumVs, Vs);
1656 Gaussian(NumVs);
1657 *CntrlVs = DoubleClosedControlPts(NumVs, CntrlN);
1658
1659 if (saved_tighter_splines) {
1660 tighterStructSplines = FALSE;
1661 }
1662 pxp = DoMakeDoubleIntSplinePolygonVertex(N, XOff, YOff, *CntrlN, *CntrlVs);
1663 tighterStructSplines = saved_tighter_splines;
1664
1665 return pxp;
1666 }
1667
DumpCurvedPolyPoints(FP,Curved,NumPts,V,Indent)1668 void DumpCurvedPolyPoints(FP, Curved, NumPts, V, Indent)
1669 FILE *FP;
1670 int Curved, NumPts, Indent;
1671 register IntPoint *V;
1672 {
1673 register int j, i;
1674 double x1, y1, x2, y2;
1675 double mx1, my1, mx2, my2, mx3, my3, mx4, my4;
1676 int saved_tighter_splines=tighterStructSplines;
1677
1678 if (Curved != LT_STRUCT_SPLINE && saved_tighter_splines) {
1679 tighterStructSplines = FALSE;
1680 }
1681 switch (NumPts) {
1682 case 0:
1683 case 1:
1684 case 2:
1685 break;
1686 case 3:
1687 mx1 = V->x; my1 = (V++)->y;
1688 x1 = V->x; y1 = (V++)->y;
1689 x2 = V->x; y2 = (V++)->y;
1690 mx2 = compCurveToFactor*mx1 + curveToFactor*x1;
1691 my2 = compCurveToFactor*my1 + curveToFactor*y1;
1692 mx3 = curveToFactor*x1 + compCurveToFactor*x2;
1693 my3 = curveToFactor*y1 + compCurveToFactor*y2;
1694 for (j = 0; j < Indent; j++) fprintf(FP, " ");
1695 fprintf(FP, "%.2f %.2f %.2f %.2f\n", mx2, my2, mx3, my3);
1696 break;
1697 default:
1698 if (tighterStructSplines) {
1699 #ifdef _TGIF_DBG /* debug, do not translate */
1700 TgAssert(NumPts <= 4, "NumPts > 4 in DumpCurvedPolyPoints()", NULL);
1701 #endif /* _TGIF_DBG */
1702 mx1 = V->x; my1 = (V++)->y;
1703 x1 = V->x; y1 = (V++)->y;
1704 x2 = V->x; y2 = (V++)->y;
1705 mx4 = V->x; my4 = V->y;
1706 for (j = 0; j < Indent; j++) fprintf(FP, " ");
1707 fprintf(FP, "%.2f %.2f %.2f %.2f\n", x1, y1, x2, y2);
1708 } else {
1709 mx1 = V->x; my1 = (V++)->y;
1710 x1 = V->x; y1 = (V++)->y;
1711 x2 = V->x; y2 = (V++)->y;
1712 mx2 = (mx1 + 2.0*x1) / 3.0; my2 = (my1 + 2.0*y1) / 3.0;
1713 mx3 = (5.0*x1 + x2) / 6.0; my3 = (5.0*y1 + y2) / 6.0;
1714 mx4 = (x1 + x2) / 2.0; my4 = (y1 + y2) / 2.0;
1715 for (j = 0; j < Indent; j++) fprintf(FP, " ");
1716 fprintf(FP, "%.2f %.2f %.2f %.2f %.2f %.2f %s\n",
1717 mx2, my2, mx3, my3, mx4, my4, gPsCmd[PS_CURVETO]);
1718
1719 for (i=2; i < NumPts-2; i++, V++) {
1720 mx2 = (x1 + 5.0*x2) / 6.0; my2 = (y1 + 5.0*y2) / 6.0;
1721 x1 = x2; y1 = y2;
1722 #ifdef stellar
1723 mx3 = (5.0*x1 + V->x) / 6.0; my3 = (5.0*y1 + V->y) / 6.0;
1724 mx4 = (x1 + V->x) / 2.0; my4 = (y1 + V->y) / 2.0;
1725 #else
1726 x2 = V->x; y2 = V->y;
1727 mx3 = (5.0*x1 + x2) / 6.0; my3 = (5.0*y1 + y2) / 6.0;
1728 mx4 = (x1 + x2) / 2.0; my4 = (y1 + y2) / 2.0;
1729 #endif
1730 for (j = 0; j < Indent; j++) fprintf(FP, " ");
1731 fprintf(FP, "%.2f %.2f %.2f %.2f %.2f %.2f %s\n",
1732 mx2, my2, mx3, my3, mx4, my4, gPsCmd[PS_CURVETO]);
1733 #ifdef stellar
1734 x2 = V->x; y2 = V->y;
1735 #endif
1736 }
1737 mx2 = (x1 + 5.0*x2) / 6.0; my2 = (y1 + 5.0*y2) / 6.0;
1738 x1 = x2; y1 = y2;
1739 mx3 = (2.0*x1 + V->x) / 3.0; my3 = (2.0*y1 + V->y) / 3.0;
1740 for (j = 0; j < Indent; j++) fprintf(FP, " ");
1741 fprintf(FP, "%.2f %.2f %.2f %.2f\n", mx2, my2, mx3, my3);
1742 }
1743 break;
1744 }
1745 tighterStructSplines = saved_tighter_splines;
1746 }
1747
DumpCurvedPolygonPoints(FP,Curved,NumPts,V,Indent)1748 void DumpCurvedPolygonPoints(FP, Curved, NumPts, V, Indent)
1749 FILE *FP;
1750 int Curved, NumPts, Indent;
1751 register IntPoint *V;
1752 {
1753 register int j;
1754 double mx2, my2, mx3, my3, mx4, my4, x1, y1, x2, y2;
1755 int i;
1756 int saved_tighter_splines=tighterStructSplines;
1757
1758 if (Curved != LT_STRUCT_SPLINE && saved_tighter_splines) {
1759 tighterStructSplines = FALSE;
1760 }
1761 V[NumPts].x = V[1].x; V[NumPts].y = V[1].y;
1762 x1 = V->x; y1 = (V++)->y;
1763 x2 = V->x; y2 = (V++)->y;
1764 mx4 = (x1 + x2) / 2.0; my4 = (y1 + y2) / 2.0;
1765 for (j = 0; j < Indent; j++) fprintf(FP, " ");
1766 fprintf(FP, "%.2f %.2f %s\n", mx4, my4, gPsCmd[PS_MOVETO]);
1767
1768 for (i=1; i < NumPts; i++, V++) {
1769 mx2 = (x1+5.0*x2)/6.0; my2 = (y1+5.0*y2)/6.0;
1770 x1 = x2; y1 = y2;
1771 #ifdef stellar
1772 mx3 = (5.0*x1+V->x)/6.0; my3 = (5.0*y1+V->y)/6.0;
1773 mx4 = (x1+V->x)/2.0; my4 = (y1+V->y)/2.0;
1774 #else
1775 x2 = V->x; y2 = V->y;
1776 mx3 = (5.0*x1+x2)/6.0; my3 = (5.0*y1+y2)/6.0;
1777 mx4 = (x1+x2)/2.0; my4 = (y1+y2)/2.0;
1778 #endif
1779 for (j = 0; j < Indent; j++) fprintf(FP, " ");
1780 fprintf(FP, "%.2f %.2f %.2f %.2f %.2f %.2f %s\n",
1781 mx2, my2, mx3, my3, mx4, my4, gPsCmd[PS_CURVETO]);
1782 #ifdef stellar
1783 x2 = V->x; y2 = V->y;
1784 #endif
1785 }
1786 tighterStructSplines = saved_tighter_splines;
1787 }
1788
DumpMultiCurvedPolyPoints(FP,Smooth,Style,Curved,NumPts,V,Indent)1789 void DumpMultiCurvedPolyPoints(FP, Smooth, Style, Curved, NumPts, V, Indent)
1790 FILE *FP;
1791 char *Smooth;
1792 int Style, Curved, NumPts, Indent;
1793 register IntPoint *V;
1794 {
1795 register int i, j;
1796 int segments=1, has_smooth_point=FALSE, start_index;
1797
1798 if (Curved == LT_INTSPLINE || Smooth == NULL) {
1799 DumpCurvedPolyPoints(FP, Curved, NumPts, V, Indent);
1800 return;
1801 }
1802 if (Smooth[0] || Smooth[NumPts-1]) {
1803 FatalUnexpectedError(
1804 TgLoadCachedString(CSTID_CORRUPTED_POLY_DMPMULTICURVE),
1805 TgLoadCachedString(CSTID_FIX_ATTEMPTED));
1806 Smooth[0] = Smooth[NumPts-1] = FALSE;
1807 }
1808 for (i=1; i < NumPts-1; i++) {
1809 if (Smooth[i]) {
1810 has_smooth_point = TRUE;
1811 } else {
1812 segments++;
1813 }
1814 }
1815 if (!has_smooth_point) {
1816 /* simple polyline */
1817 if (Style & LS_RIGHT) {
1818 DumpPoints(FP, NumPts-1, V, Indent);
1819 } else {
1820 DumpPoints(FP, NumPts, V, Indent);
1821 }
1822 return;
1823 }
1824 if (segments == 1) {
1825 /* simple spline */
1826 if (Style & LS_RIGHT) {
1827 if (NumPts != 2) {
1828 DumpCurvedPolyPoints(FP, Curved, NumPts, V, Indent);
1829 } else {
1830 DumpPoints(FP, NumPts-1, V, Indent);
1831 }
1832 } else if (NumPts != 2) {
1833 DumpCurvedPolyPoints(FP, Curved, NumPts, V, Indent);
1834 for (i=0; i < Indent; i++) fprintf(FP, " ");
1835 fprintf(FP, "%1d %1d %s\n", V[NumPts-1].x, V[NumPts-1].y,
1836 gPsCmd[PS_CURVETO]);
1837 } else {
1838 DumpPoints(FP, NumPts, V, Indent);
1839 }
1840 return;
1841 }
1842 start_index = 0;
1843 for (i=1; i <= NumPts-1; i++) {
1844 if (!Smooth[i]) {
1845 int num_tmp_vs=i-start_index+1;
1846
1847 if (num_tmp_vs == 2) {
1848 if (!(i == NumPts-1 && (Style & LS_RIGHT))) {
1849 DumpPoints(FP, num_tmp_vs, &V[start_index], Indent);
1850 }
1851 } else {
1852 DumpCurvedPolyPoints(FP, Curved, num_tmp_vs, &V[start_index],
1853 Indent);
1854 if (!(i == NumPts-1 && (Style & LS_RIGHT))) {
1855 for (j=0; j < Indent; j++) fprintf(FP, " ");
1856 fprintf(FP, "%1d %1d %s\n", V[i].x, V[i].y, gPsCmd[PS_CURVETO]);
1857 }
1858 }
1859 start_index = i;
1860 }
1861 }
1862 }
1863
DumpMultiCurvedPolygonPoints(FP,Smooth,Curved,NumPts,V,Indent)1864 void DumpMultiCurvedPolygonPoints(FP, Smooth, Curved, NumPts, V, Indent)
1865 FILE *FP;
1866 char *Smooth;
1867 int Curved, NumPts, Indent;
1868 register IntPoint *V;
1869 {
1870 register int i, j;
1871 int num_smooth_points=0, num_hinge_points=0, tmp_index;
1872 int start_index, once_around=FALSE;
1873 IntPoint *tmp_vs=NULL;
1874
1875 if (Curved == LT_INTSPLINE || Smooth == NULL) {
1876 DumpCurvedPolygonPoints(FP, Curved, NumPts, V, Indent);
1877 return;
1878 }
1879 for (i=1; i < NumPts; i++) {
1880 if (Smooth[i]) {
1881 num_smooth_points++;
1882 } else {
1883 num_hinge_points++;
1884 }
1885 }
1886 if (num_smooth_points == 0) {
1887 /* simple polygon */
1888 for (j=0; j < Indent; j++) fprintf(FP, " ");
1889 fprintf(FP, "%1d %1d %s\n", V[0].x, V[0].y, gPsCmd[PS_MOVETO]);
1890 DumpPoints(FP, NumPts-1, V, Indent);
1891 return;
1892 }
1893 if (num_hinge_points == 0) {
1894 DumpCurvedPolygonPoints(FP, Curved, NumPts, V, Indent);
1895 return;
1896 }
1897 tmp_vs = (IntPoint*)malloc((NumPts+1)*sizeof(IntPoint));
1898 if (tmp_vs == NULL) FailAllocMessage();
1899 memset(tmp_vs, 0, (NumPts+1)*sizeof(IntPoint));
1900
1901 for (i=0; i < NumPts; i++) {
1902 if (!Smooth[i]) {
1903 break;
1904 }
1905 }
1906 for (j=0; j < Indent; j++) fprintf(FP, " ");
1907 fprintf(FP, "%1d %1d %s\n", V[i].x, V[i].y, gPsCmd[PS_MOVETO]);
1908 start_index = i;
1909 tmp_vs[0].x = V[start_index].x;
1910 tmp_vs[0].y = V[start_index].y;
1911 tmp_index = 1;
1912 for (i=start_index+1; !(once_around && i==start_index+1); i++, tmp_index++) {
1913 tmp_vs[tmp_index].x = V[i].x;
1914 tmp_vs[tmp_index].y = V[i].y;
1915 if (!Smooth[i]) {
1916 if (tmp_index == 1) {
1917 DumpPoints(FP, tmp_index+1, tmp_vs, Indent);
1918 } else {
1919 DumpCurvedPolyPoints(FP, Curved, tmp_index+1, tmp_vs, Indent);
1920 for (j=0; j < Indent; j++) fprintf(FP, " ");
1921 fprintf(FP, "%1d %1d %s\n", V[i].x, V[i].y, gPsCmd[PS_CURVETO]);
1922 }
1923 start_index = (i==NumPts-1 ? 0 : i);
1924 tmp_vs[0].x = V[start_index].x;
1925 tmp_vs[0].y = V[start_index].y;
1926 tmp_index = 0;
1927 }
1928 if (i == NumPts-1) {
1929 i = 0;
1930 once_around = TRUE;
1931 }
1932 }
1933 if (tmp_vs != NULL) free(tmp_vs);
1934 }
1935
1936