Skip to content

Commit 12370e2

Browse files
committed
[Enhancement] (GEO) Support MultiPolygon for Geometry functions (apache#49665)
### What problem does this PR solve? 1. Enhances the `GeometryFromText` function to support parsing `MULTIPOLYGON` WKT 2. Support `ST_CONTAINS ` , `ST_INTERSECTS`, `ST_TOUCHES` for it and other shapes. 3. Fixed the behavior of `ST_Touches` between two polygons, which has been updated to return `true` when they touch at a single point that is not on a horizontal or vertical edge. For example, the following polygons now return true for ST_Touches: - `POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))` - `POLYGON((5 10, 0 15, 10 15))` Obviously, they touches at the point `(5 10)`
1 parent 1ddd011 commit 12370e2

File tree

9 files changed

+1368
-33
lines changed

9 files changed

+1368
-33
lines changed

be/src/geo/geo_common.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ enum GeoParseStatus {
4242
GEO_PARSE_POLYGON_NOT_HOLE = 5,
4343
GEO_PARSE_POLYLINE_LACK_VERTICES = 6,
4444
GEO_PARSE_POLYLINE_INVALID = 7,
45-
GEO_PARSE_CIRCLE_INVALID = 8,
46-
GEO_PARSE_WKT_SYNTAX_ERROR = 9,
47-
GEO_PARSE_WKB_SYNTAX_ERROR = 10,
45+
GEO_PARSE_MULTIPOLYGON_OVERLAP = 8,
46+
GEO_PARSE_CIRCLE_INVALID = 9,
47+
GEO_PARSE_WKT_SYNTAX_ERROR = 10,
48+
GEO_PARSE_WKB_SYNTAX_ERROR = 11,
4849
};
4950

5051
std::string to_string(GeoParseStatus status);

be/src/geo/geo_types.cpp

Lines changed: 415 additions & 27 deletions
Large diffs are not rendered by default.

be/src/geo/geo_types.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <memory>
2323
#include <string>
24+
#include <vector>
2425

2526
#include "common/factory_creator.h"
2627
#include "geo/geo_common.h"
@@ -152,6 +153,7 @@ class GeoLine : public GeoShape {
152153

153154
class GeoPolygon : public GeoShape {
154155
ENABLE_FACTORY_CREATOR(GeoPolygon);
156+
friend class GeoMultiPolygon;
155157

156158
public:
157159
GeoPolygon();
@@ -185,6 +187,36 @@ class GeoPolygon : public GeoShape {
185187
std::unique_ptr<S2Polygon> _polygon;
186188
};
187189

190+
class GeoMultiPolygon : public GeoShape {
191+
ENABLE_FACTORY_CREATOR(GeoMultiPolygon);
192+
193+
public:
194+
GeoMultiPolygon();
195+
~GeoMultiPolygon() override;
196+
197+
GeoParseStatus check_self_intersection();
198+
GeoParseStatus from_coords(const std::vector<GeoCoordinateListList>& list);
199+
const std::vector<std::unique_ptr<GeoCoordinateListList>> to_coords() const;
200+
201+
GeoShapeType type() const override { return GEO_SHAPE_MULTI_POLYGON; }
202+
const std::vector<std::unique_ptr<GeoPolygon>>& polygons() const { return _polygons; }
203+
204+
bool intersects(const GeoShape* rhs) const override;
205+
bool disjoint(const GeoShape* rhs) const override;
206+
bool touches(const GeoShape* rhs) const override;
207+
bool contains(const GeoShape* rhs) const override;
208+
std::string as_wkt() const override;
209+
210+
double getArea() const;
211+
212+
protected:
213+
void encode(std::string* buf) override;
214+
bool decode(const void* data, size_t size) override;
215+
216+
private:
217+
std::vector<std::unique_ptr<GeoPolygon>> _polygons;
218+
};
219+
188220
class GeoCircle : public GeoShape {
189221
ENABLE_FACTORY_CREATOR(GeoCircle);
190222

be/src/geo/wkt_parse_type.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ struct GeoCoordinateListList {
3838
delete item;
3939
}
4040
}
41+
GeoCoordinateListList() = default;
42+
GeoCoordinateListList(GeoCoordinateListList&& other) : list(std::move(other.list)) {}
4143
void add(GeoCoordinateList* coordinates) { list.push_back(coordinates); }
4244
std::vector<GeoCoordinateList*> list;
4345
};

be/src/geo/wkt_yacc.y

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ void wkt_error(WktParseContext* ctx, const char* msg) {
3333
doris::GeoCoordinate coordinate_value;
3434
doris::GeoCoordinateList* coordinate_list_value;
3535
doris::GeoCoordinateListList* coordinate_list_list_value;
36+
std::vector<doris::GeoCoordinateListList>* multi_polygon_value;
3637
doris::GeoShape* shape_value;
3738
}
3839

@@ -67,16 +68,19 @@ void wkt_error(WktParseContext* ctx, const char* msg) {
6768
%token <double_value> NUMERIC
6869

6970
%type <None> shape
70-
%type <shape_value> point linestring polygon
71+
%type <shape_value> point linestring polygon multi_polygon
7172
%type <coordinate_value> coordinate
7273
%type <coordinate_list_value> coordinate_list
7374
%type <coordinate_list_list_value> coordinate_list_list
75+
%type <multi_polygon_value> multi_polygon_list
7476

7577
%destructor { delete $$; } coordinate_list
7678
%destructor { delete $$; } coordinate_list_list
7779
%destructor { delete $$; } point
7880
%destructor { delete $$; } linestring
7981
%destructor { delete $$; } polygon
82+
%destructor { delete $$; } multi_polygon
83+
%destructor { delete $$; } multi_polygon_list
8084

8185
%%
8286

@@ -87,6 +91,8 @@ shape:
8791
{ ctx->shape = $1; }
8892
| polygon
8993
{ ctx->shape = $1; }
94+
| multi_polygon
95+
{ ctx->shape = $1; }
9096
;
9197

9298
point:
@@ -129,6 +135,35 @@ polygon:
129135
}
130136
;
131137

138+
multi_polygon:
139+
KW_MULTI_POLYGON '(' multi_polygon_list ')'
140+
{
141+
// to avoid memory leak
142+
std::unique_ptr<std::vector<doris::GeoCoordinateListList>> list($3);
143+
std::unique_ptr<doris::GeoMultiPolygon> multi_polygon = doris::GeoMultiPolygon::create_unique();
144+
ctx->parse_status = multi_polygon->from_coords(*$3);
145+
if (ctx->parse_status != doris::GEO_PARSE_OK) {
146+
YYABORT;
147+
}
148+
$$ = multi_polygon.release();
149+
}
150+
;
151+
152+
multi_polygon_list:
153+
multi_polygon_list ',' '(' coordinate_list_list ')'
154+
{
155+
$1->push_back(std::move(*$4));
156+
delete $4;
157+
$$ = $1;
158+
}
159+
| '(' coordinate_list_list ')'
160+
{
161+
$$ = new std::vector<doris::GeoCoordinateListList>();
162+
$$->push_back(std::move(*$2));
163+
delete $2;
164+
}
165+
;
166+
132167
coordinate_list_list:
133168
coordinate_list_list ',' '(' coordinate_list ')'
134169
{

be/src/vec/common/assert_cast.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "common/logging.h"
2727
#include "vec/common/demangle.h"
28+
#include "common/compiler_util.h"
2829

2930
enum class TypeCheckOnRelease : bool { ENABLE = true, DISABLE = false };
3031

0 commit comments

Comments
 (0)