diff options
Diffstat (limited to 'sql/spatial.h')
-rw-r--r-- | sql/spatial.h | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/sql/spatial.h b/sql/spatial.h new file mode 100644 index 00000000000..3f09e86e823 --- /dev/null +++ b/sql/spatial.h @@ -0,0 +1,497 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _spatial_h +#define _spatial_h + +const uint POINT_DATA_SIZE = 8+8; +const uint WKB_HEADER_SIZE = 1+4; + +struct stPoint2D +{ + double x; + double y; +}; + +struct stLinearRing +{ + size_t n_points; + stPoint2D points; +}; + +/***************************** MBR *******************************/ + +struct MBR +{ + MBR() + { + xmin=DBL_MAX; + ymin=DBL_MAX; + xmax=-DBL_MAX; + ymax=-DBL_MAX; + } + + MBR(const double &_xmin, const double &_ymin, + const double &_xmax, const double &_ymax) + { + xmin=_xmin; + ymin=_ymin; + xmax=_xmax; + ymax=_ymax; + } + + MBR(const stPoint2D &min, const stPoint2D &max) + { + xmin=min.x; + ymin=min.y; + xmax=max.x; + ymax=max.y; + } + + double xmin; + double ymin; + double xmax; + double ymax; + + void add_xy(double x, double y) + { + /* Not using "else" for proper one point MBR calculation */ + if (x<xmin) + { + xmin=x; + } + if (x>xmax) + { + xmax=x; + } + if (y<ymin) + { + ymin=y; + } + if (y>ymax) + { + ymax=y; + } + } + + void add_xy(const char *px, const char *py) + { + double x, y; + float8get(x, px); + float8get(y, py); + /* Not using "else" for proper one point MBR calculation */ + if (x<xmin) + { + xmin=x; + } + if (x>xmax) + { + xmax=x; + } + if (y<ymin) + { + ymin=y; + } + if (y>ymax) + { + ymax=y; + } + } + + void add_mbr(const MBR *mbr) + { + if (mbr->xmin<xmin) + { + xmin=mbr->xmin; + } + if (mbr->xmax>xmax) + { + xmax=mbr->xmax; + } + if (mbr->ymin<ymin) + { + ymin=mbr->ymin; + } + if (mbr->ymax>ymax) + { + ymax=mbr->ymax; + } + } + + int equals(const MBR *mbr) + { + return ((mbr->xmin == xmin) && (mbr->ymin == ymin) && + (mbr->xmax == xmax) && (mbr->ymax == ymax)); + } + + int disjoint(const MBR *mbr) + { + return ((mbr->xmin > xmax) || (mbr->ymin > ymax) || + (mbr->xmax < xmin) || (mbr->ymax < ymin)); + } + + int intersects(const MBR *mbr) + { + return !disjoint(mbr); + } + + int touches(const MBR *mbr) + { + return ((((mbr->xmin == xmax) || (mbr->xmax == xmin)) && + ((mbr->ymin >= ymin) && (mbr->ymin <= ymax) || + (mbr->ymax >= ymin) && (mbr->ymax <= ymax))) || + (((mbr->ymin == ymax) || (mbr->ymax == ymin)) && + ((mbr->xmin >= xmin) && (mbr->xmin <= xmax) || + (mbr->xmax >= xmin) && (mbr->xmax <= xmax)))); + } + + int within(const MBR *mbr) + { + return ((mbr->xmin <= xmin) && (mbr->ymin <= ymin) && + (mbr->xmax >= xmax) && (mbr->ymax >= ymax)); + } + + int contains(const MBR *mbr) + { + return ((mbr->xmin >= xmin) && (mbr->ymin >= ymin) && + (mbr->xmax <= xmax) && (mbr->ymax <= ymax)); + } + + bool inner_point(double x, double y) const + { + return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>x); + } + + int overlaps(const MBR *mbr) + { + int lb = mbr->inner_point(xmin, ymin); + int rb = mbr->inner_point(xmax, ymin); + int rt = mbr->inner_point(xmax, ymax); + int lt = mbr->inner_point(xmin, ymax); + + int a = lb+rb+rt+lt; + return (a>0) && (a<4) && (!within(mbr)); + } +}; + + +/***************************** Geometry *******************************/ + +class Geometry; + +typedef int (Geometry::*GF_InitFromText)(GTextReadStream *, String *); +typedef int (Geometry::*GF_GetDataAsText)(String *) const; +typedef size_t (Geometry::*GF_GetDataSize)() const; +typedef int (Geometry::*GF_GetMBR)(MBR *) const; + +typedef int (Geometry::*GF_GetD)(double *) const; +typedef int (Geometry::*GF_GetI)(int *) const; +typedef int (Geometry::*GF_GetUI)(uint32 *) const; +typedef int (Geometry::*GF_GetWS)(String *) const; +typedef int (Geometry::*GF_GetUIWS)(uint32, String *) const; + +#define GEOM_METHOD_PRESENT(geom_obj, method)\ + (geom_obj.m_vmt->method != &Geometry::method) + +class Geometry +{ +public: + enum wkbType + { + wkbPoint = 1, + wkbLineString = 2, + wkbPolygon = 3, + wkbMultiPoint = 4, + wkbMultiLineString = 5, + wkbMultiPolygon = 6, + wkbGeometryCollection = 7 + }; + enum wkbByteOrder + { + wkbXDR = 0, /* Big Endian */ + wkbNDR = 1 /* Little Endian */ + }; + + + class GClassInfo + { + public: + GF_InitFromText init_from_text; + GF_GetDataAsText get_data_as_text; + GF_GetDataSize get_data_size; + GF_GetMBR get_mbr; + GF_GetD get_x; + GF_GetD get_y; + GF_GetD length; + GF_GetD area; + + GF_GetI is_closed; + + GF_GetUI num_interior_ring; + GF_GetUI num_points; + GF_GetUI num_geometries; + GF_GetUI dimension; + + GF_GetWS start_point; + GF_GetWS end_point; + GF_GetWS exterior_ring; + GF_GetWS centroid; + + GF_GetUIWS point_n; + GF_GetUIWS interior_ring_n; + GF_GetUIWS geometry_n; + + int m_type_id; + const char *m_name; + GClassInfo *m_next_rt; + }; + GClassInfo *m_vmt; + + const GClassInfo *get_class_info() const { return m_vmt; } + size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); } + + int init_from_text(GTextReadStream *trs, String *wkb) + { return (this->*m_vmt->init_from_text)(trs, wkb); } + + int get_data_as_text(String *txt) const + { return (this->*m_vmt->get_data_as_text)(txt); } + + int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); } + int dimension(uint32 *dim) const + { return (this->*m_vmt->dimension)(dim); } + + int get_x(double *x) const { return (this->*m_vmt->get_x)(x); } + int get_y(double *y) const { return (this->*m_vmt->get_y)(y); } + int length(double *len) const { return (this->*m_vmt->length)(len); } + int area(double *ar) const { return (this->*m_vmt->area)(ar); } + + int is_closed(int *closed) const + { return (this->*m_vmt->is_closed)(closed); } + + int num_interior_ring(uint32 *n_int_rings) const + { return (this->*m_vmt->num_interior_ring)(n_int_rings); } + int num_points(uint32 *n_points) const + { return (this->*m_vmt->num_points)(n_points); } + + int num_geometries(uint32 *num) const + { return (this->*m_vmt->num_geometries)(num); } + + int start_point(String *point) const + { return (this->*m_vmt->start_point)(point); } + int end_point(String *point) const + { return (this->*m_vmt->end_point)(point); } + int exterior_ring(String *ring) const + { return (this->*m_vmt->exterior_ring)(ring); } + int centroid(String *point) const + { return (this->*m_vmt->centroid)(point); } + + int point_n(uint32 num, String *result) const + { return (this->*m_vmt->point_n)(num, result); } + int interior_ring_n(uint32 num, String *result) const + { return (this->*m_vmt->interior_ring_n)(num, result); } + int geometry_n(uint32 num, String *result) const + { return (this->*m_vmt->geometry_n)(num, result); } + +public: + int create_from_wkb(const char *data, uint32 data_len); + int create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream=1); + int init(int type_id) + { + m_vmt = find_class(type_id); + return !m_vmt; + } + int new_geometry(const char *name, size_t len) + { + m_vmt = find_class(name, len); + return !m_vmt; + } + + int as_wkt(String *wkt) const + { + if (wkt->reserve(strlen(get_class_info()->m_name) + 2, 512)) + return 1; + wkt->qs_append(get_class_info()->m_name); + wkt->qs_append('('); + if (get_data_as_text(wkt)) + return 1; + wkt->qs_append(')'); + return 0; + } + + void init_from_wkb(const char *data, uint32 data_len) + { + m_data = data; + m_data_end = data + data_len; + } + + void shift_wkb_header() + { + m_data += WKB_HEADER_SIZE; + } + + int envelope(String *result) const; + +protected: + static GClassInfo *find_class(int type_id); + static GClassInfo *find_class(const char *name, size_t len); + + bool no_data(const char *cur_data, uint32 data_amount) const + { + return (cur_data + data_amount > m_data_end); + } + + const char *m_data; + const char *m_data_end; +}; + +#define SIZEOF_STORED_DOUBLE 8 + +/***************************** Point *******************************/ + +class GPoint: public Geometry +{ +public: + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; + + int get_xy(double *x, double *y) const + { + const char *data = m_data; + if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; + float8get(*x, data); + float8get(*y, data + SIZEOF_STORED_DOUBLE); + return 0; + } + + int get_x(double *x) const + { + if (no_data(m_data, SIZEOF_STORED_DOUBLE)) return 1; + float8get(*x, m_data); + return 0; + } + + int get_y(double *y) const + { + const char *data = m_data; + if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; + float8get(*y, data + SIZEOF_STORED_DOUBLE); + return 0; + } + + int dimension(uint32 *dim) const { *dim = 0; return 0; } +}; + +/***************************** LineString *******************************/ + +class GLineString: public Geometry +{ +public: + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; + + int length(double *len) const; + int is_closed(int *closed) const; + int num_points(uint32 *n_points) const; + int start_point(String *point) const; + int end_point(String *point) const; + int point_n(uint32 n, String *result) const; + int dimension(uint32 *dim) const { *dim = 1; return 0; } +// IsRing +}; + +/***************************** Polygon *******************************/ + +class GPolygon: public Geometry +{ +public: + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; + + int area(double *ar) const; + int exterior_ring(String *result) const; + int num_interior_ring(uint32 *n_int_rings) const; + int interior_ring_n(uint32 num, String *result) const; + int centroid_xy(double *x, double *y) const; + int centroid(String *result) const; + int dimension(uint32 *dim) const { *dim = 2; return 0; } +// PointOnSurface +}; + +/***************************** MultiPoint *******************************/ + +class GMultiPoint: public Geometry +{ +public: + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; + int dimension(uint32 *dim) const { *dim = 0; return 0; } +}; + +/***************************** MultiLineString *******************************/ + +class GMultiLineString: public Geometry +{ +public: + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; + + int length(double *len) const; + int is_closed(int *closed) const; + int dimension(uint32 *dim) const { *dim = 1; return 0; } +}; + +/***************************** MultiPolygon *******************************/ + +class GMultiPolygon: public Geometry +{ +public: + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; + + int area(double *ar) const; + int centroid(String *result) const; + int dimension(uint32 *dim) const { *dim = 2; return 0; } +// PointOnSurface +}; + +/***************************** GeometryCollection *******************************/ + +class GGeometryCollection: public Geometry +{ +public: + size_t get_data_size() const; + int init_from_text(GTextReadStream *trs, String *wkb); + int get_data_as_text(String *txt) const; + int get_mbr(MBR *mbr) const; + + int num_geometries(uint32 *num) const; + int geometry_n(uint32 num, String *result) const; + int dimension(uint32 *dim) const; +}; + +#endif |