18 #include "sql_string.h"
19 #include "my_global.h"
22 #include <mysqld_error.h>
47 #define MAX_DIGITS_IN_DOUBLE 30
51 String Geometry::bad_geometry_data(
"Bad object", &my_charset_bin);
53 Geometry::Class_info *Geometry::ci_collection[Geometry::wkb_last+1]=
55 NULL, NULL, NULL, NULL, NULL, NULL, NULL
58 static Geometry::Class_info **ci_collection_end=
59 Geometry::ci_collection+Geometry::wkb_last + 1;
61 Geometry::Class_info::Class_info(
const char *
name,
int type_id,
62 create_geom_t create_func):
63 m_type_id(type_id), m_create_func(create_func)
65 m_name.str= (
char *) name;
66 m_name.length= strlen(name);
68 ci_collection[type_id]=
this;
71 static Geometry *create_point(
char *buffer)
73 return new (buffer) Gis_point;
76 static Geometry *create_linestring(
char *buffer)
78 return new (buffer) Gis_line_string;
81 static Geometry *create_polygon(
char *buffer)
83 return new (buffer) Gis_polygon;
86 static Geometry *create_multipoint(
char *buffer)
88 return new (buffer) Gis_multi_point;
91 static Geometry *create_multipolygon(
char *buffer)
93 return new (buffer) Gis_multi_polygon;
96 static Geometry *create_multilinestring(
char *buffer)
98 return new (buffer) Gis_multi_line_string;
101 static Geometry *create_geometrycollection(
char *buffer)
103 return new (buffer) Gis_geometry_collection;
108 static Geometry::Class_info point_class(
"POINT",
109 Geometry::wkb_point, create_point);
111 static Geometry::Class_info linestring_class(
"LINESTRING",
112 Geometry::wkb_linestring,
114 static Geometry::Class_info polygon_class(
"POLYGON",
115 Geometry::wkb_polygon,
117 static Geometry::Class_info multipoint_class(
"MULTIPOINT",
118 Geometry::wkb_multipoint,
120 static Geometry::Class_info
121 multilinestring_class(
"MULTILINESTRING",
122 Geometry::wkb_multilinestring, create_multilinestring);
123 static Geometry::Class_info multipolygon_class(
"MULTIPOLYGON",
124 Geometry::wkb_multipolygon,
125 create_multipolygon);
126 static Geometry::Class_info
127 geometrycollection_class(
"GEOMETRYCOLLECTION",Geometry::wkb_geometrycollection,
128 create_geometrycollection);
132 Geometry::Class_info *Geometry::find_class(
const char *
name, uint32 len)
134 for (Class_info **cur_rt= ci_collection;
135 cur_rt < ci_collection_end; cur_rt++)
138 ((*cur_rt)->m_name.length == len) &&
139 (my_strnncoll(&my_charset_latin1,
140 (
const uchar*) (*cur_rt)->m_name.str, len,
141 (
const uchar*) name, len) == 0))
148 Geometry *Geometry::create_by_typeid(Geometry_buffer *buffer,
int type_id)
151 if (!(ci= find_class(type_id)))
153 return (*ci->m_create_func)(buffer->data);
157 Geometry *Geometry::construct(Geometry_buffer *buffer,
158 const char *data, uint32 data_len)
163 if (data_len < SRID_SIZE + WKB_HEADER_SIZE)
166 geom_type= uint4korr(data + SRID_SIZE + 1);
167 if (!(result= create_by_typeid(buffer, (
int) geom_type)))
169 result->set_data_ptr(data + SRID_SIZE + WKB_HEADER_SIZE,
170 data_len - SRID_SIZE - WKB_HEADER_SIZE);
175 Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer,
182 if (trs->get_next_word(&name))
184 trs->set_error_msg(
"Geometry name expected");
187 if (!(ci= find_class(name.str, name.length)) ||
188 wkt->reserve(WKB_HEADER_SIZE, 512))
190 Geometry *result= (*ci->m_create_func)(buffer->data);
191 wkt->q_append((
char) wkb_ndr);
192 wkt->q_append((uint32) result->get_class_info()->m_type_id);
193 if (trs->check_next_symbol(
'(') ||
194 result->init_from_wkt(trs, wkt) ||
195 trs->check_next_symbol(
')'))
198 result->set_data_ptr(wkt->ptr() + WKB_HEADER_SIZE,
199 wkt->length() - WKB_HEADER_SIZE);
204 static double wkb_get_double(
const char *ptr, Geometry::wkbByteOrder bo)
207 if (bo != Geometry::wkb_xdr)
214 inv_array[0]= ptr[7];
215 inv_array[1]= ptr[6];
216 inv_array[2]= ptr[5];
217 inv_array[3]= ptr[4];
218 inv_array[4]= ptr[3];
219 inv_array[5]= ptr[2];
220 inv_array[6]= ptr[1];
221 inv_array[7]= ptr[0];
222 float8get(res, inv_array);
228 static uint32 wkb_get_uint(
const char *ptr, Geometry::wkbByteOrder bo)
230 if (bo != Geometry::wkb_xdr)
231 return uint4korr(ptr);
234 char inv_array[4], *inv_array_p= inv_array;
235 inv_array[0]= ptr[3];
236 inv_array[1]= ptr[2];
237 inv_array[2]= ptr[1];
238 inv_array[3]= ptr[0];
239 return uint4korr(inv_array_p);
244 Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer,
245 const char *wkb, uint32 len,
String *res)
250 if (len < WKB_HEADER_SIZE)
252 geom_type= wkb_get_uint(wkb+1, (wkbByteOrder)wkb[0]);
253 if (!(geom= create_by_typeid(buffer, (
int) geom_type)) ||
254 res->reserve(WKB_HEADER_SIZE, 512))
257 res->q_append((
char) wkb_ndr);
258 res->q_append(geom_type);
260 return geom->init_from_wkb(wkb + WKB_HEADER_SIZE, len - WKB_HEADER_SIZE,
261 (wkbByteOrder) wkb[0], res) ? geom : NULL;
265 int Geometry::create_from_opresult(Geometry_buffer *g_buf,
268 uint32 geom_type= rr.get_result_typeid();
269 Geometry *obj= create_by_typeid(g_buf, geom_type);
271 if (!obj || res->reserve(WKB_HEADER_SIZE, 512))
274 res->q_append((
char) wkb_ndr);
275 res->q_append(geom_type);
276 return obj->init_from_opresult(res, rr.result(), rr.length());
280 bool Geometry::envelope(
String *result)
const
283 wkb_parser wkb(&m_wkb_data);
285 if (get_mbr(&mbr, &wkb) ||
286 result->reserve(1 + 4 * 3 + SIZEOF_STORED_DOUBLE * 10))
289 result->q_append((
char) wkb_ndr);
290 result->q_append((uint32) wkb_polygon);
291 result->q_append((uint32) 1);
292 result->q_append((uint32) 5);
293 result->q_append(mbr.xmin);
294 result->q_append(mbr.ymin);
295 result->q_append(mbr.xmax);
296 result->q_append(mbr.ymin);
297 result->q_append(mbr.xmax);
298 result->q_append(mbr.ymax);
299 result->q_append(mbr.xmin);
300 result->q_append(mbr.ymax);
301 result->q_append(mbr.xmin);
302 result->q_append(mbr.ymin);
317 bool Geometry::create_point(
String *result, wkb_parser *wkb)
const
319 if (wkb->no_data(POINT_DATA_SIZE) ||
320 result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
322 result->q_append((
char) wkb_ndr);
323 result->q_append((uint32) wkb_point);
325 result->q_append(wkb->data(), POINT_DATA_SIZE);
339 bool Geometry::create_point(
String *result, point_xy p)
const
341 if (result->reserve(1 + 4 + POINT_DATA_SIZE))
344 result->q_append((
char) wkb_ndr);
345 result->q_append((uint32) wkb_point);
346 result->q_append(p.x);
347 result->q_append(p.y);
360 void Geometry::append_points(
String *txt, uint32 n_points,
361 wkb_parser *wkb, uint32
offset)
const
366 wkb->skip_unsafe(offset);
367 wkb->scan_xy_unsafe(&p);
386 bool Geometry::get_mbr_for_points(MBR *mbr, wkb_parser *wkb,
391 if (wkb->scan_n_points_and_check_data(&n_points, offset))
397 wkb->skip_unsafe(offset);
398 mbr->add_xy(wkb->data(), wkb->data() + SIZEOF_STORED_DOUBLE);
399 wkb->skip_unsafe(POINT_DATA_SIZE);
407 Geometry *collection_item)
const
410 wkb_parser wkb(&m_wkb_data);
411 Geometry_buffer buffer;
413 if (wkb.scan_non_zero_uint4(&n_objects) ||
414 trn->start_collection(st, n_objects))
420 if (!(geom= collection_item))
427 if (!(geom= scan_header_and_create(&wkb, &buffer)))
432 if (wkb.skip_wkb_header())
434 geom->set_data_ptr(&wkb);
437 if (geom->store_shapes(trn, &item_status) ||
438 trn->collection_add_item(st, &item_status))
440 wkb.skip_unsafe(geom->get_data_size());
442 trn->complete_collection(st);
447 bool Geometry::collection_area(
double *ar, wkb_parser *wkb,
448 Geometry *collection_item)
const
451 Geometry_buffer buffer;
453 if (wkb->scan_non_zero_uint4(&n_objects))
456 for (*ar= 0; n_objects; n_objects--)
459 if (!(geom= collection_item))
465 if (!(geom= scan_header_and_create(wkb, &buffer)))
470 if (wkb->skip_wkb_header())
472 geom->set_data_ptr(wkb);
475 if (geom->area(&item_area, wkb))
483 uint Geometry::collection_init_from_opresult(
String *bin,
486 Geometry *collection_item)
488 Geometry_buffer buffer;
489 const char *opres_orig= opres;
490 int n_items_offs= bin->length();
493 if (bin->reserve(4, 512))
495 bin->q_append((uint32) 0);
501 if (bin->reserve(WKB_HEADER_SIZE, 512))
511 item= collection_item;
520 switch ((Gcalc_function::shape_type) uint4korr(opres))
522 case Gcalc_function::shape_point: wkb_type= wkb_point;
break;
523 case Gcalc_function::shape_line: wkb_type= wkb_linestring;
break;
524 case Gcalc_function::shape_polygon: wkb_type= wkb_polygon;
break;
531 my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"spatial self-intersecting operands");
534 if (!(item= create_by_typeid(&buffer, wkb_type)))
538 bin->q_append((
char) wkb_ndr);
539 bin->q_append((uint32) item->get_class_info()->m_type_id);
541 if (!(item_len= item->init_from_opresult(bin, opres, opres_length)))
544 opres_length-= item_len;
547 bin->write_at_position(n_items_offs, n_items);
548 return (uint) (opres - opres_orig);
554 uint32 Gis_point::get_data_size()
const
556 return POINT_DATA_SIZE;
563 if (trs->get_next_number(&x) || trs->get_next_number(&y) ||
564 wkb->reserve(POINT_DATA_SIZE))
572 uint Gis_point::init_from_wkb(
const char *wkb, uint len,
573 wkbByteOrder bo,
String *res)
576 if (len < POINT_DATA_SIZE || res->reserve(POINT_DATA_SIZE))
578 x= wkb_get_double(wkb, bo);
579 y= wkb_get_double(wkb + SIZEOF_STORED_DOUBLE, bo);
582 return POINT_DATA_SIZE;
586 bool Gis_point::get_data_as_wkt(
String *txt, wkb_parser *wkb)
const
589 if (wkb->scan_xy(&p))
591 if (txt->reserve(MAX_DIGITS_IN_DOUBLE * 2 + 1))
600 bool Gis_point::get_mbr(MBR *mbr, wkb_parser *wkb)
const
603 if (wkb->scan_xy(&p))
613 if (trn->skip_point())
615 wkb_parser wkb(&m_wkb_data);
617 return wkb.scan_xy(&p) || trn->single_point(st, p.x, p.y);
621 const Geometry::Class_info *Gis_point::get_class_info()
const
629 uint32 Gis_line_string::get_data_size()
const
632 wkb_parser wkb(&m_wkb_data);
633 if (wkb.scan_n_points_and_check_data(&n_points))
634 return GET_SIZE_ERROR;
636 return 4 + n_points * POINT_DATA_SIZE;
643 uint32 np_pos= wkb->length();
646 if (wkb->reserve(4, 512))
648 wkb->length(wkb->length()+4);
652 if (p.init_from_wkt(trs, wkb))
655 if (trs->skip_char(
','))
660 trs->set_error_msg(
"Too few points in LINESTRING");
663 wkb->write_at_position(np_pos, n_points);
668 uint Gis_line_string::init_from_wkb(
const char *wkb, uint len,
669 wkbByteOrder bo,
String *res)
671 uint32 n_points, proper_length;
676 (n_points= wkb_get_uint(wkb, bo)) < 1 ||
677 n_points > max_n_points)
679 proper_length= 4 + n_points * POINT_DATA_SIZE;
681 if (len < proper_length || res->reserve(proper_length))
684 res->q_append(n_points);
685 wkb_end= wkb + proper_length;
686 for (wkb+= 4; wkb<wkb_end; wkb+= POINT_DATA_SIZE)
688 if (!p.init_from_wkb(wkb, POINT_DATA_SIZE, bo, res))
692 return proper_length;
696 bool Gis_line_string::get_data_as_wkt(
String *txt, wkb_parser *wkb)
const
699 if (wkb->scan_n_points_and_check_data(&n_points) ||
700 txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
706 wkb->scan_xy_unsafe(&p);
712 txt->length(txt->length() - 1);
717 bool Gis_line_string::get_mbr(MBR *mbr, wkb_parser *wkb)
const
719 return get_mbr_for_points(mbr, wkb, 0);
723 int Gis_line_string::geom_length(
double *len)
const
726 wkb_parser wkb(&m_wkb_data);
729 if (wkb.scan_n_points_and_check_data(&n_points))
733 wkb.scan_xy_unsafe(&prev);
737 wkb.scan_xy_unsafe(&p);
738 *len+= prev.distance(p);
745 int Gis_line_string::is_closed(
int *closed)
const
748 wkb_parser wkb(&m_wkb_data);
750 if (wkb.scan_n_points_and_check_data(&n_points))
762 wkb.scan_xy_unsafe(&p1);
765 wkb.skip_unsafe((n_points - 2) * POINT_DATA_SIZE);
766 wkb.scan_xy_unsafe(&p2);
773 int Gis_line_string::num_points(uint32 *n_points)
const
775 wkb_parser wkb(&m_wkb_data);
776 return wkb.scan_uint4(n_points) ? 1 : 0;
780 int Gis_line_string::start_point(
String *result)
const
783 wkb_parser wkb(&m_wkb_data);
784 if (wkb.scan_n_points_and_check_data(&n_points))
786 return create_point(result, &wkb);
790 int Gis_line_string::end_point(
String *result)
const
793 wkb_parser wkb(&m_wkb_data);
794 if (wkb.scan_n_points_and_check_data(&n_points))
796 wkb.skip_unsafe((n_points - 1) * POINT_DATA_SIZE);
797 return create_point(result, &wkb);
801 int Gis_line_string::point_n(uint32 num,
String *result)
const
804 wkb_parser wkb(&m_wkb_data);
806 wkb.scan_n_points_and_check_data(&n_points) ||
809 wkb.skip_unsafe((num - 1) * POINT_DATA_SIZE);
810 return create_point(result, &wkb);
818 wkb_parser wkb(&m_wkb_data);
820 if (trn->skip_line_string())
823 if (wkb.scan_n_points_and_check_data(&n_points))
830 wkb.scan_xy_unsafe(&p);
831 if (trn->add_point(st, p.x, p.y))
834 return trn->complete_line(st);
838 const Geometry::Class_info *Gis_line_string::get_class_info()
const
840 return &linestring_class;
846 uint32 Gis_polygon::get_data_size()
const
848 uint32 n_linear_rings;
849 wkb_parser wkb(&m_wkb_data);
851 if (wkb.scan_non_zero_uint4(&n_linear_rings))
852 return GET_SIZE_ERROR;
854 while (n_linear_rings--)
857 if (wkb.scan_n_points_and_check_data(&n_points))
858 return GET_SIZE_ERROR;
859 wkb.skip_unsafe(n_points * POINT_DATA_SIZE);
861 return (uint32) (wkb.data() - m_wkb_data.data());
867 uint32 n_linear_rings= 0;
868 uint32 lr_pos= wkb->length();
871 if (wkb->reserve(4, 512))
873 wkb->length(wkb->length()+4);
877 uint32 ls_pos=wkb->length();
878 if (trs->check_next_symbol(
'(') ||
879 ls.init_from_wkt(trs, wkb) ||
880 trs->check_next_symbol(
')'))
883 ls.set_data_ptr(wkb->ptr() + ls_pos, wkb->length() - ls_pos);
884 if (ls.is_closed(&closed) || !closed)
886 trs->set_error_msg(
"POLYGON's linear ring isn't closed");
890 if (trs->skip_char(
','))
893 wkb->write_at_position(lr_pos, n_linear_rings);
898 uint Gis_polygon::init_from_opresult(
String *bin,
899 const char *opres, uint opres_length)
901 const char *opres_orig= opres;
902 const char *opres_end= opres + opres_length;
903 uint32 position= bin->length();
904 uint32 poly_shapes= 0;
906 if (bin->reserve(4, 512))
908 bin->q_append(poly_shapes);
910 while (opres < opres_end)
912 uint32 n_points, proper_length;
913 const char *op_end, *p1_position;
915 Gcalc_function::shape_type st;
917 st= (Gcalc_function::shape_type) uint4korr(opres);
918 if (poly_shapes && st != Gcalc_function::shape_hole)
921 n_points= uint4korr(opres + 4) + 1;
922 proper_length= 4 + n_points * POINT_DATA_SIZE;
924 if (bin->reserve(proper_length, 512))
927 bin->q_append(n_points);
928 op_end= opres + 8 + (n_points-1) * 8 * 2;
929 p1_position= (opres+= 8);
930 for (; opres<op_end; opres+= POINT_DATA_SIZE)
932 if (!p.init_from_wkb(opres, POINT_DATA_SIZE, wkb_ndr, bin))
935 if (!p.init_from_wkb(p1_position, POINT_DATA_SIZE, wkb_ndr, bin))
939 bin->write_at_position(position, poly_shapes);
941 return (uint) (opres - opres_orig);
945 uint Gis_polygon::init_from_wkb(
const char *wkb, uint len, wkbByteOrder bo,
948 uint32 n_linear_rings;
949 const char *wkb_orig= wkb;
954 if (0 == (n_linear_rings= wkb_get_uint(wkb, bo)) ||
955 res->reserve(4, 512))
959 res->q_append(n_linear_rings);
961 while (n_linear_rings--)
964 uint32 ls_pos= res->length();
968 if (!(ls_len= ls.init_from_wkb(wkb, len, bo, res)))
971 ls.set_data_ptr(res->ptr() + ls_pos, res->length() - ls_pos);
973 if (ls.is_closed(&closed) || !closed)
978 return (uint) (wkb - wkb_orig);
982 bool Gis_polygon::get_data_as_wkt(
String *txt, wkb_parser *wkb)
const
984 uint32 n_linear_rings;
986 if (wkb->scan_non_zero_uint4(&n_linear_rings))
989 while (n_linear_rings--)
992 if (wkb->scan_n_points_and_check_data(&n_points) ||
993 txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
996 append_points(txt, n_points, wkb, 0);
997 (*txt) [txt->length() - 1]=
')';
1000 txt->length(txt->length() - 1);
1005 bool Gis_polygon::get_mbr(MBR *mbr, wkb_parser *wkb)
const
1007 uint32 n_linear_rings;
1009 if (wkb->scan_non_zero_uint4(&n_linear_rings))
1012 while (n_linear_rings--)
1014 if (get_mbr_for_points(mbr, wkb, 0))
1021 bool Gis_polygon::area(
double *ar, wkb_parser *wkb)
const
1023 uint32 n_linear_rings;
1024 double result= -1.0;
1026 if (wkb->scan_non_zero_uint4(&n_linear_rings))
1029 while (n_linear_rings--)
1034 if (wkb->scan_n_points_and_check_data(&n_points))
1037 wkb->scan_xy_unsafe(&prev);
1042 wkb->scan_xy_unsafe(&p);
1043 lr_area+= (prev.x + p.x) * (prev.y - p.y);
1046 lr_area= fabs(lr_area)/2;
1057 int Gis_polygon::exterior_ring(
String *result)
const
1059 uint32 n_points, n_linear_rings, length;
1060 wkb_parser wkb(&m_wkb_data);
1062 if (wkb.scan_non_zero_uint4(&n_linear_rings) ||
1063 wkb.scan_n_points_and_check_data(&n_points))
1065 length= n_points * POINT_DATA_SIZE;
1066 if (result->reserve(1 + 4 + 4 + length))
1069 result->q_append((
char) wkb_ndr);
1070 result->q_append((uint32) wkb_linestring);
1071 result->q_append(n_points);
1072 result->q_append(wkb.data(), length);
1077 int Gis_polygon::num_interior_ring(uint32 *n_int_rings)
const
1079 wkb_parser wkb(&m_wkb_data);
1080 if (wkb.scan_non_zero_uint4(n_int_rings))
1087 int Gis_polygon::interior_ring_n(uint32 num,
String *result)
const
1089 wkb_parser wkb(&m_wkb_data);
1090 uint32 n_linear_rings;
1095 wkb.scan_non_zero_uint4(&n_linear_rings) ||
1096 num >= n_linear_rings)
1101 if (wkb.scan_n_points_and_check_data(&n_points))
1103 wkb.skip_unsafe(n_points * POINT_DATA_SIZE);
1105 if (wkb.scan_n_points_and_check_data(&n_points))
1107 points_size= n_points * POINT_DATA_SIZE;
1108 if (result->reserve(1 + 4 + 4 + points_size))
1111 result->q_append((
char) wkb_ndr);
1112 result->q_append((uint32) wkb_linestring);
1113 result->q_append(n_points);
1114 result->q_append(wkb.data(), points_size);
1119 bool Gis_polygon::centroid_xy(point_xy *p)
const
1121 uint32 n_linear_rings;
1122 double UNINIT_VAR(res_area);
1124 wkb_parser wkb(&m_wkb_data);
1127 if (wkb.scan_non_zero_uint4(&n_linear_rings))
1130 while (n_linear_rings--)
1132 uint32 n_points, org_n_points;
1134 point_xy prev, cur(0, 0);
1136 if (wkb.scan_n_points_and_check_data(&n_points))
1139 org_n_points= n_points - 1;
1140 wkb.scan_xy_unsafe(&prev);
1145 wkb.scan_xy_unsafe(&tmp);
1146 cur_area+= (prev.x + tmp.x) * (prev.y - tmp.y);
1151 cur_area= fabs(cur_area) / 2;
1152 cur.x= cur.x / org_n_points;
1153 cur.y= cur.y / org_n_points;
1157 double d_area= fabs(res_area - cur_area);
1158 res.x= (res_area * res.x - cur_area * cur.x) / d_area;
1159 res.y= (res_area * res.y - cur_area * cur.y) / d_area;
1174 int Gis_polygon::centroid(
String *result)
const
1177 if (centroid_xy(&p))
1179 return create_point(result, p);
1186 uint32 n_linear_rings;
1187 wkb_parser wkb(&m_wkb_data);
1189 if (trn->skip_poly())
1192 if (trn->start_poly(st))
1195 if (wkb.scan_non_zero_uint4(&n_linear_rings))
1198 while (n_linear_rings--)
1202 if (wkb.scan_n_points_and_check_data(&n_points))
1205 trn->start_ring(st);
1209 wkb.scan_xy_unsafe(&p);
1210 if (trn->add_point(st, p.x, p.y))
1213 wkb.skip_unsafe(POINT_DATA_SIZE);
1214 trn->complete_ring(st);
1217 trn->complete_poly(st);
1222 const Geometry::Class_info *Gis_polygon::get_class_info()
const
1224 return &polygon_class;
1230 uint32 Gis_multi_point::get_data_size()
const
1233 wkb_parser wkb(&m_wkb_data);
1234 if (wkb.scan_n_points_and_check_data(&n_points, WKB_HEADER_SIZE))
1235 return GET_SIZE_ERROR;
1237 return 4 + n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE);
1244 uint32 np_pos= wkb->length();
1247 if (wkb->reserve(4, 512))
1249 wkb->length(wkb->length()+4);
1253 if (wkb->reserve(1 + 4, 512))
1255 wkb->q_append((
char) wkb_ndr);
1256 wkb->q_append((uint32) wkb_point);
1257 if (p.init_from_wkt(trs, wkb))
1260 if (trs->skip_char(
','))
1263 wkb->write_at_position(np_pos, n_points);
1268 uint Gis_multi_point::init_from_opresult(
String *bin,
1269 const char *opres, uint opres_length)
1271 uint bin_size, n_points;
1273 const char *opres_end;
1275 n_points= opres_length / (4 + 8 * 2);
1276 bin_size= n_points * (WKB_HEADER_SIZE + POINT_DATA_SIZE) + 4;
1278 if (bin->reserve(bin_size, 512))
1281 bin->q_append(n_points);
1282 opres_end= opres + opres_length;
1283 for (; opres < opres_end; opres+= (4 + 8*2))
1285 bin->q_append((
char)wkb_ndr);
1286 bin->q_append((uint32)wkb_point);
1287 if (!p.init_from_wkb(opres + 4, POINT_DATA_SIZE, wkb_ndr, bin))
1290 return opres_length;
1294 uint Gis_multi_point::init_from_wkb(
const char *wkb, uint len, wkbByteOrder bo,
1300 const char *wkb_end;
1303 (n_points= wkb_get_uint(wkb, bo)) > max_n_points)
1305 proper_size= 4 + n_points * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
1307 if (len < proper_size || res->reserve(proper_size))
1310 res->q_append(n_points);
1311 wkb_end= wkb + proper_size;
1312 for (wkb+=4; wkb < wkb_end; wkb+= (WKB_HEADER_SIZE + POINT_DATA_SIZE))
1314 res->q_append((
char)wkb_ndr);
1315 res->q_append((uint32)wkb_point);
1316 if (!p.init_from_wkb(wkb + WKB_HEADER_SIZE,
1317 POINT_DATA_SIZE, (wkbByteOrder) wkb[0], res))
1324 bool Gis_multi_point::get_data_as_wkt(
String *txt, wkb_parser *wkb)
const
1328 if (wkb->scan_n_points_and_check_data(&n_points, WKB_HEADER_SIZE) ||
1329 txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
1332 append_points(txt, n_points, wkb, WKB_HEADER_SIZE);
1333 txt->length(txt->length()-1);
1338 bool Gis_multi_point::get_mbr(MBR *mbr, wkb_parser *wkb)
const
1340 return get_mbr_for_points(mbr, wkb, WKB_HEADER_SIZE);
1344 int Gis_multi_point::num_geometries(uint32 *num)
const
1346 wkb_parser wkb(&m_wkb_data);
1347 return wkb.scan_non_zero_uint4(num) ? 1 : 0;
1351 int Gis_multi_point::geometry_n(uint32 num,
String *result)
const
1354 wkb_parser wkb(&m_wkb_data);
1357 wkb.scan_n_points_and_check_data(&n_points, WKB_HEADER_SIZE) ||
1359 result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
1361 wkb.skip_unsafe((num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE));
1363 result->q_append(wkb.data(), WKB_HEADER_SIZE + POINT_DATA_SIZE);
1371 if (trn->skip_point())
1374 return collection_store_shapes(trn, st, &pt);
1378 const Geometry::Class_info *Gis_multi_point::get_class_info()
const
1380 return &multipoint_class;
1386 uint32 Gis_multi_line_string::get_data_size()
const
1388 uint32 n_line_strings;
1389 wkb_parser wkb(&m_wkb_data);
1391 if (wkb.scan_non_zero_uint4(&n_line_strings))
1392 return GET_SIZE_ERROR;
1394 while (n_line_strings--)
1398 if (wkb.skip_wkb_header() ||
1399 wkb.scan_n_points_and_check_data(&n_points))
1400 return GET_SIZE_ERROR;
1402 wkb.skip_unsafe(n_points * POINT_DATA_SIZE);
1404 return (uint32) (wkb.data() - m_wkb_data.data());
1410 uint32 n_line_strings= 0;
1411 uint32 ls_pos= wkb->length();
1413 if (wkb->reserve(4, 512))
1415 wkb->length(wkb->length()+4);
1421 if (wkb->reserve(1 + 4, 512))
1423 wkb->q_append((
char) wkb_ndr); wkb->q_append((uint32) wkb_linestring);
1425 if (trs->check_next_symbol(
'(') ||
1426 ls.init_from_wkt(trs, wkb) ||
1427 trs->check_next_symbol(
')'))
1430 if (trs->skip_char(
','))
1433 wkb->write_at_position(ls_pos, n_line_strings);
1438 uint Gis_multi_line_string::init_from_opresult(
String *bin,
1442 Gis_line_string item;
1443 return collection_init_from_opresult(bin, opres, opres_length, &item);
1447 uint Gis_multi_line_string::init_from_wkb(
const char *wkb, uint len,
1448 wkbByteOrder bo,
String *res)
1450 uint32 n_line_strings;
1451 const char *wkb_orig= wkb;
1454 (n_line_strings= wkb_get_uint(wkb, bo))< 1)
1457 if (res->reserve(4, 512))
1459 res->q_append(n_line_strings);
1462 while (n_line_strings--)
1467 if ((len < WKB_HEADER_SIZE) ||
1468 res->reserve(WKB_HEADER_SIZE, 512))
1471 res->q_append((
char) wkb_ndr);
1472 res->q_append((uint32) wkb_linestring);
1474 if (!(ls_len= ls.init_from_wkb(wkb + WKB_HEADER_SIZE, len,
1475 (wkbByteOrder) wkb[0], res)))
1477 ls_len+= WKB_HEADER_SIZE;;
1481 return (uint) (wkb - wkb_orig);
1485 bool Gis_multi_line_string::get_data_as_wkt(
String *txt, wkb_parser *wkb)
const
1487 uint32 n_line_strings;
1489 if (wkb->scan_non_zero_uint4(&n_line_strings))
1492 while (n_line_strings--)
1496 if (wkb->skip_wkb_header() ||
1497 wkb->scan_n_points_and_check_data(&n_points) ||
1498 txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
1500 txt->qs_append(
'(');
1501 append_points(txt, n_points, wkb, 0);
1502 (*txt) [txt->length() - 1]=
')';
1503 txt->qs_append(
',');
1505 txt->length(txt->length() - 1);
1510 bool Gis_multi_line_string::get_mbr(MBR *mbr, wkb_parser *wkb)
const
1512 uint32 n_line_strings;
1514 if (wkb->scan_non_zero_uint4(&n_line_strings))
1517 while (n_line_strings--)
1519 if (wkb->skip_wkb_header() ||
1520 get_mbr_for_points(mbr, wkb, 0))
1527 int Gis_multi_line_string::num_geometries(uint32 *num)
const
1529 wkb_parser wkb(&m_wkb_data);
1530 return wkb.scan_non_zero_uint4(num) ? 1 : 0;
1534 int Gis_multi_line_string::geometry_n(uint32 num,
String *result)
const
1536 uint32 n_line_strings, n_points, length;
1537 wkb_parser wkb(&m_wkb_data);
1539 if (wkb.scan_non_zero_uint4(&n_line_strings))
1542 if ((num > n_line_strings) || (num < 1))
1547 if (wkb.skip_wkb_header() ||
1548 wkb.scan_n_points_and_check_data(&n_points))
1550 length= POINT_DATA_SIZE * n_points;
1553 wkb.skip_unsafe(length);
1555 return result->append(wkb.data() - 4 - WKB_HEADER_SIZE,
1556 length + 4 + WKB_HEADER_SIZE, (uint32) 0);
1560 int Gis_multi_line_string::geom_length(
double *len)
const
1562 uint32 n_line_strings;
1563 wkb_parser wkb(&m_wkb_data);
1565 if (wkb.scan_non_zero_uint4(&n_line_strings))
1569 while (n_line_strings--)
1573 if (wkb.skip_wkb_header())
1575 ls.set_data_ptr(&wkb);
1576 if (ls.geom_length(&ls_len))
1583 wkb.skip_unsafe(ls.get_data_size());
1589 int Gis_multi_line_string::is_closed(
int *closed)
const
1591 uint32 n_line_strings;
1592 wkb_parser wkb(&m_wkb_data);
1594 if (wkb.scan_non_zero_uint4(&n_line_strings))
1597 while (n_line_strings--)
1600 if (wkb.skip_wkb_header())
1602 ls.set_data_ptr(&wkb);
1603 if (ls.is_closed(closed))
1607 wkb.skip_unsafe(ls.get_data_size());
1616 if (trn->skip_line_string())
1619 return collection_store_shapes(trn, st, &ls);
1623 const Geometry::Class_info *Gis_multi_line_string::get_class_info()
const
1625 return &multilinestring_class;
1631 uint32 Gis_multi_polygon::get_data_size()
const
1634 wkb_parser wkb(&m_wkb_data);
1636 if (wkb.scan_non_zero_uint4(&n_polygons))
1637 return GET_SIZE_ERROR;
1639 while (n_polygons--)
1641 uint32 n_linear_rings;
1642 if (wkb.skip_wkb_header() ||
1643 wkb.scan_non_zero_uint4(&n_linear_rings))
1644 return GET_SIZE_ERROR;
1646 while (n_linear_rings--)
1650 if (wkb.scan_n_points_and_check_data(&n_points))
1651 return GET_SIZE_ERROR;
1653 wkb.skip_unsafe(n_points * POINT_DATA_SIZE);
1656 return (uint32) (wkb.data() - m_wkb_data.data());
1662 uint32 n_polygons= 0;
1663 int np_pos= wkb->length();
1666 if (wkb->reserve(4, 512))
1668 wkb->length(wkb->length()+4);
1672 if (wkb->reserve(1 + 4, 512))
1674 wkb->q_append((
char) wkb_ndr);
1675 wkb->q_append((uint32) wkb_polygon);
1677 if (trs->check_next_symbol(
'(') ||
1678 p.init_from_wkt(trs, wkb) ||
1679 trs->check_next_symbol(
')'))
1682 if (trs->skip_char(
','))
1685 wkb->write_at_position(np_pos, n_polygons);
1690 uint Gis_multi_polygon::init_from_wkb(
const char *wkb, uint len,
1691 wkbByteOrder bo,
String *res)
1694 const char *wkb_orig= wkb;
1698 n_poly= wkb_get_uint(wkb, bo);
1700 if (res->reserve(4, 512))
1702 res->q_append(n_poly);
1710 if (len < WKB_HEADER_SIZE ||
1711 res->reserve(WKB_HEADER_SIZE, 512))
1713 res->q_append((
char) wkb_ndr);
1714 res->q_append((uint32) wkb_polygon);
1716 if (!(p_len= p.init_from_wkb(wkb + WKB_HEADER_SIZE, len,
1717 (wkbByteOrder) wkb[0], res)))
1719 p_len+= WKB_HEADER_SIZE;
1723 return (uint) (wkb - wkb_orig);
1727 uint Gis_multi_polygon::init_from_opresult(
String *bin,
1728 const char *opres, uint opres_length)
1731 return collection_init_from_opresult(bin, opres, opres_length, &item);
1735 bool Gis_multi_polygon::get_data_as_wkt(
String *txt, wkb_parser *wkb)
const
1739 if (wkb->scan_non_zero_uint4(&n_polygons))
1742 while (n_polygons--)
1744 uint32 n_linear_rings;
1746 if (wkb->skip_wkb_header() ||
1747 wkb->scan_non_zero_uint4(&n_linear_rings) ||
1748 txt->reserve(1, 512))
1752 while (n_linear_rings--)
1755 if (wkb->scan_n_points_and_check_data(&n_points) ||
1756 txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points, 512))
1758 txt->qs_append(
'(');
1759 append_points(txt, n_points, wkb, 0);
1760 (*txt) [txt->length() - 1]=
')';
1761 txt->qs_append(
',');
1763 (*txt) [txt->length() - 1]=
')';
1764 txt->qs_append(
',');
1766 txt->length(txt->length() - 1);
1771 bool Gis_multi_polygon::get_mbr(MBR *mbr, wkb_parser *wkb)
const
1775 if (wkb->scan_non_zero_uint4(&n_polygons))
1778 while (n_polygons--)
1780 uint32 n_linear_rings;
1781 if (wkb->skip_wkb_header() ||
1782 wkb->scan_non_zero_uint4(&n_linear_rings))
1785 while (n_linear_rings--)
1787 if (get_mbr_for_points(mbr, wkb, 0))
1795 int Gis_multi_polygon::num_geometries(uint32 *num)
const
1797 wkb_parser wkb(&m_wkb_data);
1798 return wkb.scan_non_zero_uint4(num) ? 1 : 0;
1802 int Gis_multi_polygon::geometry_n(uint32 num,
String *result)
const
1805 wkb_parser wkb(&m_wkb_data);
1806 const char *start_of_polygon= wkb.data();
1808 if (wkb.scan_non_zero_uint4(&n_polygons))
1811 if (num > n_polygons || num < 1)
1816 uint32 n_linear_rings;
1817 start_of_polygon= wkb.data();
1819 if (wkb.skip_wkb_header() ||
1820 wkb.scan_non_zero_uint4(&n_linear_rings))
1823 while (n_linear_rings--)
1826 if (wkb.scan_n_points_and_check_data(&n_points))
1828 wkb.skip_unsafe(POINT_DATA_SIZE * n_points);
1833 return result->append(start_of_polygon,
1834 (uint32) (wkb.data() - start_of_polygon),
1839 bool Gis_multi_polygon::area(
double *ar, wkb_parser *wkb)
const
1842 return collection_area(ar, wkb, &p);
1846 int Gis_multi_polygon::centroid(
String *result)
const
1851 double UNINIT_VAR(res_area);
1853 wkb_parser wkb(&m_wkb_data);
1855 if (wkb.scan_non_zero_uint4(&n_polygons))
1858 while (n_polygons--)
1862 if (wkb.skip_wkb_header())
1864 p.set_data_ptr(&wkb);
1865 if (p.area(&cur_area, &wkb) ||
1866 p.centroid_xy(&cur))
1871 double sum_area= res_area + cur_area;
1872 res.x= (res_area * res.x + cur_area * cur.x) / sum_area;
1873 res.y= (res_area * res.y + cur_area * cur.y) / sum_area;
1882 return create_point(result, res);
1889 if (trn->skip_poly())
1892 return collection_store_shapes(trn, st, &p);
1896 const Geometry::Class_info *Gis_multi_polygon::get_class_info()
const
1898 return &multipolygon_class;
1904 uint32 Gis_geometry_collection::get_data_size()
const
1907 wkb_parser wkb(&m_wkb_data);
1908 Geometry_buffer buffer;
1911 if (wkb.scan_non_zero_uint4(&n_objects))
1912 return GET_SIZE_ERROR;
1916 if (!(geom= scan_header_and_create(&wkb, &buffer)))
1917 return GET_SIZE_ERROR;
1920 if ((object_size= geom->get_data_size()) == GET_SIZE_ERROR)
1921 return GET_SIZE_ERROR;
1922 wkb.skip_unsafe(object_size);
1924 return (uint32) (wkb.data() - m_wkb_data.data());
1930 uint32 n_objects= 0;
1931 uint32 no_pos= wkb->length();
1932 Geometry_buffer buffer;
1935 if (wkb->reserve(4, 512))
1937 wkb->length(wkb->length()+4);
1941 if (!(g= create_from_wkt(&buffer, trs, wkb)))
1944 if (g->get_class_info()->m_type_id == wkb_geometrycollection)
1946 trs->set_error_msg(
"Unexpected GEOMETRYCOLLECTION");
1950 if (trs->skip_char(
','))
1954 wkb->write_at_position(no_pos, n_objects);
1959 uint Gis_geometry_collection::init_from_opresult(
String *bin,
1963 return collection_init_from_opresult(bin, opres, opres_length, NULL);
1967 uint Gis_geometry_collection::init_from_wkb(
const char *wkb, uint len,
1968 wkbByteOrder bo,
String *res)
1971 const char *wkb_orig= wkb;
1975 n_geom= wkb_get_uint(wkb, bo);
1977 if (res->reserve(4, 512))
1979 res->q_append(n_geom);
1984 Geometry_buffer buffer;
1989 if (len < WKB_HEADER_SIZE ||
1990 res->reserve(WKB_HEADER_SIZE, 512))
1993 res->q_append((
char) wkb_ndr);
1994 wkb_type= wkb_get_uint(wkb+1, (wkbByteOrder) wkb[0]);
1995 res->q_append(wkb_type);
1997 if (!(geom= create_by_typeid(&buffer, wkb_type)) ||
1998 !(g_len= geom->init_from_wkb(wkb + WKB_HEADER_SIZE, len,
1999 (wkbByteOrder) wkb[0], res)))
2001 g_len+= WKB_HEADER_SIZE;
2005 return (uint) (wkb - wkb_orig);
2009 bool Gis_geometry_collection::get_data_as_wkt(
String *txt,
2010 wkb_parser *wkb)
const
2013 Geometry_buffer buffer;
2016 if (wkb->scan_non_zero_uint4(&n_objects))
2021 if (!(geom= scan_header_and_create(wkb, &buffer)) ||
2022 geom->as_wkt(txt, wkb) ||
2023 txt->append(STRING_WITH_LEN(
","), 512))
2026 txt->length(txt->length() - 1);
2031 bool Gis_geometry_collection::get_mbr(MBR *mbr, wkb_parser *wkb)
const
2034 Geometry_buffer buffer;
2037 if (wkb->scan_non_zero_uint4(&n_objects))
2042 if (!(geom= scan_header_and_create(wkb, &buffer)) ||
2043 geom->get_mbr(mbr, wkb))
2050 bool Gis_geometry_collection::area(
double *ar, wkb_parser *wkb)
const
2052 return collection_area(ar, wkb, NULL);
2056 int Gis_geometry_collection::num_geometries(uint32 *num)
const
2058 wkb_parser wkb(&m_wkb_data);
2059 return wkb.scan_non_zero_uint4(num) ? 1 : 0;
2063 int Gis_geometry_collection::geometry_n(uint32 num,
String *result)
const
2065 uint32 n_objects, length;
2066 wkb_parser wkb(&m_wkb_data);
2067 Geometry_buffer buffer;
2070 if (wkb.scan_non_zero_uint4(&n_objects))
2073 if (num > n_objects || num < 1)
2079 if (wkb.scan_wkb_header(&header) ||
2080 !(geom= create_by_typeid(&buffer, header.wkb_type)))
2082 geom->set_data_ptr(&wkb);
2083 if ((length= geom->get_data_size()) == GET_SIZE_ERROR)
2085 wkb.skip_unsafe(length);
2089 if (result->reserve(1 + 4 + length))
2091 result->q_append((
char) wkb_ndr);
2092 result->q_append((uint32) header.wkb_type);
2093 result->q_append(wkb.data() - length, length);
2111 bool Gis_geometry_collection::dimension(uint32 *res_dim,
2112 wkb_parser *wkb)
const
2115 Geometry_buffer buffer;
2118 if (wkb->scan_non_zero_uint4(&n_objects))
2125 if (!(geom= scan_header_and_create(wkb, &buffer)) ||
2126 geom->dimension(&dim, wkb))
2128 set_if_bigger(*res_dim, dim);
2137 return collection_store_shapes(trn, st, NULL);
2141 const Geometry::Class_info *Gis_geometry_collection::get_class_info()
const
2143 return &geometrycollection_class;