MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
spatial.h
1 /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
16 #ifndef _spatial_h
17 #define _spatial_h
18 
19 #include "sql_string.h" /* String, LEX_STRING */
20 #include <my_compiler.h>
21 
22 #ifdef HAVE_SPATIAL
23 
24 #include "gcalc_tools.h"
25 
26 #include <algorithm>
27 
28 const uint SRID_SIZE= 4;
29 const uint SIZEOF_STORED_DOUBLE= 8;
30 const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2);
31 const uint WKB_HEADER_SIZE= 1+4;
32 const uint32 GET_SIZE_ERROR= ((uint32) -1);
33 
34 
38 class point_xy
39 {
40 public:
41  double x;
42  double y;
43  point_xy() { }
44  point_xy(double x_arg, double y_arg): x(x_arg), y(y_arg) { }
48  double distance(point_xy p)
49  {
50  return sqrt(pow(x - p.x, 2) + pow(y - p.y, 2));
51  }
56  bool eq(point_xy p)
57  {
58  return (x == p.x) && (y == p.y);
59  }
60 };
61 
62 typedef struct wkb_header_st
63 {
64  uchar byte_order;
65  uint32 wkb_type;
66 } wkb_header;
67 
68 
69 /***************************** MBR *******************************/
70 
71 
72 /*
73  It's ok that a lot of the functions are inline as these are only used once
74  in MySQL
75 */
76 
77 struct MBR
78 {
79  double xmin, ymin, xmax, ymax;
80 
81  MBR()
82  {
83  xmin= ymin= DBL_MAX;
84  xmax= ymax= -DBL_MAX;
85  }
86 
87  MBR(const double xmin_arg, const double ymin_arg,
88  const double xmax_arg, const double ymax_arg)
89  :xmin(xmin_arg), ymin(ymin_arg), xmax(xmax_arg), ymax(ymax_arg)
90  {}
91 
92  MBR(const point_xy &min, const point_xy &max)
93  :xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y)
94  {}
95 
96  inline void add_xy(double x, double y)
97  {
98  /* Not using "else" for proper one point MBR calculation */
99  if (x < xmin)
100  xmin= x;
101  if (x > xmax)
102  xmax= x;
103  if (y < ymin)
104  ymin= y;
105  if (y > ymax)
106  ymax= y;
107  }
108  void add_xy(point_xy p)
109  {
110  add_xy(p.x, p.y);
111  }
112  void add_xy(const char *px, const char *py)
113  {
114  double x, y;
115  float8get(x, px);
116  float8get(y, py);
117  add_xy(x,y);
118  }
119  void add_mbr(const MBR *mbr)
120  {
121  if (mbr->xmin < xmin)
122  xmin= mbr->xmin;
123  if (mbr->xmax > xmax)
124  xmax= mbr->xmax;
125  if (mbr->ymin < ymin)
126  ymin= mbr->ymin;
127  if (mbr->ymax > ymax)
128  ymax= mbr->ymax;
129  }
130 
131  int equals(const MBR *mbr)
132  {
133  /* The following should be safe, even if we compare doubles */
134  return ((mbr->xmin == xmin) && (mbr->ymin == ymin) &&
135  (mbr->xmax == xmax) && (mbr->ymax == ymax));
136  }
137 
138  int disjoint(const MBR *mbr)
139  {
140  /* The following should be safe, even if we compare doubles */
141  return ((mbr->xmin > xmax) || (mbr->ymin > ymax) ||
142  (mbr->xmax < xmin) || (mbr->ymax < ymin));
143  }
144 
145  int intersects(const MBR *mbr)
146  {
147  return !disjoint(mbr);
148  }
149 
150  int touches(const MBR *mbr)
151  {
152  /* The following should be safe, even if we compare doubles */
153  return ((mbr->xmin == xmax || mbr->xmax == xmin) &&
154  ((mbr->ymin >= ymin && mbr->ymin <= ymax) ||
155  (mbr->ymax >= ymin && mbr->ymax <= ymax))) ||
156  ((mbr->ymin == ymax || mbr->ymax == ymin) &&
157  ((mbr->xmin >= xmin && mbr->xmin <= xmax) ||
158  (mbr->xmax >= xmin && mbr->xmax <= xmax)));
159  }
160 
161  int within(const MBR *mbr)
162  {
163  /* The following should be safe, even if we compare doubles */
164  return ((mbr->xmin <= xmin) && (mbr->ymin <= ymin) &&
165  (mbr->xmax >= xmax) && (mbr->ymax >= ymax));
166  }
167 
168  int contains(const MBR *mbr)
169  {
170  /* The following should be safe, even if we compare doubles */
171  return ((mbr->xmin >= xmin) && (mbr->ymin >= ymin) &&
172  (mbr->xmax <= xmax) && (mbr->ymax <= ymax));
173  }
174 
175  bool inner_point(double x, double y) const
176  {
177  /* The following should be safe, even if we compare doubles */
178  return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>y);
179  }
180 
188  int dimension() const
189  {
190  int d= 0;
191 
192  if (xmin > xmax)
193  return -1;
194  else if (xmin < xmax)
195  d++;
196 
197  if (ymin > ymax)
198  return -1;
199  else if (ymin < ymax)
200  d++;
201 
202  return d;
203  }
204 
205  int overlaps(const MBR *mbr)
206  {
207  /*
208  overlaps() requires that some point inside *this is also inside
209  *mbr, and that both geometries and their intersection are of the
210  same dimension.
211  */
212  int d = dimension();
213 
214  if (d != mbr->dimension() || d <= 0 || contains(mbr) || within(mbr))
215  return 0;
216 
217  using std::min;
218  using std::max;
219  MBR intersection(max(xmin, mbr->xmin), max(ymin, mbr->ymin),
220  min(xmax, mbr->xmax), min(ymax, mbr->ymax));
221 
222  return (d == intersection.dimension());
223  }
224 };
225 
226 
227 /***************************** Geometry *******************************/
228 
229 struct Geometry_buffer;
230 
231 class Geometry
232 {
233 public:
234  Geometry() {} /* Remove gcc warning */
235  virtual ~Geometry() {} /* Remove gcc warning */
236  static void *operator new(size_t size, void *buffer)
237  {
238  return buffer;
239  }
240 
241  static void operator delete(void *ptr, void *buffer)
242  {}
243 
244  static void operator delete(void *buffer)
245  {}
246 
247  static String bad_geometry_data;
248 
249  enum wkbType
250  {
251  wkb_point= 1,
252  wkb_linestring= 2,
253  wkb_polygon= 3,
254  wkb_multipoint= 4,
255  wkb_multilinestring= 5,
256  wkb_multipolygon= 6,
257  wkb_geometrycollection= 7,
258  wkb_last=7
259  };
260  enum wkbByteOrder
261  {
262  wkb_xdr= 0, /* Big Endian */
263  wkb_ndr= 1 /* Little Endian */
264  };
265 
273  class wkb_container
274  {
275  protected:
276  const char *m_data;
277  const char *m_data_end;
278  public:
279  wkb_container() { }
280  wkb_container(const char *data, const char *data_end)
281  {
282  set(data, data_end);
283  }
284  void set(const char *data, const char *data_end)
285  {
286  m_data= data;
287  m_data_end= data_end;
288  }
289  const char *data() const
290  {
291  return m_data;
292  }
293  const char *data_end() const
294  {
295  return m_data_end;
296  }
297  uint32 length() const
298  {
299  return (uint32) (m_data_end - m_data);
300  }
308  inline bool no_data(size_t data_amount) const
309  {
310  return (m_data + data_amount > m_data_end);
311  }
312 
324  inline bool not_enough_points(uint32 expected_points,
325  uint32 extra_point_space= 0) const
326  {
327  return (m_data_end < m_data ||
328  expected_points > ((m_data_end - m_data) /
329  (POINT_DATA_SIZE + extra_point_space)));
330  }
331  };
332 
339  class wkb_parser: public wkb_container
340  {
341  /* Low level routines to get data of various types */
342  void get_uint4(uint32 *number)
343  {
344  *number= uint4korr(m_data); //GIS-TODO: byte order
345  }
346  void get_float8(double *x)
347  {
348  float8get(*x, m_data); //GIS-TODO: byte order
349  }
350  public:
351  wkb_parser(const char *data, const char *data_end):
352  wkb_container(data, data_end) { }
353  wkb_parser(const wkb_container *container):
354  wkb_container(*container) { }
355 
356  /* Routines to skip non-interesting data */
357  void skip_unsafe(size_t nbytes)
358  {
359  DBUG_ASSERT(!no_data(nbytes));
360  m_data+= nbytes;
361  }
362  bool skip(size_t nbytes)
363  {
364  if (no_data(nbytes))
365  return true;
366  m_data+= nbytes;
367  return false;
368  }
369  bool skip_wkb_header()
370  {
371  return skip(WKB_HEADER_SIZE);
372  }
373  bool skip_coord()
374  {
375  return skip(SIZEOF_STORED_DOUBLE);
376  }
377 
378  /* Routines to scan wkb header information */
379  bool scan_wkb_header(wkb_header *header)
380  {
381  if (no_data(WKB_HEADER_SIZE))
382  return true;
383  header->byte_order= (uchar) (*m_data);
384  m_data++;
385  get_uint4(&header->wkb_type);
386  m_data+= 4;
387  return false;
388  }
389 
390  /* Routines to scan uint4 information */
391  bool scan_uint4(uint32 *number)
392  {
393  if (no_data(4))
394  return true;
395  get_uint4(number);
396  m_data+= 4;
397  return false;
398  }
399  bool scan_non_zero_uint4(uint32 *number)
400  {
401  return (scan_uint4(number) || 0 == *number);
402  }
403  bool scan_n_points_and_check_data(uint32 *n_points,
404  uint32 extra_point_space= 0)
405  {
406  return scan_non_zero_uint4(n_points) ||
407  not_enough_points(*n_points, extra_point_space);
408  }
409 
410  /* Routines to scan coordinate information */
411  void scan_xy_unsafe(point_xy *p)
412  {
413  DBUG_ASSERT(!no_data(POINT_DATA_SIZE));
414  get_float8(&p->x);
415  m_data+= SIZEOF_STORED_DOUBLE;
416  get_float8(&p->y);
417  m_data+= SIZEOF_STORED_DOUBLE;
418  }
419  bool scan_xy(point_xy *p)
420  {
421  if (no_data(SIZEOF_STORED_DOUBLE * 2))
422  return true;
423  scan_xy_unsafe(p);
424  return false;
425  }
426  bool scan_coord(double *x)
427  {
428  if (no_data(SIZEOF_STORED_DOUBLE))
429  return true;
430  get_float8(x);
431  m_data+= SIZEOF_STORED_DOUBLE;
432  return false;
433  }
434  };
435 
437  typedef Geometry *(*create_geom_t)(char *);
438 
439  class Class_info
440  {
441  public:
442  LEX_STRING m_name;
443  int m_type_id;
444  create_geom_t m_create_func;
445  Class_info(const char *name, int type_id, create_geom_t create_func);
446  };
447 
448  virtual const Class_info *get_class_info() const=0;
449  virtual uint32 get_data_size() const=0;
450  virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0;
451  /* returns the length of the wkb that was read */
452  virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
453  String *res)=0;
454  virtual uint init_from_opresult(String *bin,
455  const char *opres, uint opres_length)
456  { return init_from_wkb(opres + 4, UINT_MAX32, wkb_ndr, bin) + 4; }
457 
458  virtual bool get_data_as_wkt(String *txt, wkb_parser *wkb) const=0;
459  virtual bool get_mbr(MBR *mbr, wkb_parser *wkb) const=0;
460  bool get_mbr(MBR *mbr)
461  {
462  wkb_parser wkb(&m_wkb_data);
463  return get_mbr(mbr, &wkb);
464  }
465  virtual bool dimension(uint32 *dim, wkb_parser *wkb) const
466  {
467  *dim= feature_dimension();
468  uint32 length;
469  if ((length= get_data_size()) == GET_SIZE_ERROR)
470  return true;
471  wkb->skip(length);
472  return false;
473  }
474  bool dimension(uint32 *dim)
475  {
476  wkb_parser wkb(&m_wkb_data);
477  return dimension(dim, &wkb);
478  }
479  virtual uint32 feature_dimension() const= 0;
480  virtual int get_x(double *x) const { return -1; }
481  virtual int get_y(double *y) const { return -1; }
482  virtual int geom_length(double *len) const { return -1; }
490  virtual bool area(double *ar, wkb_parser *wkb) const
491  {
492  uint32 data_size= get_data_size();
493  if (data_size == GET_SIZE_ERROR || wkb->no_data(data_size))
494  return true;
495  wkb->skip_unsafe(data_size);
496  *ar= 0;
497  return false;
498  }
499  bool area(double *ar) const
500  {
501  wkb_parser wkb(&m_wkb_data);
502  return area(ar, &wkb);
503  }
504  virtual int is_closed(int *closed) const { return -1; }
505  virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; }
506  virtual int num_points(uint32 *n_points) const { return -1; }
507  virtual int num_geometries(uint32 *num) const { return -1; }
508  virtual int start_point(String *point) const { return -1; }
509  virtual int end_point(String *point) const { return -1; }
510  virtual int exterior_ring(String *ring) const { return -1; }
511  virtual int centroid(String *point) const { return -1; }
512  virtual int point_n(uint32 num, String *result) const { return -1; }
513  virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
514  virtual int geometry_n(uint32 num, String *result) const { return -1; }
515  virtual int store_shapes(Gcalc_shape_transporter *trn,
516  Gcalc_shape_status *st) const=0;
517  int store_shapes(Gcalc_shape_transporter *trn) const
518  {
519  Gcalc_shape_status dummy;
520  return store_shapes(trn, &dummy);
521  }
522 
523 public:
524  static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
525  static Geometry *scan_header_and_create(wkb_parser *wkb, Geometry_buffer *buffer)
526  {
527  Geometry *geom;
528  wkb_header header;
529 
530  if (wkb->scan_wkb_header(&header) ||
531  !(geom= create_by_typeid(buffer, header.wkb_type)))
532  return NULL;
533  geom->set_data_ptr(wkb);
534  return geom;
535  }
536 
537  static Geometry *construct(Geometry_buffer *buffer,
538  const char *data, uint32 data_len);
539  static Geometry *construct(Geometry_buffer *buffer, const String *str)
540  {
541  return construct(buffer, str->ptr(), str->length());
542  }
543  static Geometry *create_from_wkt(Geometry_buffer *buffer,
544  Gis_read_stream *trs, String *wkt,
545  bool init_stream=1);
546  static Geometry *create_from_wkb(Geometry_buffer *buffer,
547  const char *wkb, uint32 len, String *res);
548  static int create_from_opresult(Geometry_buffer *g_buf,
549  String *res, Gcalc_result_receiver &rr);
550  bool as_wkt(String *wkt, wkb_parser *wkb)
551  {
552  uint32 len= (uint) get_class_info()->m_name.length;
553  if (wkt->reserve(len + 2, 512))
554  return true;
555  wkt->qs_append(get_class_info()->m_name.str, len);
556  wkt->qs_append('(');
557  if (get_data_as_wkt(wkt, wkb))
558  return true;
559  wkt->qs_append(')');
560  return false;
561  }
562  bool as_wkt(String *wkt)
563  {
564  wkb_parser wkb(&m_wkb_data);
565  return as_wkt(wkt, &wkb);
566  }
567 
568  inline void set_data_ptr(const char *data, uint32 data_len)
569  {
570  m_wkb_data.set(data, data + data_len);
571  }
572 
573  inline void set_data_ptr(const wkb_container *wkb)
574  {
575  m_wkb_data= *wkb;
576  }
577 
578  bool envelope(String *result) const;
579  static Class_info *ci_collection[wkb_last+1];
580 
581 protected:
582  static Class_info *find_class(int type_id)
583  {
584  return ((type_id < wkb_point) || (type_id > wkb_last)) ?
585  NULL : ci_collection[type_id];
586  }
587  static Class_info *find_class(const char *name, uint32 len);
588  void append_points(String *txt, uint32 n_points,
589  wkb_parser *wkb, uint32 offset) const;
590  bool create_point(String *result, wkb_parser *wkb) const;
591  bool create_point(String *result, point_xy p) const;
592  bool get_mbr_for_points(MBR *mbr, wkb_parser *wkb, uint offset) const;
593  wkb_container m_wkb_data;
607  int collection_store_shapes(Gcalc_shape_transporter *trn,
608  Gcalc_shape_status *st,
609  Geometry *collection_item) const;
617  bool collection_area(double *ar, wkb_parser *wkb, Geometry *it) const;
618 
625  uint collection_init_from_opresult(String *bin,
626  const char *opres, uint opres_length,
627  Geometry *collection_item);
628 
629 };
630 
631 
632 /***************************** Point *******************************/
633 
634 class Gis_point: public Geometry
635 {
636 public:
637  Gis_point() {} /* Remove gcc warning */
638  virtual ~Gis_point() {} /* Remove gcc warning */
639  uint32 get_data_size() const;
640  bool init_from_wkt(Gis_read_stream *trs, String *wkb);
641  uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
642  bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
643  bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
644 
645  int get_xy(point_xy *p) const
646  {
647  wkb_parser wkb(&m_wkb_data);
648  return wkb.scan_xy(p);
649  }
650  int get_x(double *x) const
651  {
652  wkb_parser wkb(&m_wkb_data);
653  return wkb.scan_coord(x);
654  }
655  int get_y(double *y) const
656  {
657  wkb_parser wkb(&m_wkb_data);
658  return wkb.skip_coord() || wkb.scan_coord(y);
659  }
660  uint32 feature_dimension() const { return 0; }
661  int store_shapes(Gcalc_shape_transporter *trn, Gcalc_shape_status *st) const;
662  const Class_info *get_class_info() const;
663 };
664 
665 
666 /***************************** LineString *******************************/
667 
668 class Gis_line_string: public Geometry
669 {
670  // Maximum number of points in LineString that can fit into String
671  static const uint32 max_n_points=
672  (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
673  POINT_DATA_SIZE;
674 public:
675  Gis_line_string() {} /* Remove gcc warning */
676  virtual ~Gis_line_string() {} /* Remove gcc warning */
677  uint32 get_data_size() const;
678  bool init_from_wkt(Gis_read_stream *trs, String *wkb);
679  uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
680  bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
681  bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
682  int geom_length(double *len) const;
683  int is_closed(int *closed) const;
684  int num_points(uint32 *n_points) const;
685  int start_point(String *point) const;
686  int end_point(String *point) const;
687  int point_n(uint32 n, String *result) const;
688  uint32 feature_dimension() const { return 1; }
689  int store_shapes(Gcalc_shape_transporter *trn, Gcalc_shape_status *st) const;
690  const Class_info *get_class_info() const;
691 };
692 
693 
694 /***************************** Polygon *******************************/
695 
696 class Gis_polygon: public Geometry
697 {
698 public:
699  Gis_polygon() {} /* Remove gcc warning */
700  virtual ~Gis_polygon() {} /* Remove gcc warning */
701  uint32 get_data_size() const;
702  bool init_from_wkt(Gis_read_stream *trs, String *wkb);
703  uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
704  uint init_from_opresult(String *bin, const char *opres, uint opres_length);
705  bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
706  bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
707  bool area(double *ar, wkb_parser *wkb) const;
708  int exterior_ring(String *result) const;
709  int num_interior_ring(uint32 *n_int_rings) const;
710  int interior_ring_n(uint32 num, String *result) const;
711  bool centroid_xy(point_xy *p) const;
712  int centroid(String *result) const;
713  uint32 feature_dimension() const { return 2; }
714  int store_shapes(Gcalc_shape_transporter *trn, Gcalc_shape_status *st) const;
715  const Class_info *get_class_info() const;
716 };
717 
718 
719 /***************************** MultiPoint *******************************/
720 
721 class Gis_multi_point: public Geometry
722 {
723  // Maximum number of points in MultiPoint that can fit into String
724  static const uint32 max_n_points=
725  (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
726  (WKB_HEADER_SIZE + POINT_DATA_SIZE);
727 public:
728  Gis_multi_point() {} /* Remove gcc warning */
729  virtual ~Gis_multi_point() {} /* Remove gcc warning */
730  uint32 get_data_size() const;
731  bool init_from_wkt(Gis_read_stream *trs, String *wkb);
732  uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
733  uint init_from_opresult(String *bin, const char *opres, uint opres_length);
734  bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
735  bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
736  int num_geometries(uint32 *num) const;
737  int geometry_n(uint32 num, String *result) const;
738  uint32 feature_dimension() const { return 0; }
739  int store_shapes(Gcalc_shape_transporter *trn, Gcalc_shape_status *st) const;
740  const Class_info *get_class_info() const;
741 };
742 
743 
744 /***************************** MultiLineString *******************************/
745 
746 class Gis_multi_line_string: public Geometry
747 {
748 public:
749  Gis_multi_line_string() {} /* Remove gcc warning */
750  virtual ~Gis_multi_line_string() {} /* Remove gcc warning */
751  uint32 get_data_size() const;
752  bool init_from_wkt(Gis_read_stream *trs, String *wkb);
753  uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
754  uint init_from_opresult(String *bin, const char *opres, uint opres_length);
755  bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
756  bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
757  int num_geometries(uint32 *num) const;
758  int geometry_n(uint32 num, String *result) const;
759  int geom_length(double *len) const;
760  int is_closed(int *closed) const;
761  uint32 feature_dimension() const { return 1; }
762  int store_shapes(Gcalc_shape_transporter *trn, Gcalc_shape_status *st) const;
763  const Class_info *get_class_info() const;
764 };
765 
766 
767 /***************************** MultiPolygon *******************************/
768 
769 class Gis_multi_polygon: public Geometry
770 {
771 public:
772  Gis_multi_polygon() {} /* Remove gcc warning */
773  virtual ~Gis_multi_polygon() {} /* Remove gcc warning */
774  uint32 get_data_size() const;
775  bool init_from_wkt(Gis_read_stream *trs, String *wkb);
776  uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
777  bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
778  bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
779  int num_geometries(uint32 *num) const;
780  int geometry_n(uint32 num, String *result) const;
781  bool area(double *ar, wkb_parser *wkb) const;
782  int centroid(String *result) const;
783  uint32 feature_dimension() const { return 2; }
784  int store_shapes(Gcalc_shape_transporter *trn, Gcalc_shape_status *st) const;
785  const Class_info *get_class_info() const;
786  uint init_from_opresult(String *bin, const char *opres, uint opres_length);
787 };
788 
789 
790 /*********************** GeometryCollection *******************************/
791 
792 class Gis_geometry_collection: public Geometry
793 {
794 public:
795  Gis_geometry_collection() {} /* Remove gcc warning */
796  virtual ~Gis_geometry_collection() {} /* Remove gcc warning */
797  uint32 get_data_size() const;
798  bool init_from_wkt(Gis_read_stream *trs, String *wkb);
799  uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
800  uint init_from_opresult(String *bin, const char *opres, uint opres_length);
801  bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
802  bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
803  bool area(double *ar, wkb_parser *wkb) const;
804  int num_geometries(uint32 *num) const;
805  int geometry_n(uint32 num, String *result) const;
806  bool dimension(uint32 *dim, wkb_parser *wkb) const;
807  uint32 feature_dimension() const
808  {
809  DBUG_ASSERT(0);
810  return 0;
811  }
812  int store_shapes(Gcalc_shape_transporter *trn, Gcalc_shape_status *st) const;
813  const Class_info *get_class_info() const;
814 };
815 
816 struct Geometry_buffer : public
817  my_aligned_storage<sizeof(Gis_point), MY_ALIGNOF(Gis_point)> {};
818 
819 #endif /*HAVE_SPATAIAL*/
820 #endif