Skip to content

Commit ba66f8f

Browse files
StefanoPetrillidavid-zhaoPavan Naiknryengdahlerlend
authored andcommitted
MDEV-34141: Implements the function ST_Simplify
The GIS function ST_Simplify takes ad input a geometry and a double. It applies the Ramer-Douglas-Peucker algorithm on the geometry and returns the resulting geometry. The tests have been cherry-picked from the MySQL implementation of this function to grant compatibility among the two implementations. Co-authored-by: David Zhao <david.zhao@oracle.com> Co-authored-by: Pavan Naik <pavan.naik@oracle.com> Co-authored-by: Norvald H. Ryeng <norvald.ryeng@oracle.com> Co-authored-by: Erlend Dahl <erlend.dahl@oracle.com> Co-authored-by: Jon Hauglid <jon.hauglid@oracle.com> Co-authored-by: Hans H Melby <hans.h.melby@oracle.com> Co-authored-by: Tor Didriksen <tor.didriksen@oracle.com>
1 parent d232e4f commit ba66f8f

File tree

7 files changed

+1559
-8
lines changed

7 files changed

+1559
-8
lines changed

mysql-test/main/spatial_utility_function_simplify.result

Lines changed: 613 additions & 0 deletions
Large diffs are not rendered by default.

mysql-test/main/spatial_utility_function_simplify.test

Lines changed: 503 additions & 0 deletions
Large diffs are not rendered by default.

sql/item_geofunc.cc

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,6 +2149,69 @@ longlong Item_func_issimple::val_int()
21492149
}
21502150

21512151

2152+
String *Item_func_simplify::val_str(String *str)
2153+
{
2154+
DBUG_ENTER("Item_func_simplify::val_str");
2155+
String *res= args[0]->val_str(&tmp_value);
2156+
double max_distance= (double) args[1]->val_real();
2157+
Geometry_buffer buffer;
2158+
Geometry *geometry;
2159+
uint32 num_points;
2160+
2161+
null_value= 1;
2162+
if ((null_value= (args[0]->null_value || args[1]->null_value)) ||
2163+
!(geometry= Geometry::construct(&buffer, res->ptr(), res->length())))
2164+
{
2165+
null_value= 1;
2166+
DBUG_RETURN(NULL);
2167+
}
2168+
2169+
if (max_distance <= 0)
2170+
{
2171+
my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name());
2172+
null_value= 1;
2173+
DBUG_RETURN(NULL);
2174+
}
2175+
2176+
uint32 srid= uint4korr(res->ptr());
2177+
if (srid != 0)
2178+
{
2179+
my_error(ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS, MYF(0), func_name());
2180+
null_value= 1;
2181+
DBUG_RETURN(NULL);
2182+
}
2183+
2184+
if (geometry->get_class_info()->m_type_id == Geometry::wkb_point ||
2185+
geometry->get_class_info()->m_type_id == Geometry::wkb_multipoint)
2186+
{
2187+
str = res;
2188+
DBUG_RETURN(str);
2189+
}
2190+
2191+
if (geometry->get_class_info()->m_type_id == Geometry::wkb_linestring)
2192+
{
2193+
if (geometry->num_points(&num_points))
2194+
{
2195+
null_value= 1;
2196+
DBUG_RETURN(NULL);
2197+
}
2198+
2199+
if (num_points < 3)
2200+
{
2201+
str = res;
2202+
DBUG_RETURN(str);
2203+
}
2204+
}
2205+
2206+
if (geometry->simplify(str, max_distance))
2207+
{
2208+
null_value= 1;
2209+
DBUG_RETURN(NULL);
2210+
}
2211+
DBUG_RETURN(str);
2212+
}
2213+
2214+
21522215
longlong Item_func_isclosed::val_int()
21532216
{
21542217
DBUG_ASSERT(fixed());
@@ -4253,6 +4316,22 @@ class Create_func_issimple : public Create_func_arg1
42534316
};
42544317

42554318

4319+
class Create_func_simplify : public Create_func_arg2
4320+
{
4321+
public:
4322+
Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
4323+
{
4324+
return new (thd->mem_root) Item_func_simplify(thd, arg1, arg2);
4325+
}
4326+
4327+
static Create_func_simplify s_singleton;
4328+
4329+
protected:
4330+
Create_func_simplify() = default;
4331+
~Create_func_simplify() override = default;
4332+
};
4333+
4334+
42564335
class Create_func_numgeometries : public Create_func_arg1
42574336
{
42584337
public:
@@ -4525,6 +4604,7 @@ Create_func_isempty Create_func_isempty::s_singleton;
45254604
Create_func_isvalid Create_func_isvalid::s_singleton;
45264605
Create_func_isring Create_func_isring::s_singleton;
45274606
Create_func_issimple Create_func_issimple::s_singleton;
4607+
Create_func_simplify Create_func_simplify::s_singleton;
45284608
Create_func_mbr_contains Create_func_mbr_contains::s_singleton;
45294609
Create_func_mbr_coveredby Create_func_mbr_coveredby::s_singleton;
45304610
Create_func_mbr_disjoint Create_func_mbr_disjoint::s_singleton;
@@ -4595,6 +4675,7 @@ static Native_func_registry func_array_geom[] =
45954675
{ { STRING_WITH_LEN("ISVALID") }, GEOM_BUILDER(Create_func_isvalid)},
45964676
{ { STRING_WITH_LEN("ISRING") }, GEOM_BUILDER(Create_func_isring)},
45974677
{ { STRING_WITH_LEN("ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
4678+
{ { STRING_WITH_LEN("SIMPLIFY") }, GEOM_BUILDER(Create_func_simplify)},
45984679
{ { STRING_WITH_LEN("LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
45994680
{ { STRING_WITH_LEN("LINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
46004681
{ { STRING_WITH_LEN("LINESTRINGFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
@@ -4678,6 +4759,7 @@ static Native_func_registry func_array_geom[] =
46784759
{ { STRING_WITH_LEN("ST_ISVALID") }, GEOM_BUILDER(Create_func_isvalid)},
46794760
{ { STRING_WITH_LEN("ST_ISRING") }, GEOM_BUILDER(Create_func_isring)},
46804761
{ { STRING_WITH_LEN("ST_ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
4762+
{ { STRING_WITH_LEN("ST_SIMPLIFY") }, GEOM_BUILDER(Create_func_simplify)},
46814763
{ { STRING_WITH_LEN("ST_LENGTH") }, GEOM_BUILDER(Create_func_glength)},
46824764
{ { STRING_WITH_LEN("ST_LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
46834765
{ { STRING_WITH_LEN("ST_LINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},

sql/item_geofunc.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,29 @@ class Item_func_issimple: public Item_long_func_args_geometry
975975
{ return get_item_copy<Item_func_issimple>(thd, this); }
976976
};
977977

978+
class Item_func_simplify: public Item_geometry_func_args_geometry
979+
{
980+
String tmp_value;
981+
Gcalc_heap collector;
982+
Gcalc_function func;
983+
Gcalc_scan_iterator scan_it;
984+
public:
985+
Item_func_simplify(THD *thd, Item *a, Item *b)
986+
:Item_geometry_func_args_geometry(thd, a, b) {}
987+
LEX_CSTRING func_name_cstring() const override
988+
{
989+
static LEX_CSTRING name= {STRING_WITH_LEN("st_simplify") };
990+
return name;
991+
}
992+
String *val_str(String *) override;
993+
const Type_handler *type_handler() const override
994+
{
995+
return &type_handler_geometry;
996+
}
997+
Item *get_copy(THD *thd) override
998+
{ return get_item_copy<Item_func_simplify>(thd, this); }
999+
};
1000+
9781001
class Item_func_isclosed: public Item_long_func_args_geometry
9791002
{
9801003
public:

sql/share/errmsg-utf8.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12303,3 +12303,5 @@ ER_TOO_MANY_OPEN_CURSORS
1230312303
eng "Too many open cursors; max %u cursors allowed"
1230412304
ER_INCOMPATIBLE_EVENT_FLAG
1230512305
eng "Event flag '%s' in the condition expression is not compatible with the trigger event type '%s'"
12306+
ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS
12307+
eng "%s has not been implemented for geographic spatial reference systems."

0 commit comments

Comments
 (0)