1 /*!
2    \file lib/ogsf/gp.c
3 
4    \brief OGSF library - loading and manipulating point sets (lower level functions)
5 
6    (C) 1999-2008, 2011 by the GRASS Development Team
7 
8    This program is free software under the GNU General Public License
9    (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11    \author Bill Brown USACERL, GMSL/University of Illinois (January 1994)
12    \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
13  */
14 
15 #include <stdlib.h>
16 
17 #include <grass/gis.h>
18 #include <grass/ogsf.h>
19 
20 #define FIRST_SITE_ID 21720
21 
22 static geosite *Site_top = NULL;
23 
24 /*!
25    \brief Get geosite struct
26 
27    \param id point set id
28 
29    \return pointer to geosite struct
30    \return NULL on failure
31  */
gp_get_site(int id)32 geosite *gp_get_site(int id)
33 {
34     geosite *gp;
35 
36     G_debug(5, "gp_get_site(%d)", id);
37 
38     for (gp = Site_top; gp; gp = gp->next) {
39 	if (gp->gsite_id == id) {
40 	    return gp;
41 	}
42     }
43 
44     return NULL;
45 }
46 
47 /*!
48    \brief Get previous geosite struct from list
49 
50    \param id point set id
51 
52    \return pointer to geosite struct
53    \return NULL on failure
54  */
gp_get_prev_site(int id)55 geosite *gp_get_prev_site(int id)
56 {
57     geosite *pp;
58 
59     G_debug(5, "gp_get_prev_site(%d)", id);
60 
61     for (pp = Site_top; pp; pp = pp->next) {
62 	if (pp->gsite_id == id - 1) {
63 	    return (pp);
64 	}
65     }
66 
67     return NULL;
68 }
69 
70 /*!
71    \brief Get number of loaded point sets
72 
73    \return number of point sets
74  */
gp_num_sites(void)75 int gp_num_sites(void)
76 {
77     geosite *gp;
78     int i;
79 
80     for (i = 0, gp = Site_top; gp; gp = gp->next, i++) ;
81 
82     G_debug(5, "gp_num_sites(): n=%d", i);
83 
84     return i;
85 }
86 
87 /*!
88    \brief Get last point set
89 
90    \return pointer to geosite struct
91    \return NULL if no point set is available
92  */
gp_get_last_site(void)93 geosite *gp_get_last_site(void)
94 {
95     geosite *lp;
96 
97     G_debug(5, "gp_get_last_site");
98 
99     if (!Site_top) {
100 	return NULL;
101     }
102 
103     for (lp = Site_top; lp->next; lp = lp->next) ;
104 
105     G_debug(5, " last site id: %d", lp->gsite_id);
106 
107     return lp;
108 }
109 
110 /*!
111    \brief Create new geosite instance and add it to list
112 
113    \return pointer to geosite struct
114    \return NULL on error
115  */
gp_get_new_site(void)116 geosite *gp_get_new_site(void)
117 {
118     geosite *np, *lp;
119 
120     np = (geosite *) G_malloc(sizeof(geosite));	/* G_fatal_error */
121     if (!np) {
122 	return NULL;
123     }
124     G_zero(np, sizeof(geosite));
125 
126     lp = gp_get_last_site();
127     if (lp) {
128 	lp->next = np;
129 	np->gsite_id = lp->gsite_id + 1;
130     }
131     else {
132 	Site_top = np;
133 	np->gsite_id = FIRST_SITE_ID;
134     }
135     np->style = (gvstyle *) G_malloc(sizeof(gvstyle));
136     if (!np->style)
137 	return NULL;
138     G_zero(np->style, sizeof (gvstyle));
139     np->hstyle = (gvstyle *) G_malloc(sizeof(gvstyle));
140     if (!np->hstyle)
141 	return NULL;
142     G_zero(np->hstyle, sizeof (gvstyle));
143 
144     G_debug(5, "gp_get_new_site id=%d", np->gsite_id);
145 
146     return np;
147 }
148 
149 /*!
150    \brief Update drape surfaces
151 
152    Call after surface is deleted
153  */
gp_update_drapesurfs(void)154 void gp_update_drapesurfs(void)
155 {
156     geosite *gp;
157     int i, j;
158 
159     for (gp = Site_top; gp; gp = gp->next) {
160 	if (gp->n_surfs) {
161 	    for (i = 0; i < gp->n_surfs; i++) {
162 		if (gp->drape_surf_id[i]) {
163 		    if (NULL == gs_get_surf(gp->drape_surf_id[i])) {
164 			for (j = i; j < gp->n_surfs - 1; j++) {
165 			    gp->drape_surf_id[j] = gp->drape_surf_id[j + 1];
166 			}
167 
168 			gp->n_surfs = gp->n_surfs - 1;
169 		    }
170 		}
171 	    }
172 	}
173     }
174 
175     return;
176 }
177 
178 /*!
179    \brief Set default value for geosite struct
180 
181    \param gp pointer to geosite struct
182 
183    \return 1 on success
184    \return -1 on failure
185  */
gp_set_defaults(geosite * gp)186 int gp_set_defaults(geosite * gp)
187 {
188     float dim;
189 
190     if (!gp) {
191 	return -1;
192     }
193     G_debug(5, "gp_set_defaults() id=%d", gp->gsite_id);
194 
195     GS_get_longdim(&dim);
196 
197     gp->style->color = 0xF0F0F0;
198     gp->style->size = dim / 100.;
199     gp->style->width = 1;
200     gp->style->symbol = ST_X;
201     gp->hstyle->color = 0xFF0000;
202     gp->hstyle->size = dim / 150.;
203     gp->hstyle->symbol = ST_X;
204     gp->tstyle = NULL;
205 
206     return 1;
207 }
208 
209 /*!
210    \brief Initialize geosite struct
211 
212    \todo Currently does nothing
213 
214    \param gp pointer to geosite struct
215 
216    \return -1 on failure
217    \return 0 on success
218  */
gp_init_site(geosite * gp)219 int gp_init_site(geosite * gp)
220 {
221     G_debug(5, "gp_init_site");
222 
223     if (!gp) {
224 	return -1;
225     }
226 
227     return 0;
228 }
229 
230 /*!
231    \brief Delete point set and remove from list
232 
233    \param id point set id
234  */
gp_delete_site(int id)235 void gp_delete_site(int id)
236 {
237     geosite *fp;
238 
239     G_debug(5, "gp_delete_site");
240 
241     fp = gp_get_site(id);
242 
243     if (fp) {
244 	gp_free_site(fp);
245     }
246 
247     return;
248 }
249 
250 /*!
251    \brief Free allocated geosite struct
252 
253    \param fp pointer to geosite struct
254 
255    \return 1 on success
256    \return -1 on failure
257  */
gp_free_site(geosite * fp)258 int gp_free_site(geosite * fp)
259 {
260     geosite *gp;
261     int found = 0;
262 
263     G_debug(5, "gp_free_site(id=%d)", fp->gsite_id);
264 
265     if (Site_top) {
266 	if (fp == Site_top) {
267 	    if (Site_top->next) {
268 		/* can't free top if last */
269 		found = 1;
270 		Site_top = fp->next;
271 	    }
272 	    else {
273 		gp_free_sitemem(fp);
274 		G_free(fp);
275 		Site_top = NULL;
276 	    }
277 	}
278 	else {
279 	    for (gp = Site_top; gp && !found; gp = gp->next) {
280 		/* can't free top */
281 		if (gp->next) {
282 		    if (gp->next == fp) {
283 			found = 1;
284 			gp->next = fp->next;
285 		    }
286 		}
287 	    }
288 	}
289 
290 	if (found) {
291 	    gp_free_sitemem(fp);
292 	    G_free(fp);
293 	    fp = NULL;
294 	}
295 
296 	return (1);
297     }
298 
299     return -1;
300 }
301 
302 /*!
303    \brief Free geosite (lower level)
304 
305    \param fp pointer to geosite struct
306  */
gp_free_sitemem(geosite * fp)307 void gp_free_sitemem(geosite * fp)
308 {
309     geopoint *gpt, *tmp;
310 
311     G_free((void *)fp->filename);
312     fp->filename = NULL;
313     if (fp->style) {
314 	G_free(fp->style);
315     }
316     if (fp->hstyle) {
317 	G_free(fp->hstyle);
318     }
319     if (fp->points) {
320 	for (gpt = fp->points; gpt;) {
321 	    G_free(gpt->cats);
322 	    if(gpt->style) {
323 		G_free(gpt->style);
324 	    }
325 
326 	    tmp = gpt;
327 	    gpt = gpt->next;
328 	    G_free(tmp);
329 	}
330 
331 	fp->n_sites = 0;
332 	fp->points = NULL;
333     }
334 
335     if (fp->tstyle) {
336 	G_free(fp->tstyle->color_column);
337 	G_free(fp->tstyle->symbol_column);
338 	G_free(fp->tstyle->size_column);
339 	G_free(fp->tstyle->width_column);
340     }
341 
342     return;
343 }
344 
345 /*!
346    \brief Set drape surfaces
347 
348    \param gp pointer to geosite struct
349    \param hsurf list of surfaces (id)
350    \param nsurf number of surfaces
351  */
gp_set_drapesurfs(geosite * gp,int hsurfs[],int nsurfs)352 void gp_set_drapesurfs(geosite * gp, int hsurfs[], int nsurfs)
353 {
354     int i;
355 
356     for (i = 0; i < nsurfs && i < MAX_SURFS; i++) {
357 	gp->drape_surf_id[i] = hsurfs[i];
358     }
359 
360     return;
361 }
362