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-1335  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 WKB_HEADER_SIZE= 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 
MBRMBR61   MBR()
62   {
63     xmin= ymin= DBL_MAX;
64     xmax= ymax= -DBL_MAX;
65   }
66 
MBRMBR67   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 
MBRMBR72   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 
MBRMBR76   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 
add_xyMBR80   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   }
add_xyMBR92   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   }
add_mbrMBR99   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   }
bufferMBR110   void buffer(double d)
111   {
112     xmin-= d;
113     ymin-= d;
114     xmax+= d;
115     ymax+= d;
116   }
117 
equalsMBR118   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 
disjointMBR125   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 
intersectsMBR132   int intersects(const MBR *mbr)
133   {
134     return !disjoint(mbr);
135   }
136 
touchesMBR137   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 
containsMBR150   int contains(const MBR *mbr)
151   {
152     /* The following should be safe, even if we compare doubles */
153     return ((mbr->xmin >= xmin) && (mbr->ymin >= ymin) &&
154 	    (mbr->xmax <= xmax) && (mbr->ymax <= ymax));
155   }
156 
inner_pointMBR157   bool inner_point(double x, double y) const
158   {
159     /* The following should be safe, even if we compare doubles */
160     return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>y);
161   }
162 
163   /**
164     The dimension maps to an integer as:
165     - Polygon -> 2
166     - Horizontal or vertical line -> 1
167     - Point -> 0
168     - Invalid MBR -> -1
169   */
dimensionMBR170   int dimension() const
171   {
172     int d= 0;
173 
174     if (xmin > xmax)
175       return -1;
176     else if (xmin < xmax)
177       d++;
178 
179     if (ymin > ymax)
180       return -1;
181     else if (ymin < ymax)
182       d++;
183 
184     return d;
185   }
186 
overlapsMBR187   int overlaps(const MBR *mbr)
188   {
189     /*
190       overlaps() requires that some point inside *this is also inside
191       *mbr, and that both geometries and their intersection are of the
192       same dimension.
193     */
194     int d = dimension();
195 
196     if (d != mbr->dimension() || d <= 0 || contains(mbr) || within(mbr))
197       return 0;
198 
199     MBR intersection(MY_MAX(xmin, mbr->xmin), MY_MAX(ymin, mbr->ymin),
200                      MY_MIN(xmax, mbr->xmax), MY_MIN(ymax, mbr->ymax));
201 
202     return (d == intersection.dimension());
203   }
204 
validMBR205   int valid() const
206   { return xmin <= xmax && ymin <= ymax; }
207 };
208 
209 
210 /***************************** Geometry *******************************/
211 
212 struct Geometry_buffer;
213 
214 class Geometry
215 {
216 public:
Geometry()217   Geometry() {}                               /* Remove gcc warning */
~Geometry()218   virtual ~Geometry() {}                        /* Remove gcc warning */
new(size_t size,void * buffer)219   static void *operator new(size_t size, void *buffer)
220   {
221     return buffer;
222   }
223 
delete(void * ptr,void * buffer)224   static void operator delete(void *ptr, void *buffer)
225   {}
226 
delete(void * buffer)227   static void operator delete(void *buffer)
228   {}
229 
230   static String bad_geometry_data;
231 
232   enum wkbType
233   {
234     wkb_point= 1,
235     wkb_linestring= 2,
236     wkb_polygon= 3,
237     wkb_multipoint= 4,
238     wkb_multilinestring= 5,
239     wkb_multipolygon= 6,
240     wkb_geometrycollection= 7,
241     wkb_last=7
242   };
243   enum wkbByteOrder
244   {
245     wkb_xdr= 0,    /* Big Endian */
246     wkb_ndr= 1     /* Little Endian */
247   };
248   enum geojson_errors
249   {
250     GEOJ_INCORRECT_GEOJSON= 1,
251     GEOJ_TOO_FEW_POINTS= 2,
252     GEOJ_POLYGON_NOT_CLOSED= 3,
253     GEOJ_DIMENSION_NOT_SUPPORTED= 4,
254     GEOJ_EMPTY_COORDINATES= 5,
255   };
256 
257 
258   /** Callback which creates Geometry objects on top of a given placement. */
259   typedef Geometry *(*create_geom_t)(char *);
260 
261   class Class_info
262   {
263   public:
264     LEX_STRING m_name;
265     LEX_STRING m_geojson_name;
266     int m_type_id;
267     create_geom_t m_create_func;
268     Class_info(const char *name, const char *gejson_name,
269                int type_id, create_geom_t create_func);
270   };
271 
272   virtual const Class_info *get_class_info() const=0;
273   virtual uint32 get_data_size() const=0;
274   virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0;
275   /* returns the length of the wkb that was read */
276   virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
277                              String *res)=0;
init_from_opresult(String * bin,const char * opres,uint res_len)278   virtual uint init_from_opresult(String *bin,
279                                   const char *opres, uint res_len)
280   { return init_from_wkb(opres + 4, UINT_MAX32, wkb_ndr, bin) + 4; }
init_from_json(json_engine_t * je,bool er_on_3D,String * wkb)281   virtual bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb)
282   { return true; }
283 
284   virtual bool get_data_as_wkt(String *txt, const char **end) const=0;
285   virtual bool get_data_as_json(String *txt, uint max_dec_digits,
286                                 const char **end) const=0;
287   virtual bool get_mbr(MBR *mbr, const char **end) const=0;
288   virtual bool dimension(uint32 *dim, const char **end) const=0;
get_x(double * x)289   virtual int get_x(double *x) const { return -1; }
get_y(double * y)290   virtual int get_y(double *y) const { return -1; }
geom_length(double * len,const char ** end)291   virtual int geom_length(double *len, const char **end) const  { return -1; }
area(double * ar,const char ** end)292   virtual int area(double *ar, const char **end) const { return -1;}
is_closed(int * closed)293   virtual int is_closed(int *closed) const { return -1; }
num_interior_ring(uint32 * n_int_rings)294   virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; }
num_points(uint32 * n_points)295   virtual int num_points(uint32 *n_points) const { return -1; }
num_geometries(uint32 * num)296   virtual int num_geometries(uint32 *num) const { return -1; }
start_point(String * point)297   virtual int start_point(String *point) const { return -1; }
end_point(String * point)298   virtual int end_point(String *point) const { return -1; }
exterior_ring(String * ring)299   virtual int exterior_ring(String *ring) const { return -1; }
centroid(String * point)300   virtual int centroid(String *point) const { return -1; }
point_n(uint32 num,String * result)301   virtual int point_n(uint32 num, String *result) const { return -1; }
interior_ring_n(uint32 num,String * result)302   virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
geometry_n(uint32 num,String * result)303   virtual int geometry_n(uint32 num, String *result) const { return -1; }
304   virtual int store_shapes(Gcalc_shape_transporter *trn) const=0;
305 
306 public:
307   static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
308 
309   static Geometry *construct(Geometry_buffer *buffer,
310                              const char *data, uint32 data_len);
311   static Geometry *create_from_wkt(Geometry_buffer *buffer,
312 				   Gis_read_stream *trs, String *wkt,
313 				   bool init_stream=1);
314   static Geometry *create_from_wkb(Geometry_buffer *buffer,
315                                    const char *wkb, uint32 len, String *res);
316   static Geometry *create_from_json(Geometry_buffer *buffer, json_engine_t *je,
317                                     bool er_on_3D, String *res);
318   static Geometry *create_from_opresult(Geometry_buffer *g_buf,
319                                   String *res, Gcalc_result_receiver &rr);
320   static uint get_key_image_itMBR(LEX_CSTRING &src, uchar *buff, uint length);
321   int as_wkt(String *wkt, const char **end);
322   int as_json(String *wkt, uint max_dec_digits, const char **end);
323   int bbox_as_json(String *wkt);
324 
set_data_ptr(const char * data,uint32 data_len)325   inline void set_data_ptr(const char *data, uint32 data_len)
326   {
327     m_data= data;
328     m_data_end= data + data_len;
329   }
330 
shift_wkb_header()331   inline void shift_wkb_header()
332   {
333     m_data+= WKB_HEADER_SIZE;
334   }
335 
get_data_ptr()336   const char *get_data_ptr() const
337   {
338     return m_data;
339   }
340 
341   bool envelope(String *result) const;
342   static Class_info *ci_collection[wkb_last+1];
343 
344   static bool create_point(String *result, double x, double y);
345 protected:
find_class(int type_id)346   static Class_info *find_class(int type_id)
347   {
348     return ((type_id < wkb_point) || (type_id > wkb_last)) ?
349       NULL : ci_collection[type_id];
350   }
351   static Class_info *find_class(const char *name, size_t len);
352   const char *append_points(String *txt, uint32 n_points,
353 			    const char *data, uint32 offset) const;
354   bool create_point(String *result, const char *data) const;
355   const char *get_mbr_for_points(MBR *mbr, const char *data, uint offset)
356     const;
357 
358   /**
359      Check if there're enough data remaining as requested
360 
361      @arg cur_data     pointer to the position in the binary form
362      @arg data_amount  number of points expected
363      @return           true if not enough data
364   */
no_data(const char * cur_data,size_t data_amount)365   inline bool no_data(const char *cur_data, size_t data_amount) const
366   {
367     return (cur_data + data_amount > m_data_end);
368   }
369 
370   /**
371      Check if there're enough points remaining as requested
372 
373      Need to perform the calculation in logical units, since multiplication
374      can overflow the size data type.
375 
376      @arg data              pointer to the beginning of the points array
377      @arg expected_points   number of points expected
378      @arg extra_point_space extra space for each point element in the array
379      @return               true if there are not enough points
380   */
381   inline bool not_enough_points(const char *data, uint32 expected_points,
382                                 uint32 extra_point_space = 0) const
383   {
384     return (m_data_end < data ||
385             (expected_points > ((m_data_end - data) /
386                                 (POINT_DATA_SIZE + extra_point_space))));
387   }
388   const char *m_data;
389   const char *m_data_end;
390 };
391 
392 
393 /***************************** Point *******************************/
394 
395 class Gis_point: public Geometry
396 {
397 public:
Gis_point()398   Gis_point() {}                              /* Remove gcc warning */
~Gis_point()399   virtual ~Gis_point() {}                     /* Remove gcc warning */
400   uint32 get_data_size() const;
401   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
402   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
403   bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
404   bool get_data_as_wkt(String *txt, const char **end) const;
405   bool get_data_as_json(String *txt, uint max_dec_digits,
406                         const char **end) const;
407   bool get_mbr(MBR *mbr, const char **end) const;
408 
get_xy(double * x,double * y)409   int get_xy(double *x, double *y) const
410   {
411     const char *data= m_data;
412     if (no_data(data, SIZEOF_STORED_DOUBLE * 2))
413       return 1;
414     float8get(*x, data);
415     float8get(*y, data + SIZEOF_STORED_DOUBLE);
416     return 0;
417   }
418 
get_xy_radian(double * x,double * y)419   int get_xy_radian(double *x, double *y) const
420   {
421     if (!get_xy(x, y))
422     {
423       *x= (*x)*M_PI/180;
424       *y= (*y)*M_PI/180;
425       return 0;
426     }
427     return 1;
428   }
429 
get_x(double * x)430   int get_x(double *x) const
431   {
432     if (no_data(m_data, SIZEOF_STORED_DOUBLE))
433       return 1;
434     float8get(*x, m_data);
435     return 0;
436   }
437 
get_y(double * y)438   int get_y(double *y) const
439   {
440     const char *data= m_data;
441     if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1;
442     float8get(*y, data + SIZEOF_STORED_DOUBLE);
443     return 0;
444   }
445 
446   int geom_length(double *len, const char **end) const;
447   int area(double *ar, const char **end) const;
dimension(uint32 * dim,const char ** end)448   bool dimension(uint32 *dim, const char **end) const
449   {
450     *dim= 0;
451     *end= 0;					/* No default end */
452     return 0;
453   }
454   int store_shapes(Gcalc_shape_transporter *trn) const;
455   const Class_info *get_class_info() const;
456   double calculate_haversine(const Geometry *g, const double sphere_radius,
457                              int *error);
458   int spherical_distance_multipoints(Geometry *g, const double r, double *result,
459                                      int *error);
460 };
461 
462 
463 /***************************** LineString *******************************/
464 
465 class Gis_line_string: public Geometry
466 {
467 public:
Gis_line_string()468   Gis_line_string() {}                        /* Remove gcc warning */
~Gis_line_string()469   virtual ~Gis_line_string() {}               /* Remove gcc warning */
470   uint32 get_data_size() const;
471   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
472   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
473   bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
474   bool get_data_as_wkt(String *txt, const char **end) const;
475   bool get_data_as_json(String *txt, uint max_dec_digits,
476                         const char **end) const;
477   bool get_mbr(MBR *mbr, const char **end) const;
478   int geom_length(double *len, const char **end) const;
479   int area(double *ar, const char **end) const;
480   int is_closed(int *closed) const;
481   int num_points(uint32 *n_points) const;
482   int start_point(String *point) const;
483   int end_point(String *point) const;
484   int point_n(uint32 n, String *result) const;
dimension(uint32 * dim,const char ** end)485   bool dimension(uint32 *dim, const char **end) const
486   {
487     *dim= 1;
488     *end= 0;					/* No default end */
489     return 0;
490   }
491   int store_shapes(Gcalc_shape_transporter *trn) const;
492   const Class_info *get_class_info() const;
493 };
494 
495 
496 /***************************** Polygon *******************************/
497 
498 class Gis_polygon: public Geometry
499 {
500 public:
Gis_polygon()501   Gis_polygon() {}                            /* Remove gcc warning */
~Gis_polygon()502   virtual ~Gis_polygon() {}                   /* Remove gcc warning */
503   uint32 get_data_size() const;
504   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
505   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
506   uint init_from_opresult(String *bin, const char *opres, uint res_len);
507   bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
508   bool get_data_as_wkt(String *txt, const char **end) const;
509   bool get_data_as_json(String *txt, uint max_dec_digits,
510                         const char **end) const;
511   bool get_mbr(MBR *mbr, const char **end) const;
512   int area(double *ar, const char **end) const;
513   int exterior_ring(String *result) const;
514   int num_interior_ring(uint32 *n_int_rings) const;
515   int interior_ring_n(uint32 num, String *result) const;
516   int centroid_xy(double *x, double *y) const;
517   int centroid(String *result) const;
dimension(uint32 * dim,const char ** end)518   bool dimension(uint32 *dim, const char **end) const
519   {
520     *dim= 2;
521     *end= 0;					/* No default end */
522     return 0;
523   }
524   int store_shapes(Gcalc_shape_transporter *trn) const;
525   const Class_info *get_class_info() const;
526 };
527 
528 
529 /***************************** MultiPoint *******************************/
530 
531 class Gis_multi_point: public Geometry
532 {
533   // Maximum number of points in MultiPoint that can fit into String
534   static const uint32 max_n_points=
535     (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
536     (WKB_HEADER_SIZE + POINT_DATA_SIZE);
537 public:
Gis_multi_point()538   Gis_multi_point() {}                        /* Remove gcc warning */
~Gis_multi_point()539   virtual ~Gis_multi_point() {}               /* Remove gcc warning */
540   uint32 get_data_size() const;
541   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
542   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
543   uint init_from_opresult(String *bin, const char *opres, uint res_len);
544   bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
545   bool get_data_as_wkt(String *txt, const char **end) const;
546   bool get_data_as_json(String *txt, uint max_dec_digits,
547                         const char **end) const;
548   bool get_mbr(MBR *mbr, const char **end) const;
549   int num_geometries(uint32 *num) const;
550   int geometry_n(uint32 num, String *result) const;
dimension(uint32 * dim,const char ** end)551   bool dimension(uint32 *dim, const char **end) const
552   {
553     *dim= 0;
554     *end= 0;					/* No default end */
555     return 0;
556   }
557   int store_shapes(Gcalc_shape_transporter *trn) const;
558   const Class_info *get_class_info() const;
559   int spherical_distance_multipoints(Geometry *g, const double r, double *res,
560                                      int *error);
561 };
562 
563 
564 /***************************** MultiLineString *******************************/
565 
566 class Gis_multi_line_string: public Geometry
567 {
568 public:
Gis_multi_line_string()569   Gis_multi_line_string() {}                  /* Remove gcc warning */
~Gis_multi_line_string()570   virtual ~Gis_multi_line_string() {}         /* Remove gcc warning */
571   uint32 get_data_size() const;
572   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
573   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
574   uint init_from_opresult(String *bin, const char *opres, uint res_len);
575   bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
576   bool get_data_as_wkt(String *txt, const char **end) const;
577   bool get_data_as_json(String *txt, uint max_dec_digits,
578                         const char **end) const;
579   bool get_mbr(MBR *mbr, const char **end) const;
580   int num_geometries(uint32 *num) const;
581   int geometry_n(uint32 num, String *result) const;
582   int geom_length(double *len, const char **end) const;
583   int is_closed(int *closed) const;
dimension(uint32 * dim,const char ** end)584   bool dimension(uint32 *dim, const char **end) const
585   {
586     *dim= 1;
587     *end= 0;					/* No default end */
588     return 0;
589   }
590   int store_shapes(Gcalc_shape_transporter *trn) const;
591   const Class_info *get_class_info() const;
592 };
593 
594 
595 /***************************** MultiPolygon *******************************/
596 
597 class Gis_multi_polygon: public Geometry
598 {
599 public:
Gis_multi_polygon()600   Gis_multi_polygon() {}                      /* Remove gcc warning */
~Gis_multi_polygon()601   virtual ~Gis_multi_polygon() {}             /* Remove gcc warning */
602   uint32 get_data_size() const;
603   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
604   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
605   bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
606   bool get_data_as_wkt(String *txt, const char **end) const;
607   bool get_data_as_json(String *txt, uint max_dec_digits,
608                         const char **end) const;
609   bool get_mbr(MBR *mbr, const char **end) const;
610   int num_geometries(uint32 *num) const;
611   int geometry_n(uint32 num, String *result) const;
612   int area(double *ar, const char **end) const;
613   int centroid(String *result) const;
dimension(uint32 * dim,const char ** end)614   bool dimension(uint32 *dim, const char **end) const
615   {
616     *dim= 2;
617     *end= 0;					/* No default end */
618     return 0;
619   }
620   int store_shapes(Gcalc_shape_transporter *trn) const;
621   const Class_info *get_class_info() const;
622   uint init_from_opresult(String *bin, const char *opres, uint res_len);
623 };
624 
625 
626 /*********************** GeometryCollection *******************************/
627 
628 class Gis_geometry_collection: public Geometry
629 {
630 public:
Gis_geometry_collection()631   Gis_geometry_collection() {}                /* Remove gcc warning */
~Gis_geometry_collection()632   virtual ~Gis_geometry_collection() {}       /* Remove gcc warning */
633   uint32 get_data_size() const;
634   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
635   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
636   uint init_from_opresult(String *bin, const char *opres, uint res_len);
637   bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
638   bool get_data_as_wkt(String *txt, const char **end) const;
639   bool get_data_as_json(String *txt, uint max_dec_digits,
640                         const char **end) const;
641   bool get_mbr(MBR *mbr, const char **end) const;
642   int area(double *ar, const char **end) const;
643   int geom_length(double *len, const char **end) const;
644   int num_geometries(uint32 *num) const;
645   int geometry_n(uint32 num, String *result) const;
646   bool dimension(uint32 *dim, const char **end) const;
647   int store_shapes(Gcalc_shape_transporter *trn) const;
648   const Class_info *get_class_info() const;
649 };
650 
651 struct Geometry_buffer : public
652   my_aligned_storage<sizeof(Gis_point), MY_ALIGNOF(Gis_point)> {};
653 
654 #endif /*HAVE_SPATIAL*/
655 #endif
656