Commit 775c7bda authored by Stefano Petrilli's avatar Stefano Petrilli Committed by Sergei Golubchik

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 55d63e34
This diff is collapsed.
This diff is collapsed.
......@@ -2140,6 +2140,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());
......@@ -4243,6 +4306,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:
......@@ -4515,6 +4594,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;
......@@ -4585,6 +4665,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)},
......@@ -4669,6 +4750,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)},
......
......@@ -971,6 +971,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 *do_get_copy(THD *thd) const override
{ return get_item_copy<Item_func_simplify>(thd, this); }
};
class Item_func_isclosed: public Item_long_func_args_geometry
{
public:
......
......@@ -12291,3 +12291,5 @@ WARN_SORTING_ON_TRUNCATED_LENGTH
ER_INCORRECT_COLUMN_NAME_COUNT
eng "Incorrect column name count for derived table"
chi "派生表的列名计数不正确"
ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS
eng "%s has not been implemented for geographic spatial reference systems."
This diff is collapsed.
......@@ -32,7 +32,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
......@@ -293,6 +293,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; }
......@@ -396,7 +397,7 @@ class Geometry
/***************************** Point *******************************/
class Gis_point: public Geometry
{
public:
......@@ -411,6 +412,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;
......@@ -483,6 +485,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;
......@@ -517,6 +520,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;
......@@ -590,6 +594,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;
......@@ -620,6 +625,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
{
......@@ -651,6 +657,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