1 /*
2 * mapLines.c --
3 *
4 * This file defines functions that manage maplines and maplinearrays.
5 * See the user documentation for more information.
6 *
7 * Copyright (c) 2004 Gordon D. Carrie. All rights reserved.
8 *
9 * Licensed under the Open Software License version 2.1
10 *
11 * Please address questions and feedback to user0@tkgeomap.org
12 *
13 * @(#) $Id: mapLines.c,v 1.7 2007/06/26 21:49:30 tkgeomap Exp $
14 *
15 ********************************************
16 *
17 */
18
19 #include "mapLines.h"
20
21 /*
22 * Local function declaration.
23 */
24
25 static void lnInit _ANSI_ARGS_((struct MapLn *mapLnPtr));
26
27 /*
28 *----------------------------------------------------------------------
29 *
30 * MapLnCreate --
31 *
32 * This procedure creates and initializes a new geoline.
33 *
34 * Results:
35 * See the user documentation.
36 *
37 * Side effects:
38 * See the user documentation.
39 *
40 *----------------------------------------------------------------------
41 */
42
43 MapLn
MapLnCreate(nPtsMax)44 MapLnCreate(nPtsMax)
45 unsigned nPtsMax;
46 {
47 struct MapLn *mapLnPtr; /* Return value */
48
49 mapLnPtr = (MapLn)CKALLOC(sizeof(*mapLnPtr));
50 lnInit(mapLnPtr);
51 if (nPtsMax == 0) {
52 return mapLnPtr;
53 }
54 mapLnPtr->pts = (MapPt *)CKALLOC(nPtsMax * sizeof(MapPt));
55 mapLnPtr->nPtsMax = nPtsMax;
56 return mapLnPtr;
57 }
58
59 /*
60 *----------------------------------------------------------------------
61 *
62 * lnInit --
63 *
64 * This procedure initializes a new geoline.
65 *
66 * Results:
67 * None.
68 *
69 * Side effects:
70 * The contents of a MapLn structure are set. The previous contents,
71 * which are assumed to be garbage, are ignored.
72 *
73 *----------------------------------------------------------------------
74 */
75
76 static void
lnInit(mapLnPtr)77 lnInit(mapLnPtr)
78 struct MapLn *mapLnPtr;
79 {
80 mapLnPtr->nPts = mapLnPtr->nPtsMax = 0;
81 mapLnPtr->ordMax = mapLnPtr->absMax = -FLT_MAX;
82 mapLnPtr->ordMin = mapLnPtr->absMin = FLT_MAX;
83 mapLnPtr->pts = NULL; /* Assumes previous value is garbage */
84 }
85
86 /*
87 *----------------------------------------------------------------------
88 *
89 * MapLnClear --
90 *
91 * This procedure set the number of points in a geoline to zero without
92 * releasing its internal storage.
93 *
94 * Results:
95 * None.
96 *
97 * Side effects:
98 * See the user documentation.
99 *
100 *----------------------------------------------------------------------
101 */
102
103 void
MapLnClear(mapLnPtr)104 MapLnClear(mapLnPtr)
105 struct MapLn *mapLnPtr;
106 {
107 /* Reset a Line without changing its memory allocation */
108 mapLnPtr->nPts = 0;
109 mapLnPtr->ordMax = mapLnPtr->absMax = -FLT_MAX;
110 mapLnPtr->ordMin = mapLnPtr->absMin = FLT_MAX;
111 }
112
113 /*
114 *----------------------------------------------------------------------
115 *
116 * MapLnDestroy --
117 *
118 * This procedure frees internal storage in a MapLn structure, and
119 * frees the structure.
120 *
121 * Results:
122 * None.
123 *
124 * Side effects:
125 * See the user documentation.
126 *
127 *----------------------------------------------------------------------
128 */
129
130 void
MapLnDestroy(mapLnPtr)131 MapLnDestroy(mapLnPtr)
132 struct MapLn *mapLnPtr;
133 {
134 /* Free storage associated with mapLnPtr and then free the mapLnPtr */
135 if (!mapLnPtr) {
136 return;
137 }
138 CKFREE((char *)mapLnPtr->pts);
139 CKFREE((char *)mapLnPtr);
140 }
141
142 /*
143 *----------------------------------------------------------------------
144 *
145 * MapLnSetAlloc --
146 *
147 * This procedure changes the number of points a mapline can store.
148 *
149 * Results:
150 * None.
151 *
152 * Side effects:
153 * This procedure reallocates a MapLn structure's internal storage.
154 * If the number of points is reduced, the geoline's maxima and minima
155 * are recomputed.
156 *
157 *----------------------------------------------------------------------
158 */
159
160 void
MapLnSetAlloc(mapLnPtr,nPtsMax)161 MapLnSetAlloc(mapLnPtr, nPtsMax)
162 struct MapLn *mapLnPtr;
163 unsigned nPtsMax;
164 {
165 /*
166 * Set mapLnPtr->nPtsMax to nPtsMax. Returns 1 on success or 0 on failure
167 * (if reallocation is required and fails).
168 * If mapLnPtr has more points than nPtsMax, the excess points are lost.
169 */
170
171 if (mapLnPtr->nPtsMax == nPtsMax) {
172 return;
173 }
174 if (nPtsMax == 0) {
175 CKFREE((char *)mapLnPtr->pts);
176 lnInit(mapLnPtr);
177 return;
178 }
179 mapLnPtr->pts
180 = (MapPt *)CKREALLOC((char *)mapLnPtr->pts, nPtsMax * sizeof(MapPt));
181 mapLnPtr->nPtsMax = nPtsMax;
182 if (mapLnPtr->nPts > mapLnPtr->nPtsMax) {
183 /*
184 * If line is shrinking, reset nPts and recompute maxima and minima.
185 */
186
187 MapPt *p, *ep;
188
189 mapLnPtr->nPts = mapLnPtr->nPtsMax;
190 for (p = mapLnPtr->pts, ep = mapLnPtr->pts + mapLnPtr->nPts; p < ep;
191 p++) {
192 mapLnPtr->absMax
193 = (mapLnPtr->absMax > p->abs) ? mapLnPtr->absMax : p->abs;
194 mapLnPtr->absMin
195 = (mapLnPtr->absMin < p->abs) ? mapLnPtr->absMin : p->abs;
196 mapLnPtr->ordMax
197 = (mapLnPtr->ordMax > p->ord) ? mapLnPtr->ordMax : p->ord;
198 mapLnPtr->ordMin
199 = (mapLnPtr->ordMin < p->ord) ? mapLnPtr->ordMin : p->ord;
200 }
201 }
202 }
203
204 /*
205 *----------------------------------------------------------------------
206 *
207 * MapLnAddPt --
208 *
209 * This procedure adds a point to a mapline.
210 *
211 * Results:
212 * None.
213 *
214 * Side effects:
215 * The mapline's allocation might increase. It's maxima and minima will
216 * be adjusted.
217 *
218 *----------------------------------------------------------------------
219 */
220
221 void
MapLnAddPt(p,mapLnPtr)222 MapLnAddPt(p, mapLnPtr)
223 MapPt p;
224 struct MapLn *mapLnPtr;
225 {
226 if (mapLnPtr->nPts + 1 > mapLnPtr->nPtsMax) {
227 MapLnSetAlloc(mapLnPtr, ((mapLnPtr->nPtsMax + 4) * 5) / 4);
228 }
229 mapLnPtr->absMin = (mapLnPtr->absMin < p.abs) ? mapLnPtr->absMin : p.abs;
230 mapLnPtr->absMax = (mapLnPtr->absMax > p.abs) ? mapLnPtr->absMax : p.abs;
231 mapLnPtr->ordMin = (mapLnPtr->ordMin < p.ord) ? mapLnPtr->ordMin : p.ord;
232 mapLnPtr->ordMax = (mapLnPtr->ordMax > p.ord) ? mapLnPtr->ordMax : p.ord;
233 mapLnPtr->pts[mapLnPtr->nPts] = p;
234 mapLnPtr->nPts++;
235 }
236
237 /*
238 *----------------------------------------------------------------------
239 *
240 * MapLnGetPt --
241 *
242 * This procedure retrieve a map-point from a mapline.
243 *
244 * Results:
245 * See the user documentation.
246 *
247 * Side effects:
248 * None.
249 *
250 *----------------------------------------------------------------------
251 */
252
253 MapPt
MapLnGetPt(mapLnPtr,n)254 MapLnGetPt(mapLnPtr, n)
255 struct MapLn *mapLnPtr;
256 unsigned n;
257 {
258 return (n < mapLnPtr->nPts) ? *(mapLnPtr->pts + n) : MapPtNowhere();
259 }
260
261 /*
262 *----------------------------------------------------------------------
263 *
264 * MapLnArrCreate --
265 *
266 * This procedure creates and initializes an new maplinearray.
267 *
268 * Results:
269 * See the user documentation.
270 *
271 * Side effects:
272 * See the user documentation.
273 *
274 *----------------------------------------------------------------------
275 */
276
277 MapLnArr
MapLnArrCreate(nLinesMax)278 MapLnArrCreate(nLinesMax)
279 unsigned nLinesMax;
280 {
281 struct MapLnArr *mapLnArrPtr;
282 int n;
283
284 mapLnArrPtr = (MapLnArr)CKALLOC(sizeof(*mapLnArrPtr));
285 mapLnArrPtr->descr = NULL;
286 mapLnArrPtr->lines = NULL;
287 MapLnArrSetDescr(mapLnArrPtr, "");
288 mapLnArrPtr->nLines = mapLnArrPtr->nLinesMax = 0;
289 mapLnArrPtr->nPts = mapLnArrPtr->nMax = 0;
290 mapLnArrPtr->ordMax = mapLnArrPtr->absMax = -FLT_MAX;
291 mapLnArrPtr->ordMin = mapLnArrPtr->absMin = FLT_MAX;
292 mapLnArrPtr->proj = NULL;
293 if (nLinesMax == 0) {
294 return mapLnArrPtr;
295 }
296 mapLnArrPtr->lines = (MapLn *)CKALLOC(nLinesMax * sizeof(MapLn));
297 mapLnArrPtr->nLinesMax = nLinesMax;
298 for (n = 0; n < nLinesMax; n++) {
299 mapLnArrPtr->lines[n] = NULL;
300 }
301
302 return mapLnArrPtr;
303 }
304
305 /*
306 *----------------------------------------------------------------------
307 *
308 * MapLnArrDestroy --
309 *
310 * This procedure frees internal storage in a maplinearray and frees the
311 * maplinearray.
312 *
313 * Results:
314 * None.
315 *
316 * Side effects:
317 * See the user documentation.
318 *
319 *----------------------------------------------------------------------
320 */
321
322 void
MapLnArrDestroy(mapLnArrPtr)323 MapLnArrDestroy(mapLnArrPtr)
324 struct MapLnArr *mapLnArrPtr;
325 {
326 int n;
327
328 if ( !mapLnArrPtr ) {
329 return;
330 }
331 for (n = 0; n < mapLnArrPtr->nLines; n++) {
332 MapLnDestroy(mapLnArrPtr->lines[n]);
333 }
334 CKFREE((char *)mapLnArrPtr->lines);
335 CKFREE((char *)mapLnArrPtr->descr);
336 CKFREE((char *)mapLnArrPtr);
337 }
338
339 /*
340 *----------------------------------------------------------------------
341 *
342 * MapLnArrSetDescr --
343 *
344 * This procedure sets the descriptor for a maplinearray.
345 *
346 * Results:
347 * None.
348 *
349 * Side effects:
350 * See the user documentation.
351 *
352 *----------------------------------------------------------------------
353 */
354
355 void
MapLnArrSetDescr(mapLnArrPtr,descr)356 MapLnArrSetDescr(mapLnArrPtr, descr)
357 struct MapLnArr *mapLnArrPtr;
358 CONST char *descr;
359 {
360 mapLnArrPtr->descr = CKREALLOC(mapLnArrPtr->descr, strlen(descr) + 1);
361 strcpy(mapLnArrPtr->descr, descr);
362 }
363
364 /*
365 *----------------------------------------------------------------------
366 *
367 * MapLnArrSetAlloc --
368 *
369 * This procedure changes the number of maplines a maplinearray can store.
370 *
371 * Results:
372 * None.
373 *
374 * Side effects:
375 * See the user documentation.
376 *
377 *----------------------------------------------------------------------
378 */
379
380 void
MapLnArrSetAlloc(mapLnArrPtr,nLinesMax)381 MapLnArrSetAlloc(mapLnArrPtr, nLinesMax)
382 struct MapLnArr *mapLnArrPtr;
383 unsigned nLinesMax;
384 {
385 int n; /* Loop index */
386
387 if (mapLnArrPtr->nLinesMax == nLinesMax) {
388 return;
389 }
390
391 /*
392 * If number of lines decreases, free excess lines
393 */
394
395 for (n = nLinesMax; n < mapLnArrPtr->nLinesMax; n++) {
396 MapLnDestroy(mapLnArrPtr->lines[n]);
397 }
398
399 /*
400 * Reallocate
401 */
402
403 mapLnArrPtr->lines = (MapLn *)CKREALLOC((char *)mapLnArrPtr->lines,
404 nLinesMax * sizeof(MapLn));
405 mapLnArrPtr->nLinesMax = nLinesMax;
406
407 /*
408 * Initialize new lines
409 */
410
411 for (n = mapLnArrPtr->nLines; n < mapLnArrPtr->nLinesMax; n++) {
412 mapLnArrPtr->lines[n] = NULL;
413 }
414 }
415
416 /*
417 *----------------------------------------------------------------------
418 *
419 * MapLnArrSet --
420 *
421 * This procedure is used to store the geolinearray, projection
422 * that produced a maplinearray.
423 *
424 * Results:
425 * None.
426 *
427 * Side effects:
428 * See the user documentation.
429 *
430 *----------------------------------------------------------------------
431 */
432
433 void
MapLnArrSet(mapLnArrPtr,geoLnArr,proj)434 MapLnArrSet(mapLnArrPtr, geoLnArr, proj)
435 struct MapLnArr *mapLnArrPtr;
436 GeoLnArr geoLnArr;
437 GeoProj proj;
438 {
439 mapLnArrPtr->geoLnArr = geoLnArr;
440 mapLnArrPtr->proj = proj;
441 }
442
443 /*
444 *----------------------------------------------------------------------
445 *
446 * MapLnArrAddLine --
447 *
448 * This procedure copies a mapline onto the end of a maplinearray.
449 *
450 * Results:
451 * None.
452 *
453 * Side effects:
454 * See the user documentation.
455 *
456 *----------------------------------------------------------------------
457 */
458
459 void
MapLnArrAddLine(mapLnPtr,mapLnArrPtr)460 MapLnArrAddLine(mapLnPtr, mapLnArrPtr)
461 struct MapLn *mapLnPtr;
462 struct MapLnArr *mapLnArrPtr;
463 {
464 int nLines; /* Initial number of lines in mapLnArrPtr */
465
466 /*
467 * If mapLnArrPtr needs more space in its allocation, grow it by 25%
468 */
469
470 nLines = mapLnArrPtr->nLines;
471 if (nLines + 1 > mapLnArrPtr->nLinesMax) {
472 MapLnArrSetAlloc(mapLnArrPtr, ((mapLnArrPtr->nLinesMax + 4) * 5) / 4);
473 }
474
475 /*
476 * Update information and add copy of mapLnPtr to array
477 */
478
479 mapLnArrPtr->lines[nLines] = MapLnCreate(mapLnPtr->nPts);
480 mapLnArrPtr->nPts += mapLnPtr->nPts;
481 mapLnArrPtr->nMax = (mapLnArrPtr->nMax > mapLnPtr->nPts)
482 ? mapLnArrPtr->nMax : mapLnPtr->nPts;
483 mapLnArrPtr->absMin = (mapLnArrPtr->absMin < mapLnPtr->absMin)
484 ? mapLnArrPtr->absMin : mapLnPtr->absMin;
485 mapLnArrPtr->absMax = (mapLnArrPtr->absMax > mapLnPtr->absMax)
486 ? mapLnArrPtr->absMax : mapLnPtr->absMax;
487 mapLnArrPtr->ordMin = (mapLnArrPtr->ordMin < mapLnPtr->ordMin)
488 ? mapLnArrPtr->ordMin : mapLnPtr->ordMin;
489 mapLnArrPtr->ordMax = (mapLnArrPtr->ordMax > mapLnPtr->ordMax)
490 ? mapLnArrPtr->ordMax : mapLnPtr->ordMax;
491 memcpy(mapLnArrPtr->lines[nLines]->pts, mapLnPtr->pts,
492 mapLnPtr->nPts * sizeof(MapPt));
493 mapLnArrPtr->lines[nLines]->nPts = mapLnPtr->nPts;
494 mapLnArrPtr->lines[nLines]->absMin = mapLnPtr->absMin;
495 mapLnArrPtr->lines[nLines]->absMax = mapLnPtr->absMax;
496 mapLnArrPtr->lines[nLines]->ordMin = mapLnPtr->ordMin;
497 mapLnArrPtr->lines[nLines]->ordMax = mapLnPtr->ordMax;
498 mapLnArrPtr->nLines++;
499 }
500
501 /*
502 *----------------------------------------------------------------------
503 *
504 * MapLnArrPutLine --
505 *
506 * This procedure gives a mapline to a maplinearray.
507 *
508 * Results:
509 * None.
510 *
511 * Side effects:
512 * See the user documentation.
513 *
514 *----------------------------------------------------------------------
515 */
516
517 void
MapLnArrPutLine(mapLnPtr,mapLnArrPtr)518 MapLnArrPutLine(mapLnPtr, mapLnArrPtr)
519 MapLn mapLnPtr;
520 struct MapLnArr *mapLnArrPtr;
521 {
522 int nLines; /* Initial number of lines in mapLnArrPtr */
523
524 /*
525 * If mapLnArrPtr needs more space in its allocation, grow it by 25%
526 */
527
528 nLines = mapLnArrPtr->nLines;
529 if (nLines + 1 > mapLnArrPtr->nLinesMax) {
530 MapLnArrSetAlloc(mapLnArrPtr, ((mapLnArrPtr->nLinesMax + 4) * 5) / 4);
531 }
532
533 /*
534 * Update information and add the line to the array
535 */
536
537 mapLnArrPtr->nPts += mapLnPtr->nPts;
538 mapLnArrPtr->nMax = (mapLnArrPtr->nMax > mapLnPtr->nPts)
539 ? mapLnArrPtr->nMax : mapLnPtr->nPts;
540 mapLnArrPtr->absMin = (mapLnArrPtr->absMin < mapLnPtr->absMin)
541 ? mapLnArrPtr->absMin : mapLnPtr->absMin;
542 mapLnArrPtr->absMax = (mapLnArrPtr->absMax > mapLnPtr->absMax)
543 ? mapLnArrPtr->absMax : mapLnPtr->absMax;
544 mapLnArrPtr->ordMin = (mapLnArrPtr->ordMin < mapLnPtr->ordMin)
545 ? mapLnArrPtr->ordMin : mapLnPtr->ordMin;
546 mapLnArrPtr->ordMax = (mapLnArrPtr->ordMax > mapLnPtr->ordMax)
547 ? mapLnArrPtr->ordMax : mapLnPtr->ordMax;
548 mapLnArrPtr->lines[nLines] = mapLnPtr;
549 mapLnArrPtr->nLines++;
550 }
551
552 /*
553 *----------------------------------------------------------------------
554 *
555 * MapLnArrGetDescr --
556 *
557 * This is a member access function.
558 *
559 * Results:
560 * See the user documentation.
561 *
562 * Side effects:
563 * None.
564 *
565 *----------------------------------------------------------------------
566 */
567
568 char *
MapLnArrGetDescr(mapLnArrPtr)569 MapLnArrGetDescr(mapLnArrPtr)
570 struct MapLnArr *mapLnArrPtr;
571 {
572 return mapLnArrPtr->descr;
573 }
574
575 /*
576 *----------------------------------------------------------------------
577 *
578 * MapLnArrGetLine --
579 *
580 * This procedure retrieves a mapline from a maplinearray.
581 *
582 * Results:
583 * See the user documentation.
584 *
585 * Side effects:
586 * See the user documentation.
587 *
588 *----------------------------------------------------------------------
589 */
590
591 MapLn
MapLnArrGetLine(mapLnArrPtr,n)592 MapLnArrGetLine(mapLnArrPtr, n)
593 struct MapLnArr *mapLnArrPtr;
594 unsigned n;
595 {
596 return (n < mapLnArrPtr->nLines) ? mapLnArrPtr->lines[n] : NULL;
597 }
598