Commit e30d000e authored by Stefano Petrilli's avatar Stefano Petrilli Committed by Dave Gosselin

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: default avatarDavid Zhao <david.zhao@oracle.com>
Co-authored-by: default avatarPavan Naik <pavan.naik@oracle.com>
Co-authored-by: default avatarNorvald H. Ryeng <norvald.ryeng@oracle.com>
Co-authored-by: default avatarErlend Dahl <erlend.dahl@oracle.com>
Co-authored-by: default avatarJon Hauglid <jon.hauglid@oracle.com>
Co-authored-by: default avatarHans H Melby <hans.h.melby@oracle.com>
Co-authored-by: default avatarTor Didriksen <tor.didriksen@oracle.com>
parent 204e5bd5
This diff is collapsed.
This diff is collapsed.
......@@ -2145,6 +2145,69 @@ longlong Item_func_issimple::val_int()
}
String *Item_func_simplify::val_str(String *str)
{
DBUG_ENTER("Item_func_simplify::val_str");
String *res= args[0]->val_str(&tmp_value);
double max_distance= (double) args[1]->val_real();
Geometry_buffer buffer;
Geometry *geometry;
uint32 num_points;
null_value= 1;
if ((null_value= (args[0]->null_value || args[1]->null_value)) ||
!(geometry= Geometry::construct(&buffer, res->ptr(), res->length())))
{
null_value= 1;
DBUG_RETURN(NULL);
}
if (max_distance <= 0)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name());
null_value= 1;
DBUG_RETURN(NULL);
}
uint32 srid= uint4korr(res->ptr());
if (srid != 0)
{
my_error(ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS, MYF(0), func_name());
null_value= 1;
DBUG_RETURN(NULL);
}
if (geometry->get_class_info()->m_type_id == Geometry::wkb_point ||
geometry->get_class_info()->m_type_id == Geometry::wkb_multipoint)
{
str = res;
DBUG_RETURN(str);
}
if (geometry->get_class_info()->m_type_id == Geometry::wkb_linestring)
{
if (geometry->num_points(&num_points))
{
null_value= 1;
DBUG_RETURN(NULL);
}
if (num_points < 3)
{
str = res;
DBUG_RETURN(str);
}
}
if (geometry->simplify(str, max_distance))
{
null_value= 1;
DBUG_RETURN(NULL);
}
DBUG_RETURN(str);
}
longlong Item_func_isclosed::val_int()
{
DBUG_ASSERT(fixed());
......@@ -4248,6 +4311,22 @@ class Create_func_issimple : public Create_func_arg1
};
class Create_func_simplify : public Create_func_arg2
{
public:
Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
{
return new (thd->mem_root) Item_func_simplify(thd, arg1, arg2);
}
static Create_func_simplify s_singleton;
protected:
Create_func_simplify() = default;
~Create_func_simplify() override = default;
};
class Create_func_numgeometries : public Create_func_arg1
{
public:
......@@ -4520,6 +4599,7 @@ Create_func_isempty Create_func_isempty::s_singleton;
Create_func_isvalid Create_func_isvalid::s_singleton;
Create_func_isring Create_func_isring::s_singleton;
Create_func_issimple Create_func_issimple::s_singleton;
Create_func_simplify Create_func_simplify::s_singleton;
Create_func_mbr_contains Create_func_mbr_contains::s_singleton;
Create_func_mbr_coveredby Create_func_mbr_coveredby::s_singleton;
Create_func_mbr_disjoint Create_func_mbr_disjoint::s_singleton;
......@@ -4590,6 +4670,7 @@ static Native_func_registry func_array_geom[] =
{ { STRING_WITH_LEN("ISVALID") }, GEOM_BUILDER(Create_func_isvalid)},
{ { STRING_WITH_LEN("ISRING") }, GEOM_BUILDER(Create_func_isring)},
{ { STRING_WITH_LEN("ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
{ { STRING_WITH_LEN("SIMPLIFY") }, GEOM_BUILDER(Create_func_simplify)},
{ { STRING_WITH_LEN("LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
{ { STRING_WITH_LEN("LINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
{ { STRING_WITH_LEN("LINESTRINGFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
......@@ -4674,6 +4755,7 @@ static Native_func_registry func_array_geom[] =
{ { STRING_WITH_LEN("ST_ISVALID") }, GEOM_BUILDER(Create_func_isvalid)},
{ { STRING_WITH_LEN("ST_ISRING") }, GEOM_BUILDER(Create_func_isring)},
{ { STRING_WITH_LEN("ST_ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
{ { STRING_WITH_LEN("ST_SIMPLIFY") }, GEOM_BUILDER(Create_func_simplify)},
{ { STRING_WITH_LEN("ST_LENGTH") }, GEOM_BUILDER(Create_func_glength)},
{ { STRING_WITH_LEN("ST_LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
{ { STRING_WITH_LEN("ST_LINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
......
......@@ -977,6 +977,29 @@ class Item_func_issimple: public Item_long_func_args_geometry
{ return get_item_copy<Item_func_issimple>(thd, this); }
};
class Item_func_simplify: public Item_geometry_func_args_geometry
{
String tmp_value;
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
public:
Item_func_simplify(THD *thd, Item *a, Item *b)
:Item_geometry_func_args_geometry(thd, a, b) {}
LEX_CSTRING func_name_cstring() const override
{
static LEX_CSTRING name= {STRING_WITH_LEN("st_simplify") };
return name;
}
String *val_str(String *) override;
const Type_handler *type_handler() const override
{
return &type_handler_geometry;
}
Item *get_copy(THD *thd) override
{ return get_item_copy<Item_func_simplify>(thd, this); }
};
class Item_func_isclosed: public Item_long_func_args_geometry
{
public:
......
......@@ -12280,3 +12280,5 @@ ER_SEQUENCE_TABLE_ORDER_BY
eng "ORDER BY"
ER_VARIABLE_IGNORED
eng "The variable '%s' is ignored. It only exists for compatibility with old installations and will be removed in a future release"
ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS
eng "%s has not been implemented for geographic spatial reference systems."
This diff is collapsed.
......@@ -34,7 +34,7 @@ const uint32 SRID_PLACEHOLDER= 0;
const uint SIZEOF_STORED_DOUBLE= 8;
const uint BYTE_ORDER_SIZE= 1;
const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2);
const uint WKB_HEADER_SIZE= 1+4;
const uint WKB_HEADER_SIZE= BYTE_ORDER_SIZE + 4;
const uint32 GET_SIZE_ERROR= ((uint32) -1);
struct st_point_2d
......@@ -295,6 +295,7 @@ class Geometry
virtual int area(double *ar, const char **end) const { return -1;}
virtual int is_closed(int *closed) const { return -1; }
virtual int is_valid(int *valid) const { return -1; }
virtual int simplify(String* result, double max_distance) const { return -1; }
virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; }
virtual int num_points(uint32 *n_points) const { return -1; }
virtual int num_geometries(uint32 *num) const { return -1; }
......@@ -413,6 +414,7 @@ class Gis_point: public Geometry
const char **end) const override;
bool get_mbr(MBR *mbr, const char **end) const override;
int is_valid(int *valid) const override;
int get_xy(double *x, double *y) const
{
const char *data= m_data;
......@@ -485,6 +487,7 @@ class Gis_line_string: public Geometry
int geom_length(double *len, const char **end) const override;
int area(double *ar, const char **end) const override;
int is_closed(int *closed) const override;
int simplify(String* result, double max_distance) const override;
int num_points(uint32 *n_points) const override;
int is_valid(int *valid) const override;
int start_point(String *point) const override;
......@@ -519,6 +522,7 @@ class Gis_polygon: public Geometry
bool get_mbr(MBR *mbr, const char **end) const override;
int is_valid(int *valid) const override;
int area(double *ar, const char **end) const override;
int simplify(String* result, double max_distance) const override;
int exterior_ring(String *result) const override;
int num_interior_ring(uint32 *n_int_rings) const override;
int interior_ring_n(uint32 num, String *result) const override;
......@@ -592,6 +596,7 @@ class Gis_multi_line_string: public Geometry
int geometry_n(uint32 num, String *result) const override;
int geom_length(double *len, const char **end) const override;
int is_closed(int *closed) const override;
int simplify(String* result, double max_distance) const override;
bool dimension(uint32 *dim, const char **end) const override
{
*dim= 1;
......@@ -622,6 +627,7 @@ class Gis_multi_polygon: public Geometry
int num_geometries(uint32 *num) const override;
int geometry_n(uint32 num, String *result) const override;
int area(double *ar, const char **end) const override;
int simplify(String* result, double max_distance) const override;
int centroid(String *result) const override;
bool dimension(uint32 *dim, const char **end) const override
{
......@@ -653,6 +659,7 @@ class Gis_geometry_collection: public Geometry
int is_valid(int *valid) const override;
bool get_mbr(MBR *mbr, const char **end) const override;
int area(double *ar, const char **end) const override;
int simplify(String* result, double max_distance) const override;
int geom_length(double *len, const char **end) const override;
int num_geometries(uint32 *num) const override;
int geometry_n(uint32 num, String *result) const override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment