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