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