1 | /* |
2 | Copyright (c) 2002, 2013, Oracle and/or its affiliates. |
3 | Copyright (c) 2009, 2013, Monty Program Ab. |
4 | |
5 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by |
7 | the Free Software Foundation; version 2 of the License. |
8 | |
9 | This program is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License |
15 | along with this program; if not, write to the Free Software |
16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
17 | |
18 | #ifndef _spatial_h |
19 | #define _spatial_h |
20 | |
21 | #include "sql_string.h" /* String, LEX_STRING */ |
22 | #include <my_compiler.h> |
23 | #include <json_lib.h> |
24 | |
25 | #ifdef HAVE_SPATIAL |
26 | |
27 | class Gis_read_stream; |
28 | |
29 | #include "gcalc_tools.h" |
30 | |
31 | const uint SRID_SIZE= 4; |
32 | const uint SIZEOF_STORED_DOUBLE= 8; |
33 | const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2); |
34 | const uint = 1+4; |
35 | const uint32 GET_SIZE_ERROR= ((uint32) -1); |
36 | |
37 | struct st_point_2d |
38 | { |
39 | double x; |
40 | double y; |
41 | }; |
42 | |
43 | struct st_linear_ring |
44 | { |
45 | uint32 n_points; |
46 | st_point_2d points; |
47 | }; |
48 | |
49 | /***************************** MBR *******************************/ |
50 | |
51 | |
52 | /* |
53 | It's ok that a lot of the functions are inline as these are only used once |
54 | in MySQL |
55 | */ |
56 | |
57 | struct MBR |
58 | { |
59 | double xmin, ymin, xmax, ymax; |
60 | |
61 | MBR() |
62 | { |
63 | xmin= ymin= DBL_MAX; |
64 | xmax= ymax= -DBL_MAX; |
65 | } |
66 | |
67 | MBR(const double xmin_arg, const double ymin_arg, |
68 | const double xmax_arg, const double ymax_arg) |
69 | :xmin(xmin_arg), ymin(ymin_arg), xmax(xmax_arg), ymax(ymax_arg) |
70 | {} |
71 | |
72 | MBR(const st_point_2d &min, const st_point_2d &max) |
73 | :xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y) |
74 | {} |
75 | |
76 | MBR(const MBR &mbr1, const MBR &mbr2) |
77 | :xmin(mbr1.xmin), ymin(mbr1.ymin), xmax(mbr1.xmax), ymax(mbr1.ymax) |
78 | { add_mbr(&mbr2); } |
79 | |
80 | inline void add_xy(double x, double y) |
81 | { |
82 | /* Not using "else" for proper one point MBR calculation */ |
83 | if (x < xmin) |
84 | xmin= x; |
85 | if (x > xmax) |
86 | xmax= x; |
87 | if (y < ymin) |
88 | ymin= y; |
89 | if (y > ymax) |
90 | ymax= y; |
91 | } |
92 | void add_xy(const char *px, const char *py) |
93 | { |
94 | double x, y; |
95 | float8get(x, px); |
96 | float8get(y, py); |
97 | add_xy(x,y); |
98 | } |
99 | void add_mbr(const MBR *mbr) |
100 | { |
101 | if (mbr->xmin < xmin) |
102 | xmin= mbr->xmin; |
103 | if (mbr->xmax > xmax) |
104 | xmax= mbr->xmax; |
105 | if (mbr->ymin < ymin) |
106 | ymin= mbr->ymin; |
107 | if (mbr->ymax > ymax) |
108 | ymax= mbr->ymax; |
109 | } |
110 | void buffer(double d) |
111 | { |
112 | xmin-= d; |
113 | ymin-= d; |
114 | xmax+= d; |
115 | ymax+= d; |
116 | } |
117 | |
118 | int equals(const MBR *mbr) |
119 | { |
120 | /* The following should be safe, even if we compare doubles */ |
121 | return ((mbr->xmin == xmin) && (mbr->ymin == ymin) && |
122 | (mbr->xmax == xmax) && (mbr->ymax == ymax)); |
123 | } |
124 | |
125 | int disjoint(const MBR *mbr) |
126 | { |
127 | /* The following should be safe, even if we compare doubles */ |
128 | return ((mbr->xmin > xmax) || (mbr->ymin > ymax) || |
129 | (mbr->xmax < xmin) || (mbr->ymax < ymin)); |
130 | } |
131 | |
132 | int intersects(const MBR *mbr) |
133 | { |
134 | return !disjoint(mbr); |
135 | } |
136 | |
137 | int touches(const MBR *mbr) |
138 | { |
139 | /* The following should be safe, even if we compare doubles */ |
140 | return ((mbr->xmin == xmax || mbr->xmax == xmin) && |
141 | ((mbr->ymin >= ymin && mbr->ymin <= ymax) || |
142 | (mbr->ymax >= ymin && mbr->ymax <= ymax))) || |
143 | ((mbr->ymin == ymax || mbr->ymax == ymin) && |
144 | ((mbr->xmin >= xmin && mbr->xmin <= xmax) || |
145 | (mbr->xmax >= xmin && mbr->xmax <= xmax))); |
146 | } |
147 | |
148 | int within(const MBR *mbr) |
149 | { |
150 | /* The following should be safe, even if we compare doubles */ |
151 | return ((mbr->xmin <= xmin) && (mbr->ymin <= ymin) && |
152 | (mbr->xmax >= xmax) && (mbr->ymax >= ymax)); |
153 | } |
154 | |
155 | int contains(const MBR *mbr) |
156 | { |
157 | /* The following should be safe, even if we compare doubles */ |
158 | return ((mbr->xmin >= xmin) && (mbr->ymin >= ymin) && |
159 | (mbr->xmax <= xmax) && (mbr->ymax <= ymax)); |
160 | } |
161 | |
162 | bool inner_point(double x, double y) const |
163 | { |
164 | /* The following should be safe, even if we compare doubles */ |
165 | return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>y); |
166 | } |
167 | |
168 | /** |
169 | The dimension maps to an integer as: |
170 | - Polygon -> 2 |
171 | - Horizontal or vertical line -> 1 |
172 | - Point -> 0 |
173 | - Invalid MBR -> -1 |
174 | */ |
175 | int dimension() const |
176 | { |
177 | int d= 0; |
178 | |
179 | if (xmin > xmax) |
180 | return -1; |
181 | else if (xmin < xmax) |
182 | d++; |
183 | |
184 | if (ymin > ymax) |
185 | return -1; |
186 | else if (ymin < ymax) |
187 | d++; |
188 | |
189 | return d; |
190 | } |
191 | |
192 | int overlaps(const MBR *mbr) |
193 | { |
194 | /* |
195 | overlaps() requires that some point inside *this is also inside |
196 | *mbr, and that both geometries and their intersection are of the |
197 | same dimension. |
198 | */ |
199 | int d = dimension(); |
200 | |
201 | if (d != mbr->dimension() || d <= 0 || contains(mbr) || within(mbr)) |
202 | return 0; |
203 | |
204 | MBR intersection(MY_MAX(xmin, mbr->xmin), MY_MAX(ymin, mbr->ymin), |
205 | MY_MIN(xmax, mbr->xmax), MY_MIN(ymax, mbr->ymax)); |
206 | |
207 | return (d == intersection.dimension()); |
208 | } |
209 | |
210 | int valid() const |
211 | { return xmin <= xmax && ymin <= ymax; } |
212 | }; |
213 | |
214 | |
215 | /***************************** Geometry *******************************/ |
216 | |
217 | struct Geometry_buffer; |
218 | |
219 | class Geometry |
220 | { |
221 | public: |
222 | Geometry() {} /* Remove gcc warning */ |
223 | virtual ~Geometry() {} /* Remove gcc warning */ |
224 | static void *operator new(size_t size, void *buffer) |
225 | { |
226 | return buffer; |
227 | } |
228 | |
229 | static void operator delete(void *ptr, void *buffer) |
230 | {} |
231 | |
232 | static void operator delete(void *buffer) |
233 | {} |
234 | |
235 | static String bad_geometry_data; |
236 | |
237 | enum wkbType |
238 | { |
239 | wkb_point= 1, |
240 | wkb_linestring= 2, |
241 | wkb_polygon= 3, |
242 | wkb_multipoint= 4, |
243 | wkb_multilinestring= 5, |
244 | wkb_multipolygon= 6, |
245 | wkb_geometrycollection= 7, |
246 | wkb_last=7 |
247 | }; |
248 | enum wkbByteOrder |
249 | { |
250 | wkb_xdr= 0, /* Big Endian */ |
251 | wkb_ndr= 1 /* Little Endian */ |
252 | }; |
253 | enum geojson_errors |
254 | { |
255 | GEOJ_INCORRECT_GEOJSON= 1, |
256 | GEOJ_TOO_FEW_POINTS= 2, |
257 | GEOJ_POLYGON_NOT_CLOSED= 3, |
258 | GEOJ_DIMENSION_NOT_SUPPORTED= 4, |
259 | GEOJ_EMPTY_COORDINATES= 5, |
260 | }; |
261 | |
262 | |
263 | /** Callback which creates Geometry objects on top of a given placement. */ |
264 | typedef Geometry *(*create_geom_t)(char *); |
265 | |
266 | class Class_info |
267 | { |
268 | public: |
269 | LEX_STRING m_name; |
270 | LEX_STRING m_geojson_name; |
271 | int m_type_id; |
272 | create_geom_t m_create_func; |
273 | Class_info(const char *name, const char *gejson_name, |
274 | int type_id, create_geom_t create_func); |
275 | }; |
276 | |
277 | virtual const Class_info *get_class_info() const=0; |
278 | virtual uint32 get_data_size() const=0; |
279 | virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0; |
280 | /* returns the length of the wkb that was read */ |
281 | virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, |
282 | String *res)=0; |
283 | virtual uint init_from_opresult(String *bin, |
284 | const char *opres, uint res_len) |
285 | { return init_from_wkb(opres + 4, UINT_MAX32, wkb_ndr, bin) + 4; } |
286 | virtual bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) |
287 | { return true; } |
288 | |
289 | virtual bool get_data_as_wkt(String *txt, const char **end) const=0; |
290 | virtual bool get_data_as_json(String *txt, uint max_dec_digits, |
291 | const char **end) const=0; |
292 | virtual bool get_mbr(MBR *mbr, const char **end) const=0; |
293 | virtual bool dimension(uint32 *dim, const char **end) const=0; |
294 | virtual int get_x(double *x) const { return -1; } |
295 | virtual int get_y(double *y) const { return -1; } |
296 | virtual int geom_length(double *len, const char **end) const { return -1; } |
297 | virtual int area(double *ar, const char **end) const { return -1;} |
298 | virtual int is_closed(int *closed) const { return -1; } |
299 | virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; } |
300 | virtual int num_points(uint32 *n_points) const { return -1; } |
301 | virtual int num_geometries(uint32 *num) const { return -1; } |
302 | virtual int start_point(String *point) const { return -1; } |
303 | virtual int end_point(String *point) const { return -1; } |
304 | virtual int exterior_ring(String *ring) const { return -1; } |
305 | virtual int centroid(String *point) const { return -1; } |
306 | virtual int point_n(uint32 num, String *result) const { return -1; } |
307 | virtual int interior_ring_n(uint32 num, String *result) const { return -1; } |
308 | virtual int geometry_n(uint32 num, String *result) const { return -1; } |
309 | virtual int store_shapes(Gcalc_shape_transporter *trn) const=0; |
310 | |
311 | public: |
312 | static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id); |
313 | |
314 | static Geometry *construct(Geometry_buffer *buffer, |
315 | const char *data, uint32 data_len); |
316 | static Geometry *create_from_wkt(Geometry_buffer *buffer, |
317 | Gis_read_stream *trs, String *wkt, |
318 | bool init_stream=1); |
319 | static Geometry *create_from_wkb(Geometry_buffer *buffer, |
320 | const char *wkb, uint32 len, String *res); |
321 | static Geometry *create_from_json(Geometry_buffer *buffer, json_engine_t *je, |
322 | bool er_on_3D, String *res); |
323 | static Geometry *create_from_opresult(Geometry_buffer *g_buf, |
324 | String *res, Gcalc_result_receiver &rr); |
325 | int as_wkt(String *wkt, const char **end); |
326 | int as_json(String *wkt, uint max_dec_digits, const char **end); |
327 | int bbox_as_json(String *wkt); |
328 | |
329 | inline void set_data_ptr(const char *data, uint32 data_len) |
330 | { |
331 | m_data= data; |
332 | m_data_end= data + data_len; |
333 | } |
334 | |
335 | inline void () |
336 | { |
337 | m_data+= WKB_HEADER_SIZE; |
338 | } |
339 | |
340 | bool envelope(String *result) const; |
341 | static Class_info *ci_collection[wkb_last+1]; |
342 | |
343 | static bool create_point(String *result, double x, double y); |
344 | protected: |
345 | static Class_info *find_class(int type_id) |
346 | { |
347 | return ((type_id < wkb_point) || (type_id > wkb_last)) ? |
348 | NULL : ci_collection[type_id]; |
349 | } |
350 | static Class_info *find_class(const char *name, size_t len); |
351 | const char *append_points(String *txt, uint32 n_points, |
352 | const char *data, uint32 offset) const; |
353 | bool create_point(String *result, const char *data) const; |
354 | const char *get_mbr_for_points(MBR *mbr, const char *data, uint offset) |
355 | const; |
356 | |
357 | /** |
358 | Check if there're enough data remaining as requested |
359 | |
360 | @arg cur_data pointer to the position in the binary form |
361 | @arg data_amount number of points expected |
362 | @return true if not enough data |
363 | */ |
364 | inline bool no_data(const char *cur_data, size_t data_amount) const |
365 | { |
366 | return (cur_data + data_amount > m_data_end); |
367 | } |
368 | |
369 | /** |
370 | Check if there're enough points remaining as requested |
371 | |
372 | Need to perform the calculation in logical units, since multiplication |
373 | can overflow the size data type. |
374 | |
375 | @arg data pointer to the beginning of the points array |
376 | @arg expected_points number of points expected |
377 | @arg extra_point_space extra space for each point element in the array |
378 | @return true if there are not enough points |
379 | */ |
380 | inline bool not_enough_points(const char *data, uint32 expected_points, |
381 | uint32 = 0) const |
382 | { |
383 | return (m_data_end < data || |
384 | (expected_points > ((m_data_end - data) / |
385 | (POINT_DATA_SIZE + extra_point_space)))); |
386 | } |
387 | const char *m_data; |
388 | const char *m_data_end; |
389 | }; |
390 | |
391 | |
392 | /***************************** Point *******************************/ |
393 | |
394 | class Gis_point: public Geometry |
395 | { |
396 | public: |
397 | Gis_point() {} /* Remove gcc warning */ |
398 | virtual ~Gis_point() {} /* Remove gcc warning */ |
399 | uint32 get_data_size() const; |
400 | bool init_from_wkt(Gis_read_stream *trs, String *wkb); |
401 | uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); |
402 | bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb); |
403 | bool get_data_as_wkt(String *txt, const char **end) const; |
404 | bool get_data_as_json(String *txt, uint max_dec_digits, |
405 | const char **end) const; |
406 | bool get_mbr(MBR *mbr, const char **end) const; |
407 | |
408 | int get_xy(double *x, double *y) const |
409 | { |
410 | const char *data= m_data; |
411 | if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) |
412 | return 1; |
413 | float8get(*x, data); |
414 | float8get(*y, data + SIZEOF_STORED_DOUBLE); |
415 | return 0; |
416 | } |
417 | |
418 | int get_x(double *x) const |
419 | { |
420 | if (no_data(m_data, SIZEOF_STORED_DOUBLE)) |
421 | return 1; |
422 | float8get(*x, m_data); |
423 | return 0; |
424 | } |
425 | |
426 | int get_y(double *y) const |
427 | { |
428 | const char *data= m_data; |
429 | if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; |
430 | float8get(*y, data + SIZEOF_STORED_DOUBLE); |
431 | return 0; |
432 | } |
433 | |
434 | int geom_length(double *len, const char **end) const; |
435 | int area(double *ar, const char **end) const; |
436 | bool dimension(uint32 *dim, const char **end) const |
437 | { |
438 | *dim= 0; |
439 | *end= 0; /* No default end */ |
440 | return 0; |
441 | } |
442 | int store_shapes(Gcalc_shape_transporter *trn) const; |
443 | const Class_info *get_class_info() const; |
444 | }; |
445 | |
446 | |
447 | /***************************** LineString *******************************/ |
448 | |
449 | class Gis_line_string: public Geometry |
450 | { |
451 | public: |
452 | Gis_line_string() {} /* Remove gcc warning */ |
453 | virtual ~Gis_line_string() {} /* Remove gcc warning */ |
454 | uint32 get_data_size() const; |
455 | bool init_from_wkt(Gis_read_stream *trs, String *wkb); |
456 | uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); |
457 | bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb); |
458 | bool get_data_as_wkt(String *txt, const char **end) const; |
459 | bool get_data_as_json(String *txt, uint max_dec_digits, |
460 | const char **end) const; |
461 | bool get_mbr(MBR *mbr, const char **end) const; |
462 | int geom_length(double *len, const char **end) const; |
463 | int area(double *ar, const char **end) const; |
464 | int is_closed(int *closed) const; |
465 | int num_points(uint32 *n_points) const; |
466 | int start_point(String *point) const; |
467 | int end_point(String *point) const; |
468 | int point_n(uint32 n, String *result) const; |
469 | bool dimension(uint32 *dim, const char **end) const |
470 | { |
471 | *dim= 1; |
472 | *end= 0; /* No default end */ |
473 | return 0; |
474 | } |
475 | int store_shapes(Gcalc_shape_transporter *trn) const; |
476 | const Class_info *get_class_info() const; |
477 | }; |
478 | |
479 | |
480 | /***************************** Polygon *******************************/ |
481 | |
482 | class Gis_polygon: public Geometry |
483 | { |
484 | public: |
485 | Gis_polygon() {} /* Remove gcc warning */ |
486 | virtual ~Gis_polygon() {} /* Remove gcc warning */ |
487 | uint32 get_data_size() const; |
488 | bool init_from_wkt(Gis_read_stream *trs, String *wkb); |
489 | uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); |
490 | uint init_from_opresult(String *bin, const char *opres, uint res_len); |
491 | bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb); |
492 | bool get_data_as_wkt(String *txt, const char **end) const; |
493 | bool get_data_as_json(String *txt, uint max_dec_digits, |
494 | const char **end) const; |
495 | bool get_mbr(MBR *mbr, const char **end) const; |
496 | int area(double *ar, const char **end) const; |
497 | int exterior_ring(String *result) const; |
498 | int num_interior_ring(uint32 *n_int_rings) const; |
499 | int interior_ring_n(uint32 num, String *result) const; |
500 | int centroid_xy(double *x, double *y) const; |
501 | int centroid(String *result) const; |
502 | bool dimension(uint32 *dim, const char **end) const |
503 | { |
504 | *dim= 2; |
505 | *end= 0; /* No default end */ |
506 | return 0; |
507 | } |
508 | int store_shapes(Gcalc_shape_transporter *trn) const; |
509 | const Class_info *get_class_info() const; |
510 | }; |
511 | |
512 | |
513 | /***************************** MultiPoint *******************************/ |
514 | |
515 | class Gis_multi_point: public Geometry |
516 | { |
517 | // Maximum number of points in MultiPoint that can fit into String |
518 | static const uint32 max_n_points= |
519 | (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / |
520 | (WKB_HEADER_SIZE + POINT_DATA_SIZE); |
521 | public: |
522 | Gis_multi_point() {} /* Remove gcc warning */ |
523 | virtual ~Gis_multi_point() {} /* Remove gcc warning */ |
524 | uint32 get_data_size() const; |
525 | bool init_from_wkt(Gis_read_stream *trs, String *wkb); |
526 | uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); |
527 | uint init_from_opresult(String *bin, const char *opres, uint res_len); |
528 | bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb); |
529 | bool get_data_as_wkt(String *txt, const char **end) const; |
530 | bool get_data_as_json(String *txt, uint max_dec_digits, |
531 | const char **end) const; |
532 | bool get_mbr(MBR *mbr, const char **end) const; |
533 | int num_geometries(uint32 *num) const; |
534 | int geometry_n(uint32 num, String *result) const; |
535 | bool dimension(uint32 *dim, const char **end) const |
536 | { |
537 | *dim= 0; |
538 | *end= 0; /* No default end */ |
539 | return 0; |
540 | } |
541 | int store_shapes(Gcalc_shape_transporter *trn) const; |
542 | const Class_info *get_class_info() const; |
543 | }; |
544 | |
545 | |
546 | /***************************** MultiLineString *******************************/ |
547 | |
548 | class Gis_multi_line_string: public Geometry |
549 | { |
550 | public: |
551 | Gis_multi_line_string() {} /* Remove gcc warning */ |
552 | virtual ~Gis_multi_line_string() {} /* Remove gcc warning */ |
553 | uint32 get_data_size() const; |
554 | bool init_from_wkt(Gis_read_stream *trs, String *wkb); |
555 | uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); |
556 | uint init_from_opresult(String *bin, const char *opres, uint res_len); |
557 | bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb); |
558 | bool get_data_as_wkt(String *txt, const char **end) const; |
559 | bool get_data_as_json(String *txt, uint max_dec_digits, |
560 | const char **end) const; |
561 | bool get_mbr(MBR *mbr, const char **end) const; |
562 | int num_geometries(uint32 *num) const; |
563 | int geometry_n(uint32 num, String *result) const; |
564 | int geom_length(double *len, const char **end) const; |
565 | int is_closed(int *closed) const; |
566 | bool dimension(uint32 *dim, const char **end) const |
567 | { |
568 | *dim= 1; |
569 | *end= 0; /* No default end */ |
570 | return 0; |
571 | } |
572 | int store_shapes(Gcalc_shape_transporter *trn) const; |
573 | const Class_info *get_class_info() const; |
574 | }; |
575 | |
576 | |
577 | /***************************** MultiPolygon *******************************/ |
578 | |
579 | class Gis_multi_polygon: public Geometry |
580 | { |
581 | public: |
582 | Gis_multi_polygon() {} /* Remove gcc warning */ |
583 | virtual ~Gis_multi_polygon() {} /* Remove gcc warning */ |
584 | uint32 get_data_size() const; |
585 | bool init_from_wkt(Gis_read_stream *trs, String *wkb); |
586 | uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); |
587 | bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb); |
588 | bool get_data_as_wkt(String *txt, const char **end) const; |
589 | bool get_data_as_json(String *txt, uint max_dec_digits, |
590 | const char **end) const; |
591 | bool get_mbr(MBR *mbr, const char **end) const; |
592 | int num_geometries(uint32 *num) const; |
593 | int geometry_n(uint32 num, String *result) const; |
594 | int area(double *ar, const char **end) const; |
595 | int centroid(String *result) const; |
596 | bool dimension(uint32 *dim, const char **end) const |
597 | { |
598 | *dim= 2; |
599 | *end= 0; /* No default end */ |
600 | return 0; |
601 | } |
602 | int store_shapes(Gcalc_shape_transporter *trn) const; |
603 | const Class_info *get_class_info() const; |
604 | uint init_from_opresult(String *bin, const char *opres, uint res_len); |
605 | }; |
606 | |
607 | |
608 | /*********************** GeometryCollection *******************************/ |
609 | |
610 | class Gis_geometry_collection: public Geometry |
611 | { |
612 | public: |
613 | Gis_geometry_collection() {} /* Remove gcc warning */ |
614 | virtual ~Gis_geometry_collection() {} /* Remove gcc warning */ |
615 | uint32 get_data_size() const; |
616 | bool init_from_wkt(Gis_read_stream *trs, String *wkb); |
617 | uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); |
618 | uint init_from_opresult(String *bin, const char *opres, uint res_len); |
619 | bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb); |
620 | bool get_data_as_wkt(String *txt, const char **end) const; |
621 | bool get_data_as_json(String *txt, uint max_dec_digits, |
622 | const char **end) const; |
623 | bool get_mbr(MBR *mbr, const char **end) const; |
624 | int area(double *ar, const char **end) const; |
625 | int geom_length(double *len, const char **end) const; |
626 | int num_geometries(uint32 *num) const; |
627 | int geometry_n(uint32 num, String *result) const; |
628 | bool dimension(uint32 *dim, const char **end) const; |
629 | int store_shapes(Gcalc_shape_transporter *trn) const; |
630 | const Class_info *get_class_info() const; |
631 | }; |
632 | |
633 | struct Geometry_buffer : public |
634 | my_aligned_storage<sizeof(Gis_point), MY_ALIGNOF(Gis_point)> {}; |
635 | |
636 | #endif /*HAVE_SPATIAL*/ |
637 | #endif |
638 | |