19 #include "sql_string.h"
20 #include <my_compiler.h>
24 #include "gcalc_tools.h"
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);
44 point_xy(
double x_arg,
double y_arg): x(x_arg), y(y_arg) { }
48 double distance(point_xy p)
50 return sqrt(pow(x - p.x, 2) + pow(y - p.y, 2));
58 return (x == p.x) && (y == p.y);
62 typedef struct wkb_header_st
79 double xmin, ymin, xmax, ymax;
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)
92 MBR(
const point_xy &min,
const point_xy &max)
93 :xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y)
96 inline void add_xy(
double x,
double y)
108 void add_xy(point_xy p)
112 void add_xy(
const char *px,
const char *py)
119 void add_mbr(
const MBR *mbr)
121 if (mbr->xmin < xmin)
123 if (mbr->xmax > xmax)
125 if (mbr->ymin < ymin)
127 if (mbr->ymax > ymax)
131 int equals(
const MBR *mbr)
134 return ((mbr->xmin == xmin) && (mbr->ymin == ymin) &&
135 (mbr->xmax == xmax) && (mbr->ymax == ymax));
138 int disjoint(
const MBR *mbr)
141 return ((mbr->xmin > xmax) || (mbr->ymin > ymax) ||
142 (mbr->xmax < xmin) || (mbr->ymax < ymin));
145 int intersects(
const MBR *mbr)
147 return !disjoint(mbr);
150 int touches(
const MBR *mbr)
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)));
161 int within(
const MBR *mbr)
164 return ((mbr->xmin <= xmin) && (mbr->ymin <= ymin) &&
165 (mbr->xmax >= xmax) && (mbr->ymax >= ymax));
168 int contains(
const MBR *mbr)
171 return ((mbr->xmin >= xmin) && (mbr->ymin >= ymin) &&
172 (mbr->xmax <= xmax) && (mbr->ymax <= ymax));
175 bool inner_point(
double x,
double y)
const
178 return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>y);
188 int dimension()
const
194 else if (xmin < xmax)
199 else if (ymin < ymax)
205 int overlaps(
const MBR *mbr)
214 if (d != mbr->dimension() || d <= 0 || contains(mbr) || within(mbr))
219 MBR intersection(max(xmin, mbr->xmin), max(ymin, mbr->ymin),
220 min(xmax, mbr->xmax), min(ymax, mbr->ymax));
222 return (d == intersection.dimension());
229 struct Geometry_buffer;
235 virtual ~Geometry() {}
236 static void *
operator new(
size_t size,
void *buffer)
241 static void operator delete(
void *ptr,
void *buffer)
244 static void operator delete(
void *buffer)
247 static String bad_geometry_data;
255 wkb_multilinestring= 5,
257 wkb_geometrycollection= 7,
277 const char *m_data_end;
280 wkb_container(
const char *data,
const char *data_end)
284 void set(
const char *data,
const char *data_end)
287 m_data_end= data_end;
289 const char *data()
const
293 const char *data_end()
const
297 uint32 length()
const
299 return (uint32) (m_data_end - m_data);
308 inline bool no_data(
size_t data_amount)
const
310 return (m_data + data_amount > m_data_end);
324 inline bool not_enough_points(uint32 expected_points,
325 uint32 extra_point_space= 0)
const
327 return (m_data_end < m_data ||
328 expected_points > ((m_data_end - m_data) /
329 (POINT_DATA_SIZE + extra_point_space)));
339 class wkb_parser:
public wkb_container
342 void get_uint4(uint32 *number)
344 *number= uint4korr(m_data);
346 void get_float8(
double *x)
348 float8get(*x, m_data);
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) { }
357 void skip_unsafe(
size_t nbytes)
359 DBUG_ASSERT(!no_data(nbytes));
362 bool skip(
size_t nbytes)
369 bool skip_wkb_header()
371 return skip(WKB_HEADER_SIZE);
375 return skip(SIZEOF_STORED_DOUBLE);
379 bool scan_wkb_header(wkb_header *header)
381 if (no_data(WKB_HEADER_SIZE))
383 header->byte_order= (uchar) (*m_data);
385 get_uint4(&header->wkb_type);
391 bool scan_uint4(uint32 *number)
399 bool scan_non_zero_uint4(uint32 *number)
401 return (scan_uint4(number) || 0 == *number);
403 bool scan_n_points_and_check_data(uint32 *n_points,
404 uint32 extra_point_space= 0)
406 return scan_non_zero_uint4(n_points) ||
407 not_enough_points(*n_points, extra_point_space);
411 void scan_xy_unsafe(point_xy *p)
413 DBUG_ASSERT(!no_data(POINT_DATA_SIZE));
415 m_data+= SIZEOF_STORED_DOUBLE;
417 m_data+= SIZEOF_STORED_DOUBLE;
419 bool scan_xy(point_xy *p)
421 if (no_data(SIZEOF_STORED_DOUBLE * 2))
426 bool scan_coord(
double *x)
428 if (no_data(SIZEOF_STORED_DOUBLE))
431 m_data+= SIZEOF_STORED_DOUBLE;
437 typedef Geometry *(*create_geom_t)(
char *);
444 create_geom_t m_create_func;
445 Class_info(
const char *
name,
int type_id, create_geom_t create_func);
448 virtual const Class_info *get_class_info()
const=0;
449 virtual uint32 get_data_size()
const=0;
452 virtual uint init_from_wkb(
const char *wkb, uint len, wkbByteOrder bo,
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; }
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)
462 wkb_parser wkb(&m_wkb_data);
463 return get_mbr(mbr, &wkb);
465 virtual bool dimension(uint32 *dim, wkb_parser *wkb)
const
467 *dim= feature_dimension();
469 if ((length= get_data_size()) == GET_SIZE_ERROR)
474 bool dimension(uint32 *dim)
476 wkb_parser wkb(&m_wkb_data);
477 return dimension(dim, &wkb);
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
492 uint32 data_size= get_data_size();
493 if (data_size == GET_SIZE_ERROR || wkb->no_data(data_size))
495 wkb->skip_unsafe(data_size);
499 bool area(
double *ar)
const
501 wkb_parser wkb(&m_wkb_data);
502 return area(ar, &wkb);
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; }
520 return store_shapes(trn, &dummy);
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)
530 if (wkb->scan_wkb_header(&header) ||
531 !(geom= create_by_typeid(buffer, header.wkb_type)))
533 geom->set_data_ptr(wkb);
537 static Geometry *construct(Geometry_buffer *buffer,
538 const char *data, uint32 data_len);
539 static Geometry *construct(Geometry_buffer *buffer,
const String *str)
541 return construct(buffer, str->ptr(), str->length());
543 static Geometry *create_from_wkt(Geometry_buffer *buffer,
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,
550 bool as_wkt(
String *wkt, wkb_parser *wkb)
552 uint32 len= (uint) get_class_info()->m_name.length;
553 if (wkt->reserve(len + 2, 512))
555 wkt->qs_append(get_class_info()->m_name.str, len);
557 if (get_data_as_wkt(wkt, wkb))
564 wkb_parser wkb(&m_wkb_data);
565 return as_wkt(wkt, &wkb);
568 inline void set_data_ptr(
const char *data, uint32 data_len)
570 m_wkb_data.set(data, data + data_len);
573 inline void set_data_ptr(
const wkb_container *wkb)
578 bool envelope(
String *result)
const;
579 static Class_info *ci_collection[wkb_last+1];
582 static Class_info *find_class(
int type_id)
584 return ((type_id < wkb_point) || (type_id > wkb_last)) ?
585 NULL : ci_collection[type_id];
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;
609 Geometry *collection_item)
const;
617 bool collection_area(
double *ar, wkb_parser *wkb, Geometry *it)
const;
625 uint collection_init_from_opresult(
String *bin,
626 const char *opres, uint opres_length,
627 Geometry *collection_item);
634 class Gis_point:
public Geometry
638 virtual ~Gis_point() {}
639 uint32 get_data_size()
const;
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;
645 int get_xy(point_xy *p)
const
647 wkb_parser wkb(&m_wkb_data);
648 return wkb.scan_xy(p);
650 int get_x(
double *x)
const
652 wkb_parser wkb(&m_wkb_data);
653 return wkb.scan_coord(x);
655 int get_y(
double *y)
const
657 wkb_parser wkb(&m_wkb_data);
658 return wkb.skip_coord() || wkb.scan_coord(y);
660 uint32 feature_dimension()
const {
return 0; }
662 const Class_info *get_class_info()
const;
668 class Gis_line_string:
public Geometry
671 static const uint32 max_n_points=
672 (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 ) /
676 virtual ~Gis_line_string() {}
677 uint32 get_data_size()
const;
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; }
690 const Class_info *get_class_info()
const;
696 class Gis_polygon:
public Geometry
700 virtual ~Gis_polygon() {}
701 uint32 get_data_size()
const;
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; }
715 const Class_info *get_class_info()
const;
721 class Gis_multi_point:
public Geometry
724 static const uint32 max_n_points=
725 (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 ) /
726 (WKB_HEADER_SIZE + POINT_DATA_SIZE);
729 virtual ~Gis_multi_point() {}
730 uint32 get_data_size()
const;
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; }
740 const Class_info *get_class_info()
const;
746 class Gis_multi_line_string:
public Geometry
749 Gis_multi_line_string() {}
750 virtual ~Gis_multi_line_string() {}
751 uint32 get_data_size()
const;
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; }
763 const Class_info *get_class_info()
const;
769 class Gis_multi_polygon:
public Geometry
772 Gis_multi_polygon() {}
773 virtual ~Gis_multi_polygon() {}
774 uint32 get_data_size()
const;
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; }
785 const Class_info *get_class_info()
const;
786 uint init_from_opresult(
String *bin,
const char *opres, uint opres_length);
792 class Gis_geometry_collection:
public Geometry
795 Gis_geometry_collection() {}
796 virtual ~Gis_geometry_collection() {}
797 uint32 get_data_size()
const;
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
813 const Class_info *get_class_info()
const;
816 struct Geometry_buffer :
public
817 my_aligned_storage<sizeof(Gis_point), MY_ALIGNOF(Gis_point)> {};