1 /**********************************************************************
2 *
3 * rttopo - topology library
4 * http://git.osgeo.org/gitea/rttopo/librttopo
5 *
6 * rttopo 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 * rttopo 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 rttopo. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **********************************************************************
20 *
21 * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
22 *
23 **********************************************************************/
24
25
26
27 #include "rttopo_config.h"
28 #include <ctype.h>
29
30 #include "librttopo_geom_internal.h"
31
32 /* Structure for the type array */
33 struct geomtype_struct
34 {
35 char *typename;
36 int type;
37 int z;
38 int m;
39 };
40
41 /* Type array. Note that the order of this array is important in
42 that any typename in the list must *NOT* occur within an entry
43 before it. Otherwise if we search for "POINT" at the top of the
44 list we would also match MULTIPOINT, for example. */
45
46 struct geomtype_struct geomtype_struct_array[] =
47 {
48 { "GEOMETRYCOLLECTIONZM", RTCOLLECTIONTYPE, 1, 1 },
49 { "GEOMETRYCOLLECTIONZ", RTCOLLECTIONTYPE, 1, 0 },
50 { "GEOMETRYCOLLECTIONM", RTCOLLECTIONTYPE, 0, 1 },
51 { "GEOMETRYCOLLECTION", RTCOLLECTIONTYPE, 0, 0 },
52
53 { "GEOMETRYZM", 0, 1, 1 },
54 { "GEOMETRYZ", 0, 1, 0 },
55 { "GEOMETRYM", 0, 0, 1 },
56 { "GEOMETRY", 0, 0, 0 },
57
58 { "POLYHEDRALSURFACEZM", RTPOLYHEDRALSURFACETYPE, 1, 1 },
59 { "POLYHEDRALSURFACEZ", RTPOLYHEDRALSURFACETYPE, 1, 0 },
60 { "POLYHEDRALSURFACEM", RTPOLYHEDRALSURFACETYPE, 0, 1 },
61 { "POLYHEDRALSURFACE", RTPOLYHEDRALSURFACETYPE, 0, 0 },
62
63 { "TINZM", RTTINTYPE, 1, 1 },
64 { "TINZ", RTTINTYPE, 1, 0 },
65 { "TINM", RTTINTYPE, 0, 1 },
66 { "TIN", RTTINTYPE, 0, 0 },
67
68 { "CIRCULARSTRINGZM", RTCIRCSTRINGTYPE, 1, 1 },
69 { "CIRCULARSTRINGZ", RTCIRCSTRINGTYPE, 1, 0 },
70 { "CIRCULARSTRINGM", RTCIRCSTRINGTYPE, 0, 1 },
71 { "CIRCULARSTRING", RTCIRCSTRINGTYPE, 0, 0 },
72
73 { "COMPOUNDCURVEZM", RTCOMPOUNDTYPE, 1, 1 },
74 { "COMPOUNDCURVEZ", RTCOMPOUNDTYPE, 1, 0 },
75 { "COMPOUNDCURVEM", RTCOMPOUNDTYPE, 0, 1 },
76 { "COMPOUNDCURVE", RTCOMPOUNDTYPE, 0, 0 },
77
78 { "CURVEPOLYGONZM", RTCURVEPOLYTYPE, 1, 1 },
79 { "CURVEPOLYGONZ", RTCURVEPOLYTYPE, 1, 0 },
80 { "CURVEPOLYGONM", RTCURVEPOLYTYPE, 0, 1 },
81 { "CURVEPOLYGON", RTCURVEPOLYTYPE, 0, 0 },
82
83 { "MULTICURVEZM", RTMULTICURVETYPE, 1, 1 },
84 { "MULTICURVEZ", RTMULTICURVETYPE, 1, 0 },
85 { "MULTICURVEM", RTMULTICURVETYPE, 0, 1 },
86 { "MULTICURVE", RTMULTICURVETYPE, 0, 0 },
87
88 { "MULTISURFACEZM", RTMULTISURFACETYPE, 1, 1 },
89 { "MULTISURFACEZ", RTMULTISURFACETYPE, 1, 0 },
90 { "MULTISURFACEM", RTMULTISURFACETYPE, 0, 1 },
91 { "MULTISURFACE", RTMULTISURFACETYPE, 0, 0 },
92
93 { "MULTILINESTRINGZM", RTMULTILINETYPE, 1, 1 },
94 { "MULTILINESTRINGZ", RTMULTILINETYPE, 1, 0 },
95 { "MULTILINESTRINGM", RTMULTILINETYPE, 0, 1 },
96 { "MULTILINESTRING", RTMULTILINETYPE, 0, 0 },
97
98 { "MULTIPOLYGONZM", RTMULTIPOLYGONTYPE, 1, 1 },
99 { "MULTIPOLYGONZ", RTMULTIPOLYGONTYPE, 1, 0 },
100 { "MULTIPOLYGONM", RTMULTIPOLYGONTYPE, 0, 1 },
101 { "MULTIPOLYGON", RTMULTIPOLYGONTYPE, 0, 0 },
102
103 { "MULTIPOINTZM", RTMULTIPOINTTYPE, 1, 1 },
104 { "MULTIPOINTZ", RTMULTIPOINTTYPE, 1, 0 },
105 { "MULTIPOINTM", RTMULTIPOINTTYPE, 0, 1 },
106 { "MULTIPOINT", RTMULTIPOINTTYPE, 0, 0 },
107
108 { "LINESTRINGZM", RTLINETYPE, 1, 1 },
109 { "LINESTRINGZ", RTLINETYPE, 1, 0 },
110 { "LINESTRINGM", RTLINETYPE, 0, 1 },
111 { "LINESTRING", RTLINETYPE, 0, 0 },
112
113 { "TRIANGLEZM", RTTRIANGLETYPE, 1, 1 },
114 { "TRIANGLEZ", RTTRIANGLETYPE, 1, 0 },
115 { "TRIANGLEM", RTTRIANGLETYPE, 0, 1 },
116 { "TRIANGLE", RTTRIANGLETYPE, 0, 0 },
117
118 { "POLYGONZM", RTPOLYGONTYPE, 1, 1 },
119 { "POLYGONZ", RTPOLYGONTYPE, 1, 0 },
120 { "POLYGONM", RTPOLYGONTYPE, 0, 1 },
121 { "POLYGON", RTPOLYGONTYPE, 0, 0 },
122
123 { "POINTZM", RTPOINTTYPE, 1, 1 },
124 { "POINTZ", RTPOINTTYPE, 1, 0 },
125 { "POINTM", RTPOINTTYPE, 0, 1 },
126 { "POINT", RTPOINTTYPE, 0, 0 }
127
128 };
129 #define GEOMTYPE_STRUCT_ARRAY_LEN (sizeof geomtype_struct_array/sizeof(struct geomtype_struct))
130
131 /*
132 * We use a very simple upper case mapper here, because the system toupper() function
133 * is locale dependent and may have trouble mapping lower case strings to the upper
134 * case ones we expect (see, the "Turkisk I", http://www.i18nguy.com/unicode/turkish-i18n.html)
135 * We could also count on PgSQL sending us *lower* case inputs, as it seems to do that
136 * regardless of the case the user provides for the type arguments.
137 */
138 const char dumb_upper_map[128] = "................................................0123456789.......ABCDEFGHIJKLMNOPQRSTUVWXYZ......ABCDEFGHIJKLMNOPQRSTUVWXYZ.....";
139
dump_toupper(const RTCTX * ctx,int in)140 static char dump_toupper(const RTCTX *ctx, int in)
141 {
142 if ( in < 0 || in > 127 )
143 return '.';
144 return dumb_upper_map[in];
145 }
146
gflags(const RTCTX * ctx,int hasz,int hasm,int geodetic)147 uint8_t gflags(const RTCTX *ctx, int hasz, int hasm, int geodetic)
148 {
149 uint8_t flags = 0;
150 if ( hasz )
151 RTFLAGS_SET_Z(flags, 1);
152 if ( hasm )
153 RTFLAGS_SET_M(flags, 1);
154 if ( geodetic )
155 RTFLAGS_SET_GEODETIC(flags, 1);
156 return flags;
157 }
158
159 /**
160 * Calculate type integer and dimensional flags from string input.
161 * Case insensitive, and insensitive to spaces at front and back.
162 * Type == 0 in the case of the string "GEOMETRY" or "GEOGRAPHY".
163 * Return RT_SUCCESS for success.
164 */
geometry_type_from_string(const RTCTX * ctx,const char * str,uint8_t * type,int * z,int * m)165 int geometry_type_from_string(const RTCTX *ctx, const char *str, uint8_t *type, int *z, int *m)
166 {
167 char *tmpstr;
168 int tmpstartpos, tmpendpos;
169 int i;
170
171 assert(str);
172 assert(type);
173 assert(z);
174 assert(m);
175
176 /* Initialize. */
177 *type = 0;
178 *z = 0;
179 *m = 0;
180
181 /* Locate any leading/trailing spaces */
182 tmpstartpos = 0;
183 for (i = 0; i < strlen(str); i++)
184 {
185 if (str[i] != ' ')
186 {
187 tmpstartpos = i;
188 break;
189 }
190 }
191
192 tmpendpos = strlen(str) - 1;
193 for (i = strlen(str) - 1; i >= 0; i--)
194 {
195 if (str[i] != ' ')
196 {
197 tmpendpos = i;
198 break;
199 }
200 }
201
202 /* Copy and convert to upper case for comparison */
203 tmpstr = rtalloc(ctx, tmpendpos - tmpstartpos + 2);
204 for (i = tmpstartpos; i <= tmpendpos; i++)
205 tmpstr[i - tmpstartpos] = dump_toupper(ctx, str[i]);
206
207 /* Add NULL to terminate */
208 tmpstr[i - tmpstartpos] = '\0';
209
210 /* Now check for the type */
211 for (i = 0; i < GEOMTYPE_STRUCT_ARRAY_LEN; i++)
212 {
213 if (!strcmp(tmpstr, geomtype_struct_array[i].typename))
214 {
215 *type = geomtype_struct_array[i].type;
216 *z = geomtype_struct_array[i].z;
217 *m = geomtype_struct_array[i].m;
218
219 rtfree(ctx, tmpstr);
220
221 return RT_SUCCESS;
222 }
223
224 }
225
226 rtfree(ctx, tmpstr);
227
228 return RT_FAILURE;
229 }
230
231
232
233
234