1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2004 Refractions Research Inc.
22  *
23  **********************************************************************/
24 
25 
26 #include "lwgeom_log.h"
27 #include "liblwgeom.h"
28 
29 #include <stdio.h>
30 #include <string.h>
31 
32 /* Place to hold the ZM string used in other summaries */
33 static char tflags[6];
34 
35 static char *
lwgeom_flagchars(LWGEOM * lwg)36 lwgeom_flagchars(LWGEOM *lwg)
37 {
38 	int flagno = 0;
39 	if ( FLAGS_GET_Z(lwg->flags) ) tflags[flagno++] = 'Z';
40 	if ( FLAGS_GET_M(lwg->flags) ) tflags[flagno++] = 'M';
41 	if ( FLAGS_GET_BBOX(lwg->flags) ) tflags[flagno++] = 'B';
42 	if ( FLAGS_GET_GEODETIC(lwg->flags) ) tflags[flagno++] = 'G';
43 	if ( lwg->srid != SRID_UNKNOWN ) tflags[flagno++] = 'S';
44 	tflags[flagno] = '\0';
45 
46 	LWDEBUGF(4, "Flags: %s - returning %p", lwg->flags, tflags);
47 
48 	return tflags;
49 }
50 
51 /*
52  * Returns an alloced string containing summary for the LWGEOM object
53  */
54 static char *
lwpoint_summary(LWPOINT * point,int offset)55 lwpoint_summary(LWPOINT *point, int offset)
56 {
57 	char *result;
58 	char *pad="";
59 	char *zmflags = lwgeom_flagchars((LWGEOM*)point);
60 
61 	result = (char *)lwalloc(128+offset);
62 
63 	sprintf(result, "%*.s%s[%s]",
64 	        offset, pad, lwtype_name(point->type),
65 	        zmflags);
66 	return result;
67 }
68 
69 static char *
lwline_summary(LWLINE * line,int offset)70 lwline_summary(LWLINE *line, int offset)
71 {
72 	char *result;
73 	char *pad="";
74 	char *zmflags = lwgeom_flagchars((LWGEOM*)line);
75 
76 	result = (char *)lwalloc(128+offset);
77 
78 	sprintf(result, "%*.s%s[%s] with %d points",
79 	        offset, pad, lwtype_name(line->type),
80 	        zmflags,
81 	        line->points->npoints);
82 	return result;
83 }
84 
85 
86 static char *
lwcollection_summary(LWCOLLECTION * col,int offset)87 lwcollection_summary(LWCOLLECTION *col, int offset)
88 {
89 	size_t size = 128;
90 	char *result;
91 	char *tmp;
92 	uint32_t i;
93 	static char *nl = "\n";
94 	char *pad="";
95 	char *zmflags = lwgeom_flagchars((LWGEOM*)col);
96 
97 	LWDEBUG(2, "lwcollection_summary called");
98 
99 	result = (char *)lwalloc(size);
100 
101 	sprintf(result, "%*.s%s[%s] with %d element%s",
102 	        offset, pad, lwtype_name(col->type),
103 	        zmflags,
104 	        col->ngeoms,
105 					col->ngeoms ?
106 						( col->ngeoms > 1 ? "s:\n" : ":\n")
107 						: "s");
108 
109 	for (i=0; i<col->ngeoms; i++)
110 	{
111 		tmp = lwgeom_summary(col->geoms[i], offset+2);
112 		size += strlen(tmp)+1;
113 		result = lwrealloc(result, size);
114 
115 		LWDEBUGF(4, "Reallocated %d bytes for result", size);
116 		if ( i > 0 ) strcat(result,nl);
117 
118 		strcat(result, tmp);
119 		lwfree(tmp);
120 	}
121 
122 	LWDEBUG(3, "lwcollection_summary returning");
123 
124 	return result;
125 }
126 
127 static char *
lwpoly_summary(LWPOLY * poly,int offset)128 lwpoly_summary(LWPOLY *poly, int offset)
129 {
130 	char tmp[256];
131 	size_t size = 64*(poly->nrings+1)+128;
132 	char *result;
133 	uint32_t i;
134 	char *pad="";
135 	static char *nl = "\n";
136 	char *zmflags = lwgeom_flagchars((LWGEOM*)poly);
137 
138 	LWDEBUG(2, "lwpoly_summary called");
139 
140 	result = (char *)lwalloc(size);
141 
142 	sprintf(result, "%*.s%s[%s] with %i ring%s",
143 	        offset, pad, lwtype_name(poly->type),
144 	        zmflags,
145 	        poly->nrings,
146 					poly->nrings ?
147 						( poly->nrings > 1 ? "s:\n" : ":\n")
148 						: "s");
149 
150 	for (i=0; i<poly->nrings; i++)
151 	{
152 		sprintf(tmp,"%s   ring %i has %i points",
153 		        pad, i, poly->rings[i]->npoints);
154 		if ( i > 0 ) strcat(result,nl);
155 		strcat(result,tmp);
156 	}
157 
158 	LWDEBUG(3, "lwpoly_summary returning");
159 
160 	return result;
161 }
162 
163 char *
lwgeom_summary(const LWGEOM * lwgeom,int offset)164 lwgeom_summary(const LWGEOM *lwgeom, int offset)
165 {
166 	char *result;
167 
168 	switch (lwgeom->type)
169 	{
170 	case POINTTYPE:
171 		return lwpoint_summary((LWPOINT *)lwgeom, offset);
172 
173 	case CIRCSTRINGTYPE:
174 	case TRIANGLETYPE:
175 	case LINETYPE:
176 		return lwline_summary((LWLINE *)lwgeom, offset);
177 
178 	case POLYGONTYPE:
179 		return lwpoly_summary((LWPOLY *)lwgeom, offset);
180 
181 	case TINTYPE:
182 	case MULTISURFACETYPE:
183 	case MULTICURVETYPE:
184 	case CURVEPOLYTYPE:
185 	case COMPOUNDTYPE:
186 	case MULTIPOINTTYPE:
187 	case MULTILINETYPE:
188 	case MULTIPOLYGONTYPE:
189 	case COLLECTIONTYPE:
190 		return lwcollection_summary((LWCOLLECTION *)lwgeom, offset);
191 	default:
192 		result = (char *)lwalloc(256);
193 		sprintf(result, "Object is of unknown type: %d",
194 		        lwgeom->type);
195 		return result;
196 	}
197 
198 	return NULL;
199 }
200