1 /* Copyright (c) 2015, 2018, 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, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #ifndef ITEM_GEOFUNC_BGWRAP_INCLUDED
24 #define ITEM_GEOFUNC_BGWRAP_INCLUDED
25 
26 /**
27   Wraps and dispatches type specific BG function calls according to operation
28   type and both operands' types.
29 
30   We want to isolate boost header file inclusion only inside this file, so we
31   put this class declaration in an internal header file. And we want to make the
32   methods static since no state is needed here.
33 
34   @tparam Geom_types Geometry types definitions.
35 */
36 
37 #include <stddef.h>
38 #include <string.h>  // Boost expects ::memset to be already present.
39 #include <set>
40 #include <string>  // Boost expects std::string to be already present.
41 #include <vector>
42 
43 #include <boost/geometry/algorithms/crosses.hpp>
44 #include <boost/geometry/algorithms/intersects.hpp>
45 #include <boost/geometry/algorithms/touches.hpp>
46 #include <boost/geometry/algorithms/within.hpp>
47 
48 #include "my_inttypes.h"
49 #include "my_sys.h"
50 #include "mysqld_error.h"
51 #include "sql/item_geofunc.h"
52 
53 class Geometry;
54 struct bgpt_lt;
55 
56 template <typename Geom_types>
57 class BG_wrap {
58  public:
59   typedef typename Geom_types::Point Point;
60   typedef typename Geom_types::Linestring Linestring;
61   typedef typename Geom_types::Polygon Polygon;
62   typedef typename Geom_types::Multipoint Multipoint;
63   typedef typename Geom_types::Multilinestring Multilinestring;
64   typedef typename Geom_types::Multipolygon Multipolygon;
65   typedef typename Geom_types::Coordinate_type Coord_type;
66   typedef typename Geom_types::Coordinate_system Coordsys;
67 
68   // For abbrievation.
69   typedef Item_func_spatial_rel Ifsr;
70   typedef std::set<Point, bgpt_lt> Point_set;
71   typedef std::vector<Point> Point_vector;
72 
73   static int point_within_geometry(Geometry *g1, Geometry *g2,
74                                    bool *pnull_value);
75 
76   static int multipoint_within_geometry(Geometry *g1, Geometry *g2,
77                                         bool *pnull_value);
78 
79   static int linestring_within_geometry(Geometry *g1, Geometry *g2,
80                                         bool *pnull_value);
81   static int multilinestring_within_geometry(Geometry *g1, Geometry *g2,
82                                              bool *pnull_value);
83   static int polygon_within_geometry(Geometry *g1, Geometry *g2,
84                                      bool *pnull_value);
85   static int multipolygon_within_geometry(Geometry *g1, Geometry *g2,
86                                           bool *pnull_value);
87 
88   static int multipoint_equals_geometry(Geometry *g1, Geometry *g2,
89                                         bool *pnull_value);
90 
91   static int point_disjoint_geometry(Geometry *g1, Geometry *g2,
92                                      bool *pnull_value);
93   static int multipoint_disjoint_geometry(Geometry *g1, Geometry *g2,
94                                           bool *pnull_value);
95 
96   static int linestring_disjoint_geometry(Geometry *g1, Geometry *g2,
97                                           bool *pnull_value);
98   static int multilinestring_disjoint_geometry(Geometry *g1, Geometry *g2,
99                                                bool *pnull_value);
100   static int polygon_disjoint_geometry(Geometry *g1, Geometry *g2,
101                                        bool *pnull_value);
102   static int multipolygon_disjoint_geometry(Geometry *g1, Geometry *g2,
103                                             bool *pnull_value);
104   static int point_intersects_geometry(Geometry *g1, Geometry *g2,
105                                        bool *pnull_value);
106   static int multipoint_intersects_geometry(Geometry *g1, Geometry *g2,
107                                             bool *pnull_value);
108   static int linestring_intersects_geometry(Geometry *g1, Geometry *g2,
109                                             bool *pnull_value);
110   static int multilinestring_intersects_geometry(Geometry *g1, Geometry *g2,
111                                                  bool *pnull_value);
112   static int polygon_intersects_geometry(Geometry *g1, Geometry *g2,
113                                          bool *pnull_value);
114   static int multipolygon_intersects_geometry(Geometry *g1, Geometry *g2,
115                                               bool *pnull_value);
116   static int linestring_crosses_geometry(Geometry *g1, Geometry *g2,
117                                          bool *pnull_value);
118   static int multipoint_crosses_geometry(Geometry *g1, Geometry *g2,
119                                          bool *pnull_value);
120   static int multilinestring_crosses_geometry(Geometry *g1, Geometry *g2,
121                                               bool *pnull_value);
122   static int multipoint_overlaps_multipoint(Geometry *g1, Geometry *g2);
123   static int point_touches_geometry(Geometry *g1, Geometry *g2,
124                                     bool *pnull_value);
125   static int multipoint_touches_geometry(Geometry *g1, Geometry *g2,
126                                          bool *pnull_value);
127   static int linestring_touches_geometry(Geometry *g1, Geometry *g2,
128                                          bool *pnull_value);
129   static int multilinestring_touches_polygon(Geometry *g1, Geometry *g2,
130                                              bool *pnull_value);
131   static int multilinestring_touches_geometry(Geometry *g1, Geometry *g2,
132                                               bool *pnull_value);
133   static int polygon_touches_geometry(Geometry *g1, Geometry *g2,
134                                       bool *pnull_value);
135   static int multipolygon_touches_geometry(Geometry *g1, Geometry *g2,
136                                            bool *pnull_value);
137 
138  private:
139   template <typename Geom_type>
140   static int multipoint_disjoint_geometry_internal(const Multipoint &mpts1,
141                                                    const Geom_type &geom);
142   template <typename Geom_type>
143   static int multipoint_disjoint_multi_geometry(const Multipoint &mpts,
144                                                 const Geom_type &geom);
145   template <typename GeomType>
146   static int multipoint_within_geometry_internal(const Multipoint &mpts,
147                                                  const GeomType &geom);
148   static int multipoint_within_multipolygon(const Multipoint &mpts,
149                                             const Multipolygon &mplgn);
150 };  // BG_wrap
151 
152 /*
153   Call a BG function with specified types of operands. We have to create
154   geo1 and geo2 because operands g1 and g2 are created without their WKB data
155   parsed, so not suitable for BG to use. geo1 will share the same copy of WKB
156   data with g1, also true for geo2.
157  */
158 #define BGCALL(res, bgfunc, GeoType1, g1, GeoType2, g2, pnullval) \
159   do {                                                            \
160     const void *pg1 = g1->normalize_ring_order();                 \
161     const void *pg2 = g2->normalize_ring_order();                 \
162     if (pg1 != NULL && pg2 != NULL) {                             \
163       GeoType1 geo1(pg1, g1->get_data_size(), g1->get_flags(),    \
164                     g1->get_srid());                              \
165       GeoType2 geo2(pg2, g2->get_data_size(), g2->get_flags(),    \
166                     g2->get_srid());                              \
167       res = boost::geometry::bgfunc(geo1, geo2);                  \
168     } else {                                                      \
169       my_error(ER_GIS_INVALID_DATA, MYF(0), "st_" #bgfunc);       \
170       (*(pnullval)) = 1;                                          \
171     }                                                             \
172   } while (0)
173 
174 #endif  // ITEM_GEOFUNC_BGWRAP_INCLUDED
175