Commit 97327557 authored by StefanoPetrilli's avatar StefanoPetrilli Committed by Sergei Golubchik

MDEV-34276: Implements the function ST_IsValid

The GIS function ST_IsValid takes ad input a geometry and returns 1
if the argument is geometrically valid, 0 if the argument is not
geometrically valid.

Author: StefanoPetrilli <stefanop_1999@hotmail.it>
Co-authored-by: default avatarAhmed Ibrahim <ahmed.ibr.hashim@gmail.com>
Co-authored-by: default avatarJon Olav Hauglid <jon.hauglid@oracle.com>
Co-authored-by: default avatarErlend Dahl <erlend.dahl@oracle.com>
Co-authored-by: default avatarNorvald H. Ryeng <norvald.ryeng@oracle.com>
Co-authored-by: default avatarMenelaos Karavelas <menelaos.karavelas@oracle.com>
Co-authored-by: default avatarDavid.Zhao <david.zhao@oracle.com>
Co-authored-by: default avatarPavan <pavan.naik@oracle.com>
parent 70e646bd
......@@ -4582,6 +4582,12 @@ SELECT ST_ISSIMPLE(1);
ERROR HY000: Illegal parameter data type int for operation 'st_issimple'
SELECT ST_ISSIMPLE('test');
ERROR HY000: Illegal parameter data type varchar for operation 'st_issimple'
SELECT ST_ISVALID(ROW(1,1));
ERROR HY000: Illegal parameter data type row for operation 'st_isvalid'
SELECT ST_ISVALID(1);
ERROR HY000: Illegal parameter data type int for operation 'st_isvalid'
SELECT ST_ISVALID('test');
ERROR HY000: Illegal parameter data type varchar for operation 'st_isvalid'
SELECT ST_ISRING(ROW(1,1));
ERROR HY000: Illegal parameter data type row for operation 'st_isring'
SELECT ST_ISRING(1);
......@@ -5501,3 +5507,48 @@ ERROR HY000: Cannot cast 'point' as 'int' in assignment of `test`.`t1`.`b`
#
# End of 11.5 tests
#
#
# Start of 11.6 tests
#
#
# MDEV-34276 Tests for ST_isValid
#
# Some tests for Point, multipoint, linestring
SET @g = ST_GEOMFROMTEXT('POINT(0 0)');
SELECT ST_ISVALID(@g);
ST_ISVALID(@g)
1
SELECT ISVALID(@g);
ISVALID(@g)
1
SET @g = ST_GEOMFROMTEXT('POINT(15 0)');
SELECT ST_ISVALID(@g);
ST_ISVALID(@g)
1
SET @g = ST_GEOMFROMTEXT('MULTIPOINT(15 0, 10 0, 0 0, 11 11)');
SELECT ST_ISVALID(@g);
ST_ISVALID(@g)
1
SET @g = ST_GEOMFROMTEXT('LINESTRING(0 0, 1 1, 2 2, 2 3)');
SELECT ST_ISVALID(@g);
ST_ISVALID(@g)
1
# Some tests for Polygons
SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))'));
ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))'))
1
SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))'));
ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))'))
1
SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 0 2, 2 2, 1 1, 2 0, 0 0))'));
ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 0 2, 2 2, 1 1, 2 0, 0 0))'))
1
SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0, 0 2, 2 2, 2 0, 0 0)),((4 4, 4 5, 5 5, 5 4, 4 4)))')) AS a;
a
1
SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (15 15, 15 20, 20 20, 20 15, 15 15))')) as t;
t
0
#
# End of 11.6 tests
#
......@@ -2625,6 +2625,13 @@ SELECT ST_ISSIMPLE(1);
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ST_ISSIMPLE('test');
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ST_ISVALID(ROW(1,1));
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ST_ISVALID(1);
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ST_ISVALID('test');
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ST_ISRING(ROW(1,1));
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
......@@ -3503,3 +3510,42 @@ CREATE TABLE t1 (a POINT, b INT GENERATED ALWAYS AS (a));
--echo #
--echo # End of 11.5 tests
--echo #
--echo #
--echo # Start of 11.6 tests
--echo #
--echo #
--echo # MDEV-34276 Tests for ST_isValid
--echo #
--echo # Some tests for Point, multipoint, linestring
SET @g = ST_GEOMFROMTEXT('POINT(0 0)');
SELECT ST_ISVALID(@g);
SELECT ISVALID(@g);
SET @g = ST_GEOMFROMTEXT('POINT(15 0)');
SELECT ST_ISVALID(@g);
SET @g = ST_GEOMFROMTEXT('MULTIPOINT(15 0, 10 0, 0 0, 11 11)');
SELECT ST_ISVALID(@g);
SET @g = ST_GEOMFROMTEXT('LINESTRING(0 0, 1 1, 2 2, 2 3)');
SELECT ST_ISVALID(@g);
--echo # Some tests for Polygons
SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))'));
SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))'));
SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 0 2, 2 2, 1 1, 2 0, 0 0))'));
SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0, 0 2, 2 2, 2 0, 0 0)),((4 4, 4 5, 5 5, 5 4, 4 4)))')) AS a;
SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (15 15, 15 20, 20 20, 20 15, 15 15))')) as t;
--echo #
--echo # End of 11.6 tests
--echo #
This diff is collapsed.
This diff is collapsed.
......@@ -2073,6 +2073,29 @@ String *Item_func_buffer::val_str(String *str_value)
DBUG_RETURN(str_result);
}
longlong Item_func_isvalid::val_int()
{
String *wkb= args[0]->val_str(&tmp);
Geometry_buffer buffer;
Geometry *geometry;
int valid;
if ((args[0]->null_value ||
!(geometry= Geometry::construct(&buffer, wkb->ptr(), wkb->length()))))
{
my_error(ER_GIS_INVALID_DATA, MYF(0), func_name());
null_value= 1;
return 1;
}
if (geometry->is_valid(&valid))
{
null_value= 1;
return 1;
}
return (longlong) valid;
}
longlong Item_func_isempty::val_int()
{
......@@ -2080,7 +2103,7 @@ longlong Item_func_isempty::val_int()
String tmp;
String *swkb= args[0]->val_str(&tmp);
Geometry_buffer buffer;
null_value= args[0]->null_value ||
!(Geometry::construct(&buffer, swkb->ptr(), swkb->length()));
return null_value ? 1 : 0;
......@@ -2091,71 +2114,29 @@ longlong Item_func_issimple::val_int()
{
String *swkb= args[0]->val_str(&tmp);
Geometry_buffer buffer;
Gcalc_operation_transporter trn(&func, &collector);
Geometry *g;
int result= 1;
MBR mbr;
const char *c_end;
Geometry *geometry;
DBUG_ENTER("Item_func_issimple::val_int");
DBUG_ASSERT(fixed());
null_value= 0;
if ((args[0]->null_value ||
!(g= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
g->get_mbr(&mbr, &c_end)))
!(geometry= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
{
/* We got NULL as an argument. Have to return -1 */
DBUG_RETURN(-1);
}
collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
if (g->get_class_info()->m_type_id == Geometry::wkb_point)
if (geometry->get_class_info()->m_type_id == Geometry::wkb_point)
DBUG_RETURN(1);
if (g->store_shapes(&trn))
goto mem_error;
collector.prepare_operation();
scan_it.init(&collector);
while (scan_it.more_points())
{
const Gcalc_scan_iterator::event_point *ev, *next_ev;
if (scan_it.step())
goto mem_error;
ev= scan_it.get_events();
if (ev->simple_event())
continue;
next_ev= ev->get_next();
if ((ev->event & (scev_thread | scev_single_point)) && !next_ev)
continue;
if ((ev->event == scev_two_threads) && !next_ev->get_next())
continue;
/* If the first and last points of a curve coincide - that is */
/* an exception to the rule and the line is considered as simple. */
if ((next_ev && !next_ev->get_next()) &&
(ev->event & (scev_thread | scev_end)) &&
(next_ev->event & (scev_thread | scev_end)))
continue;
result= 0;
break;
int simple;
if (geometry->is_simple(&simple)) {
null_value= 1;
DBUG_RETURN(0);
}
collector.reset();
func.reset();
scan_it.reset();
DBUG_RETURN(result);
mem_error:
null_value= 1;
DBUG_RETURN(0);
DBUG_RETURN(simple);
}
......@@ -4230,6 +4211,22 @@ class Create_func_isempty : public Create_func_arg1
};
class Create_func_isvalid : public Create_func_arg1
{
public:
Item *create_1_arg(THD *thd, Item *arg1) override
{
return new (thd->mem_root) Item_func_isvalid(thd, arg1);
}
static Create_func_isvalid s_singleton;
protected:
Create_func_isvalid() = default;
virtual ~Create_func_isvalid() = default;
};
class Create_func_issimple : public Create_func_arg1
{
public:
......@@ -4246,7 +4243,6 @@ class Create_func_issimple : public Create_func_arg1
};
class Create_func_numgeometries : public Create_func_arg1
{
public:
......@@ -4516,6 +4512,7 @@ Create_func_intersection Create_func_intersection::s_singleton;
Create_func_intersects Create_func_intersects::s_singleton;
Create_func_isclosed Create_func_isclosed::s_singleton;
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_mbr_contains Create_func_mbr_contains::s_singleton;
......@@ -4585,6 +4582,7 @@ static Native_func_registry func_array_geom[] =
{ { STRING_WITH_LEN("INTERSECTS") }, GEOM_BUILDER(Create_func_mbr_intersects)},
{ { STRING_WITH_LEN("ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
{ { STRING_WITH_LEN("ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
{ { 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("LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
......@@ -4668,6 +4666,7 @@ static Native_func_registry func_array_geom[] =
{ { STRING_WITH_LEN("ST_INTERSECTS") }, GEOM_BUILDER(Create_func_intersects)},
{ { STRING_WITH_LEN("ST_ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
{ { STRING_WITH_LEN("ST_ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
{ { 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_LENGTH") }, GEOM_BUILDER(Create_func_glength)},
......
......@@ -955,9 +955,6 @@ class Item_func_isempty: public Item_bool_func_args_geometry
class Item_func_issimple: public Item_long_func_args_geometry
{
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
String tmp;
public:
Item_func_issimple(THD *thd, Item *a)
......@@ -1005,6 +1002,21 @@ class Item_func_isring: public Item_func_issimple
{ return get_item_copy<Item_func_isring>(thd, this); }
};
class Item_func_isvalid: public Item_long_func_args_geometry
{
public:
String tmp;
Item_func_isvalid(THD *thd, Item *a): Item_long_func_args_geometry(thd, a) {}
longlong val_int() override;
LEX_CSTRING func_name_cstring() const override
{
static LEX_CSTRING name= {STRING_WITH_LEN("st_isvalid") };
return name;
}
Item *do_get_copy(THD *thd) const override
{ return get_item_copy<Item_func_isvalid>(thd, this); }
};
class Item_func_dimension: public Item_long_func_args_geometry
{
public:
......
......@@ -750,6 +750,56 @@ bool Geometry::envelope(String *result) const
return 0;
}
int Geometry::is_simple(int *simple) const {
Gcalc_scan_iterator scan_it;
Gcalc_heap collector;
Gcalc_function func;
Gcalc_operation_transporter trn(&func, &collector);
const char *c_end;
MBR mbr;
*simple= 0;
if(this->get_mbr(&mbr, &c_end))
return 1;
collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
if (this->store_shapes(&trn))
return 1;
collector.prepare_operation();
scan_it.init(&collector);
while (scan_it.more_points())
{
const Gcalc_scan_iterator::event_point *ev, *next_ev;
if (scan_it.step())
return 1;
ev= scan_it.get_events();
if (ev->simple_event())
continue;
next_ev= ev->get_next();
if ((ev->event & (scev_thread | scev_single_point)) && !next_ev)
continue;
if ((ev->event == scev_two_threads) && !next_ev->get_next())
continue;
/* If the first and last points of a curve coincide - that is */
/* an exception to the rule and the line is considered as simple. */
if ((next_ev && !next_ev->get_next()) &&
(ev->event & (scev_thread | scev_end)) &&
(next_ev->event & (scev_thread | scev_end)))
continue;
return 0;
}
*simple= 1;
return 0;
}
/*
Create a point from data.
......@@ -763,7 +813,6 @@ bool Geometry::envelope(String *result) const
0 ok
1 Can't reallocate 'result'
*/
bool Geometry::create_point(String *result, const char *data) const
{
if (no_data(data, POINT_DATA_SIZE) ||
......@@ -1045,6 +1094,17 @@ bool Gis_point::get_mbr(MBR *mbr, const char **end) const
}
int Gis_point::is_valid(int *valid) const
{
double x, y;
if (get_xy(&x, &y))
return 1;
*valid= 1;
return 0;
}
int Gis_point::area(double *ar, const char **end) const
{
*ar= 0;
......@@ -1444,6 +1504,47 @@ int Gis_line_string::is_closed(int *closed) const
}
int Gis_line_string::is_valid(int *valid) const
{
Geometry_buffer buffer;
Geometry *geometry;
uint32 num_points;
*valid= 0;
if (no_data(m_data, 4))
return 1;
num_points= uint4korr(m_data);
if (not_enough_points(m_data, num_points))
return 1;
double x, y, previous_x, previous_y;
for (uint32 i = 1; i <= num_points; i++)
{
String wkb= 0;
if (wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE))
return 1;
wkb.q_append(SRID_PLACEHOLDER);
this->point_n(i, &wkb);
if (!(geometry= Geometry::construct(&buffer, wkb.ptr(), wkb.length()))||
((Gis_point *) geometry)->get_xy(&x, &y))
return 1;
if ((i != 1) && (x != previous_x || y != previous_y))
{
*valid= 1;
return 0;
}
previous_x = x;
previous_y = y;
}
return 0;
}
int Gis_line_string::num_points(uint32 *n_points) const
{
*n_points= uint4korr(m_data);
......@@ -1801,6 +1902,75 @@ bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const
}
int Gis_polygon::is_valid(int *valid) const
{
Geometry *exterior_ring, *interior_ring;
MBR exterior_mbr, interior_mbr;
uint32 num_interior_ring;
Geometry_buffer buffer;
const char *c_end;
String wkb= 0;
*valid= 0;
if (wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE))
return 1;
wkb.q_append(SRID_PLACEHOLDER);
if (this->exterior_ring(&wkb) ||
!(exterior_ring= Geometry::construct(&buffer, wkb.ptr(), wkb.length())))
return 1;
int valid_ring, simple;
if (exterior_ring->is_valid(&valid_ring) ||
exterior_ring->is_simple(&simple))
return 1;
if (!valid_ring || !simple)
return 0;
if (exterior_ring->get_mbr(&exterior_mbr, &c_end) ||
this->num_interior_ring(&num_interior_ring))
return 1;
std::vector<MBR> interior_mbrs;
for(uint32 i= 1; i <= num_interior_ring; i++)
{
String interior_wkb= 0;
if (interior_wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE))
return 1;
interior_wkb.q_append(SRID_PLACEHOLDER);
if (this->interior_ring_n(i, &interior_wkb))
break;
if (!(interior_ring= Geometry::construct(&buffer, interior_wkb.ptr(),
interior_wkb.length())) ||
interior_ring->get_mbr(&interior_mbr, &c_end))
return 1;
if (!exterior_mbr.contains(&interior_mbr) ||
exterior_mbr.equals(&interior_mbr))
return 0;
if (interior_ring->is_simple(&simple))
return 1;
if (!simple)
return 0;
for (const auto &mbr : interior_mbrs)
{
if (interior_mbr.equals(&mbr) || interior_mbr.within(&mbr))
return 0;
}
interior_mbrs.push_back(interior_mbr);
}
*valid= 1;
return 0;
}
int Gis_polygon::area(double *ar, const char **end_of_data) const
{
uint32 n_linear_rings;
......@@ -2265,6 +2435,21 @@ bool Gis_multi_point::get_data_as_json(String *txt, uint max_dec_digits,
}
int Gis_multi_point::is_valid(int *valid) const
{
uint32 num_points;
if (no_data(m_data, 4))
return 1;
num_points= uint4korr(m_data);
if (not_enough_points(m_data, num_points))
return 1;
*valid= 1;
return 0;
}
bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const
{
return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 0;
......@@ -2656,6 +2841,39 @@ bool Gis_multi_line_string::get_data_as_json(String *txt, uint max_dec_digits,
}
int Gis_multi_line_string::is_valid(int *valid) const
{
uint32 num_linestring;
Geometry_buffer buffer;
Geometry *geometry= NULL;
*valid= 0;
if (no_data(m_data, 4))
return 1;
num_linestring= uint4korr(m_data);
for (uint32 i = 1; i <= num_linestring; i++)
{
String wkb = 0;
wkb.q_append(SRID_PLACEHOLDER);
if (this->geometry_n(i, &wkb) ||
!(geometry= Geometry::construct(&buffer, wkb.ptr(), wkb.length())))
return 1;
int line_valid;
if(geometry->is_valid(&line_valid))
return 1;
if (!line_valid)
return 0;
}
*valid= 1;
return 0;
}
bool Gis_multi_line_string::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_line_strings;
......@@ -3079,6 +3297,51 @@ bool Gis_multi_polygon::get_data_as_json(String *txt, uint max_dec_digits,
}
int Gis_multi_polygon::is_valid(int *valid) const
{
Geometry_buffer buffer;
uint32 num_geometries;
std::vector<MBR> mbrs;
Geometry *geometry;
*valid= 0;
if (this->num_geometries(&num_geometries))
return 1;
for (uint32 i= 1; i <= num_geometries; i++)
{
String wkb= 0;
if (wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE))
return 0;
wkb.q_append(SRID_PLACEHOLDER);
if (this->geometry_n(i, &wkb) ||
!(geometry= Geometry::construct(&buffer, wkb.ptr(), wkb.length())))
return 1;
int internal_valid;
const char *c_end;
MBR interior_mbr;
if (geometry->is_valid(&internal_valid) ||
geometry->get_mbr(&interior_mbr, &c_end))
return 1;
if (!internal_valid)
return 0;
for (const auto &mbr : mbrs)
{
if (interior_mbr.intersects(&mbr) && !interior_mbr.touches(&mbr))
return 0;
}
mbrs.push_back(interior_mbr);
}
*valid= 1;
return 0;
}
bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_polygons;
......@@ -3307,7 +3570,7 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb)
return 1;
if (next_word.length != 5 ||
(my_charset_latin1.strnncoll("empty", 5, next_word.str, 5) != 0))
(my_charset_latin1.strnncoll("empty", 5, next_word.str, 5) != 0))
{
for (;;)
{
......@@ -3551,6 +3814,41 @@ bool Gis_geometry_collection::get_data_as_json(String *txt, uint max_dec_digits,
}
int Gis_geometry_collection::is_valid(int *valid) const
{
Geometry_buffer buffer;
uint32 num_geometries;
Geometry *geometry;
*valid= 0;
if (this->num_geometries(&num_geometries))
return 1;
for (uint32 i= 1; i <= num_geometries; i++)
{
String wkb= 0;
if (wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE))
return 1;
wkb.q_append(SRID_PLACEHOLDER);
if(this->geometry_n(i, &wkb) ||
!(geometry= Geometry::construct(&buffer, wkb.ptr(), wkb.length())))
return 1;
int internal_valid;
if (geometry->is_valid(&internal_valid))
return 1;
if (!internal_valid)
return 0;
}
*valid= 1;
return 0;
}
bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_objects;
......
......@@ -19,6 +19,7 @@
#define SPATIAL_INCLUDED
#include "sql_string.h" /* String, LEX_STRING */
#include <vector>
#include <my_compiler.h>
#include <json_lib.h>
......@@ -27,8 +28,10 @@ class Gis_read_stream;
#include "gcalc_tools.h"
const uint SRID_SIZE= 4;
const uint32 SRID_PLACEHOLDER= 0;
const uint SIZEOF_STORED_DOUBLE= 8;
const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2);
const uint BYTE_ORDER_SIZE= 1;
const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2);
const uint WKB_HEADER_SIZE= 1+4;
const uint32 GET_SIZE_ERROR= ((uint32) -1);
......@@ -289,6 +292,7 @@ class Geometry
virtual int geom_length(double *len, const char **end) const { return -1; }
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 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; }
......@@ -337,6 +341,7 @@ class Geometry
}
bool envelope(String *result) const;
int is_simple(int *simple) const;
static Class_info *ci_collection[wkb_last+1];
static bool create_point(String *result, double x, double y);
......@@ -405,7 +410,7 @@ class Gis_point: public Geometry
bool get_data_as_json(String *txt, uint max_dec_digits,
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;
......@@ -479,6 +484,7 @@ class Gis_line_string: public Geometry
int area(double *ar, const char **end) const override;
int is_closed(int *closed) const override;
int num_points(uint32 *n_points) const override;
int is_valid(int *valid) const override;
int start_point(String *point) const override;
int end_point(String *point) const override;
int point_n(uint32 n, String *result) const override;
......@@ -509,6 +515,7 @@ class Gis_polygon: public Geometry
bool get_data_as_json(String *txt, uint max_dec_digits,
const char **end) const override;
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 exterior_ring(String *result) const override;
int num_interior_ring(uint32 *n_int_rings) const override;
......@@ -545,6 +552,7 @@ class Gis_multi_point: public Geometry
bool get_data_as_wkt(String *txt, const char **end) const override;
bool get_data_as_json(String *txt, uint max_dec_digits,
const char **end) const override;
int is_valid(int *valid) const override;
bool get_mbr(MBR *mbr, const char **end) const override;
int num_geometries(uint32 *num) const override;
int geometry_n(uint32 num, String *result) const override;
......@@ -576,6 +584,7 @@ class Gis_multi_line_string: public Geometry
bool get_data_as_wkt(String *txt, const char **end) const override;
bool get_data_as_json(String *txt, uint max_dec_digits,
const char **end) const override;
int is_valid(int *valid) const override;
bool get_mbr(MBR *mbr, const char **end) const override;
int num_geometries(uint32 *num) const override;
int geometry_n(uint32 num, String *result) const override;
......@@ -606,6 +615,7 @@ class Gis_multi_polygon: public Geometry
bool get_data_as_wkt(String *txt, const char **end) const override;
bool get_data_as_json(String *txt, uint max_dec_digits,
const char **end) const override;
int is_valid(int *valid) const override;
bool get_mbr(MBR *mbr, const char **end) const override;
int num_geometries(uint32 *num) const override;
int geometry_n(uint32 num, String *result) const override;
......@@ -638,6 +648,7 @@ class Gis_geometry_collection: public Geometry
bool get_data_as_wkt(String *txt, const char **end) const override;
bool get_data_as_json(String *txt, uint max_dec_digits,
const char **end) const override;
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 geom_length(double *len, const char **end) 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