MDEV-34137: Implement the GIS function ST_Validate
The GIS function ST_Validate takes ad input a geometry and verifies that - is compliant with the Well-Known Binary (WKB) format and Spatial Reference System Identifier (SRID) syntax. - is geometrically valid. If the input is valid return it, else it returns NULL. The use case of this function is to filter out invalid geometry data. Author: StefanoPetrilli <stefanop_1999@hotmail.it> Co-authored-by: Torje Digernes <torje.digernes@oracle.com> Co-authored-by: Hans H Melby <hans.h.melby@oracle.com> Co-authored-by: Jon Olav Hauglid <jon.hauglid@oracle.com> Co-authored-by: Erlend Dahl <erlend.dahl@oracle.com> Co-authored-by: Norvald H. Ryeng <norvald.ryeng@oracle.com> Co-authored-by: David.Zhao <david.zhao@oracle.com> Co-authored-by: Pavan <pavan.naik@oracle.com>
This commit is contained in:
parent
869b4c243e
commit
b50366667b
139
mysql-test/main/spatial_utility_function_validate.result
Normal file
139
mysql-test/main/spatial_utility_function_validate.result
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
# Creating the spatial Geometry object
|
||||||
|
USE test;
|
||||||
|
# ST_VALIDATE must return null when its parameter is NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( NULL ));
|
||||||
|
ST_ASTEXT(ST_VALIDATE( NULL ))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT(NULL,0)));
|
||||||
|
ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT(NULL,0)))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT(NULL,4053)));
|
||||||
|
ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT(NULL,4053)))
|
||||||
|
NULL
|
||||||
|
# ST_VALIDATE raises an error if the data is malformed
|
||||||
|
SELECT ST_VALIDATE( x'00000000DEADBEEF');
|
||||||
|
ERROR 22023: Invalid GIS data provided to function st_validate.
|
||||||
|
# ST_VALIDATE return the input if it is valid
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POINT(15 25)')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POINT(15 25)')))
|
||||||
|
POINT(15 25)
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOINT(5 0,25 0,15 10,15 25)')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOINT(5 0,25 0,15 10,15 25)')))
|
||||||
|
MULTIPOINT(5 0,25 0,15 10,15 25)
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('LINESTRING(10 15,20 15)')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('LINESTRING(10 15,20 15)')))
|
||||||
|
LINESTRING(10 15,20 15)
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTILINESTRING((25 0,0 15,15 30,0 5))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTILINESTRING((25 0,0 15,15 30,0 5))')))
|
||||||
|
MULTILINESTRING((25 0,0 15,15 30,0 5))
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0))')))
|
||||||
|
POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0))
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,0 0)),((10 10,10 15,15 15,10 10)))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,0 0)),((10 10,10 15,15 15,10 10)))')))
|
||||||
|
MULTIPOLYGON(((0 0,0 10,10 10,0 0)),((10 10,10 15,15 15,10 10)))
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(10 10),'
|
||||||
|
'MULTIPOINT(0 0,10 10),'
|
||||||
|
'LINESTRING(1 1,2 2,3 3),'
|
||||||
|
'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(10 10),'
|
||||||
|
'MULTIPOINT(0 0,10 10),'
|
||||||
|
'LINESTRING(1 1,2 2,3 3),'
|
||||||
|
|
||||||
|
GEOMETRYCOLLECTION(POINT(10 10),MULTIPOINT(0 0,10 10),LINESTRING(1 1,2 2,3 3),MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)))
|
||||||
|
# The only valid empty geometry is the empty geometrycollection
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POINT()')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POINT()')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOINT()')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOINT()')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('LINESTRING()')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('LINESTRING()')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTILINESTRING(())')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTILINESTRING(())')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON(())')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON(())')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON((()),(()))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON((()),(()))')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION()')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION()')))
|
||||||
|
GEOMETRYCOLLECTION EMPTY
|
||||||
|
# Invalid geometries return null
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('LINESTRING(0 0,-0.00 0,0.0 0)')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('LINESTRING(0 0,-0.00 0,0.0 0)')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTILINESTRING((0 0))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTILINESTRING((0 0))')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON((0 0))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON((0 0))')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON(((1 1, 1 1, 1 1, 1 1, 1 1)))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON(((1 1, 1 1, 1 1, 1 1, 1 1)))')))
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0))')))
|
||||||
|
NULL
|
||||||
|
# If a polygon or multipolygon has counterclockwise internal rings, the rings are returned counterclockwise
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))')))
|
||||||
|
POLYGON((0 0,10 0,10 10,0 10,0 0),(1 1,1 2,2 2,2 1,1 1))
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1)))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1)))')))
|
||||||
|
MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(1 1,1 2,2 2,2 1,1 1)))
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1)))')));
|
||||||
|
ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1)))')))
|
||||||
|
GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(1 1,1 2,2 2,2 1,1 1)))
|
||||||
|
# ST_VALIDATE raises an error if longitude is out of range
|
||||||
|
SELECT ST_VALIDATE(ST_GEOMFROMTEXT('POINT(0 270)', 4326));
|
||||||
|
ERROR HY000: Longitude 270.000000 is out of range in function st_validate. It must be within (-180.000000, 180.000000].
|
||||||
|
# ST_VALIDATE raises an error if latitude is out of range
|
||||||
|
SELECT ST_VALIDATE(ST_GEOMFROMTEXT('POINT(270 0)', 4326));
|
||||||
|
ERROR HY000: Latitude 270.000000 is out of range in function st_validate. It must be within [-90.000000, 90.000000].
|
||||||
|
# ST_VALIDATE returns the same geometry as it was given when it is valid
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 0.25 0.75, 0.75 0.75, 0.75 0.25, 0.25 0.25))'))) AS
|
||||||
|
valid_polygon;
|
||||||
|
valid_polygon
|
||||||
|
POLYGON((0 0,1 0,1 1,0 1,0 0),(0.25 0.25,0.25 0.75,0.75 0.75,0.75 0.25,0.25 0.25))
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 0.25 0.75, 0.75 0.75, 0.75 0.25, 0.25 0.25))',4053))) AS
|
||||||
|
valid_polygon;
|
||||||
|
valid_polygon
|
||||||
|
POLYGON((0 0,1 0,1 1,0 1,0 0),(0.25 0.25,0.25 0.75,0.75 0.75,0.75 0.25,0.25 0.25))
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 0.25 0.75, 0.75 0.75, 0.75 0.25, 0.25 0.25))',2000))) AS
|
||||||
|
valid_polygon;
|
||||||
|
valid_polygon
|
||||||
|
POLYGON((0 0,1 0,1 1,0 1,0 0),(0.25 0.25,0.25 0.75,0.75 0.75,0.75 0.25,0.25 0.25))
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 0.25 0.75, 0.75 0.75, 0.75 0.25, 0.25 0.25))',4326))) AS
|
||||||
|
valid_polygon;
|
||||||
|
valid_polygon
|
||||||
|
POLYGON((0 0,1 0,1 1,0 1,0 0),(0.25 0.25,0.25 0.75,0.75 0.75,0.75 0.25,0.25 0.25))
|
||||||
|
# ST_VALIDATE returns NULL if the geometry is invalid
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 1.75 0.25, 0.75 0.75, 0.25 0.75, 0.25 0.25))'))) AS
|
||||||
|
should_be_null;
|
||||||
|
should_be_null
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 1.75 0.25, 0.75 0.75, 0.25 0.75, 0.25 0.25))',4053))) AS
|
||||||
|
should_be_null;
|
||||||
|
should_be_null
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 1.75 0.25, 0.75 0.75, 0.25 0.75, 0.25 0.25))',2000))) AS
|
||||||
|
should_be_null;
|
||||||
|
should_be_null
|
||||||
|
NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 1.75 0.25, 0.75 0.75, 0.25 0.75, 0.25 0.25))',4326))) AS
|
||||||
|
should_be_null;
|
||||||
|
should_be_null
|
||||||
|
NULL
|
101
mysql-test/main/spatial_utility_function_validate.test
Normal file
101
mysql-test/main/spatial_utility_function_validate.test
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# Copyright (c) 2014, Oracle and/or its affiliates
|
||||||
|
# Copyright (c) 2024, MariaDB Corporation.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; version 2 of the License.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
|
|
||||||
|
############################################################################################
|
||||||
|
# Creating the spatial objects #
|
||||||
|
############################################################################################
|
||||||
|
|
||||||
|
--echo # Creating the spatial Geometry object
|
||||||
|
USE test;
|
||||||
|
|
||||||
|
--echo # ST_VALIDATE must return null when its parameter is NULL
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( NULL ));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT(NULL,0)));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT(NULL,4053)));
|
||||||
|
|
||||||
|
--echo # ST_VALIDATE raises an error if the data is malformed
|
||||||
|
--error ER_GIS_INVALID_DATA
|
||||||
|
SELECT ST_VALIDATE( x'00000000DEADBEEF');
|
||||||
|
|
||||||
|
--echo # ST_VALIDATE return the input if it is valid
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POINT(15 25)')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOINT(5 0,25 0,15 10,15 25)')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('LINESTRING(10 15,20 15)')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTILINESTRING((25 0,0 15,15 30,0 5))')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0))')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,0 0)),((10 10,10 15,15 15,10 10)))')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(10 10),'
|
||||||
|
'MULTIPOINT(0 0,10 10),'
|
||||||
|
'LINESTRING(1 1,2 2,3 3),'
|
||||||
|
'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)))')));
|
||||||
|
|
||||||
|
--echo # The only valid empty geometry is the empty geometrycollection
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POINT()')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOINT()')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('LINESTRING()')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTILINESTRING(())')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON(())')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON((()),(()))')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION()')));
|
||||||
|
|
||||||
|
--echo # Invalid geometries return null
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('LINESTRING(0 0,-0.00 0,0.0 0)')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTILINESTRING((0 0))')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON((0 0))')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON(((1 1, 1 1, 1 1, 1 1, 1 1)))')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0))')));
|
||||||
|
|
||||||
|
--echo # If a polygon or multipolygon has counterclockwise internal rings, the rings are returned counterclockwise
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1)))')));
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1)))')));
|
||||||
|
|
||||||
|
--echo # ST_VALIDATE raises an error if longitude is out of range
|
||||||
|
--error ER_LONGITUDE_OUT_OF_RANGE
|
||||||
|
SELECT ST_VALIDATE(ST_GEOMFROMTEXT('POINT(0 270)', 4326));
|
||||||
|
|
||||||
|
--echo # ST_VALIDATE raises an error if latitude is out of range
|
||||||
|
--error ER_LATITUDE_OUT_OF_RANGE
|
||||||
|
SELECT ST_VALIDATE(ST_GEOMFROMTEXT('POINT(270 0)', 4326));
|
||||||
|
|
||||||
|
--echo # ST_VALIDATE returns the same geometry as it was given when it is valid
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 0.25 0.75, 0.75 0.75, 0.75 0.25, 0.25 0.25))'))) AS
|
||||||
|
valid_polygon;
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 0.25 0.75, 0.75 0.75, 0.75 0.25, 0.25 0.25))',4053))) AS
|
||||||
|
valid_polygon;
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 0.25 0.75, 0.75 0.75, 0.75 0.25, 0.25 0.25))',2000))) AS
|
||||||
|
valid_polygon;
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 0.25 0.75, 0.75 0.75, 0.75 0.25, 0.25 0.25))',4326))) AS
|
||||||
|
valid_polygon;
|
||||||
|
|
||||||
|
--echo # ST_VALIDATE returns NULL if the geometry is invalid
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 1.75 0.25, 0.75 0.75, 0.25 0.75, 0.25 0.25))'))) AS
|
||||||
|
should_be_null;
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 1.75 0.25, 0.75 0.75, 0.25 0.75, 0.25 0.25))',4053))) AS
|
||||||
|
should_be_null;
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 1.75 0.25, 0.75 0.75, 0.25 0.75, 0.25 0.25))',2000))) AS
|
||||||
|
should_be_null;
|
||||||
|
SELECT ST_ASTEXT(ST_VALIDATE( ST_GEOMFROMTEXT('POLYGON((0 0, 1 0, 1 1, 0 1, 0
|
||||||
|
0),( 0.25 0.25, 1.75 0.25, 0.75 0.75, 0.25 0.75, 0.25 0.25))',4326))) AS
|
||||||
|
should_be_null;
|
@ -2082,6 +2082,7 @@ mem_error:
|
|||||||
DBUG_RETURN(str_result);
|
DBUG_RETURN(str_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_isvalid::val_int()
|
longlong Item_func_isvalid::val_int()
|
||||||
{
|
{
|
||||||
String *wkb= args[0]->val_str(&tmp);
|
String *wkb= args[0]->val_str(&tmp);
|
||||||
@ -2106,6 +2107,73 @@ longlong Item_func_isvalid::val_int()
|
|||||||
return (longlong) valid;
|
return (longlong) valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String *Item_func_validate::val_str(String *str_value)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_func_buffer::val_str");
|
||||||
|
DBUG_ASSERT(fixed());
|
||||||
|
String *wkb= args[0]->val_str(&tmp);
|
||||||
|
Geometry_buffer buffer;
|
||||||
|
Geometry *geometry;
|
||||||
|
int valid= 1;
|
||||||
|
str_value= NULL;
|
||||||
|
null_value= 1;
|
||||||
|
|
||||||
|
if(args[0]->null_value)
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
|
||||||
|
if (!(geometry= Geometry::construct(&buffer, wkb->ptr(), wkb->length())))
|
||||||
|
{
|
||||||
|
my_error(ER_GIS_INVALID_DATA, MYF(0), func_name());
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (geometry->get_class_info()->m_type_id == Geometry::wkb_point)
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
if(((Gis_point *) geometry)->get_xy(&x, &y))
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
|
||||||
|
if (x > MAX_LONGITUDE || x <= MIN_LONGITUDE)
|
||||||
|
{
|
||||||
|
my_error(ER_LATITUDE_OUT_OF_RANGE, MYF(0), x, "st_validate");
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
}
|
||||||
|
else if(y > MAX_LATITUDE || y < MIN_LATITUDE) {
|
||||||
|
my_error(ER_LONGITUDE_OUT_OF_RANGE, MYF(0), y,"st_validate");
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
null_value= 0;
|
||||||
|
str_value= wkb;
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (geometry->is_valid(&valid))
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
|
||||||
|
if (!valid)
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
|
||||||
|
if (geometry->get_class_info()->m_type_id == Geometry::wkb_polygon ||
|
||||||
|
geometry->get_class_info()->m_type_id == Geometry::wkb_multipolygon ||
|
||||||
|
geometry->get_class_info()->m_type_id ==
|
||||||
|
Geometry::wkb_geometrycollection)
|
||||||
|
{
|
||||||
|
String clockwise_wkb;
|
||||||
|
if(geometry->make_clockwise(&clockwise_wkb))
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
|
||||||
|
wkb->length(4); // keep the SRID
|
||||||
|
wkb->append(clockwise_wkb.ptr(), clockwise_wkb.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
null_value= 0;
|
||||||
|
str_value= wkb;
|
||||||
|
DBUG_RETURN(str_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_isempty::val_bool()
|
bool Item_func_isempty::val_bool()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed());
|
DBUG_ASSERT(fixed());
|
||||||
@ -4299,37 +4367,21 @@ protected:
|
|||||||
virtual ~Create_func_isvalid() = default;
|
virtual ~Create_func_isvalid() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Create_func_isvalid : public Create_func_arg1
|
class Create_func_validate : public Create_func_arg1
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item *create_1_arg(THD *thd, Item *arg1) override
|
Item *create_1_arg(THD *thd, Item *arg1) override
|
||||||
{
|
{
|
||||||
return new (thd->mem_root) Item_func_isvalid(thd, arg1);
|
return new (thd->mem_root) Item_func_validate(thd, arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Create_func_isvalid s_singleton;
|
static Create_func_validate s_singleton;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Create_func_isvalid() = default;
|
Create_func_validate() = default;
|
||||||
virtual ~Create_func_isvalid() = default;
|
virtual ~Create_func_validate() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
class Create_func_issimple : public Create_func_arg1
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -4632,6 +4684,7 @@ Create_func_intersects Create_func_intersects::s_singleton;
|
|||||||
Create_func_isclosed Create_func_isclosed::s_singleton;
|
Create_func_isclosed Create_func_isclosed::s_singleton;
|
||||||
Create_func_isempty Create_func_isempty::s_singleton;
|
Create_func_isempty Create_func_isempty::s_singleton;
|
||||||
Create_func_isvalid Create_func_isvalid::s_singleton;
|
Create_func_isvalid Create_func_isvalid::s_singleton;
|
||||||
|
Create_func_validate Create_func_validate::s_singleton;
|
||||||
Create_func_isring Create_func_isring::s_singleton;
|
Create_func_isring Create_func_isring::s_singleton;
|
||||||
Create_func_issimple Create_func_issimple::s_singleton;
|
Create_func_issimple Create_func_issimple::s_singleton;
|
||||||
Create_func_simplify Create_func_simplify::s_singleton;
|
Create_func_simplify Create_func_simplify::s_singleton;
|
||||||
@ -4703,6 +4756,7 @@ static Native_func_registry func_array_geom[] =
|
|||||||
{ { STRING_WITH_LEN("ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
|
{ { STRING_WITH_LEN("ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
|
||||||
{ { STRING_WITH_LEN("ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
|
{ { STRING_WITH_LEN("ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
|
||||||
{ { STRING_WITH_LEN("ISVALID") }, GEOM_BUILDER(Create_func_isvalid)},
|
{ { STRING_WITH_LEN("ISVALID") }, GEOM_BUILDER(Create_func_isvalid)},
|
||||||
|
{ { STRING_WITH_LEN("VALIDATE") }, GEOM_BUILDER(Create_func_validate)},
|
||||||
{ { STRING_WITH_LEN("ISRING") }, GEOM_BUILDER(Create_func_isring)},
|
{ { STRING_WITH_LEN("ISRING") }, GEOM_BUILDER(Create_func_isring)},
|
||||||
{ { STRING_WITH_LEN("ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
|
{ { STRING_WITH_LEN("ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
|
||||||
{ { STRING_WITH_LEN("SIMPLIFY") }, GEOM_BUILDER(Create_func_simplify)},
|
{ { STRING_WITH_LEN("SIMPLIFY") }, GEOM_BUILDER(Create_func_simplify)},
|
||||||
@ -4787,6 +4841,7 @@ static Native_func_registry func_array_geom[] =
|
|||||||
{ { STRING_WITH_LEN("ST_ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
|
{ { STRING_WITH_LEN("ST_ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
|
||||||
{ { STRING_WITH_LEN("ST_ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
|
{ { STRING_WITH_LEN("ST_ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
|
||||||
{ { STRING_WITH_LEN("ST_ISVALID") }, GEOM_BUILDER(Create_func_isvalid)},
|
{ { STRING_WITH_LEN("ST_ISVALID") }, GEOM_BUILDER(Create_func_isvalid)},
|
||||||
|
{ { STRING_WITH_LEN("ST_VALIDATE") }, GEOM_BUILDER(Create_func_validate)},
|
||||||
{ { STRING_WITH_LEN("ST_ISRING") }, GEOM_BUILDER(Create_func_isring)},
|
{ { STRING_WITH_LEN("ST_ISRING") }, GEOM_BUILDER(Create_func_isring)},
|
||||||
{ { STRING_WITH_LEN("ST_ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
|
{ { STRING_WITH_LEN("ST_ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
|
||||||
{ { STRING_WITH_LEN("ST_SIMPLIFY") }, GEOM_BUILDER(Create_func_simplify)},
|
{ { STRING_WITH_LEN("ST_SIMPLIFY") }, GEOM_BUILDER(Create_func_simplify)},
|
||||||
|
@ -1044,6 +1044,26 @@ public:
|
|||||||
{ return get_item_copy<Item_func_isvalid>(thd, this); }
|
{ return get_item_copy<Item_func_isvalid>(thd, this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Item_func_validate: public Item_geometry_func_args_geometry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String tmp;
|
||||||
|
Item_func_validate(THD *thd, Item *a):
|
||||||
|
Item_geometry_func_args_geometry(thd, a) {}
|
||||||
|
LEX_CSTRING func_name_cstring() const override
|
||||||
|
{
|
||||||
|
static LEX_CSTRING name= {STRING_WITH_LEN("st_validate") };
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
String *val_str(String *) override;
|
||||||
|
const Type_handler *type_handler() const override
|
||||||
|
{
|
||||||
|
return &type_handler_point;
|
||||||
|
}
|
||||||
|
Item *get_copy(THD *thd) override
|
||||||
|
{ return get_item_copy<Item_func_validate>(thd, this); }
|
||||||
|
};
|
||||||
|
|
||||||
class Item_func_dimension: public Item_long_func_args_geometry
|
class Item_func_dimension: public Item_long_func_args_geometry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -12305,3 +12305,7 @@ ER_INCOMPATIBLE_EVENT_FLAG
|
|||||||
eng "Event flag '%s' in the condition expression is not compatible with the trigger event type '%s'"
|
eng "Event flag '%s' in the condition expression is not compatible with the trigger event type '%s'"
|
||||||
ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS
|
ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS
|
||||||
eng "%s has not been implemented for geographic spatial reference systems."
|
eng "%s has not been implemented for geographic spatial reference systems."
|
||||||
|
ER_LONGITUDE_OUT_OF_RANGE
|
||||||
|
eng "Longitude %f is out of range in function %s. It must be within (-180.000000, 180.000000]."
|
||||||
|
ER_LATITUDE_OUT_OF_RANGE
|
||||||
|
eng "Latitude %f is out of range in function %s. It must be within [-90.000000, 90.000000]."
|
||||||
|
199
sql/spatial.cc
199
sql/spatial.cc
@ -1739,6 +1739,59 @@ int Gis_line_string::store_shapes(Gcalc_shape_transporter *trn) const
|
|||||||
return trn->complete_line();
|
return trn->complete_line();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate the internal area using the shoelace formula
|
||||||
|
(https://en.wikipedia.org/wiki/Shoelace_formula). If the area is < 0 then
|
||||||
|
it is clockwise. If the area is > 0 it is counterclockwise.
|
||||||
|
If it is 0 is degenerate.
|
||||||
|
*/
|
||||||
|
int Gis_line_string::is_clockwise(int *result) const
|
||||||
|
{
|
||||||
|
uint32 num_points;
|
||||||
|
double area= 0;
|
||||||
|
|
||||||
|
if (this->num_points(&num_points))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (uint32 i= 1; i <= num_points; i++)
|
||||||
|
{
|
||||||
|
Geometry_buffer buffer_first, buffer_second;
|
||||||
|
Geometry *point_first, *point_second;
|
||||||
|
String wkb_first, wkb_second;
|
||||||
|
|
||||||
|
if (wkb_first.reserve(SRID_SIZE + WKB_HEADER_SIZE) ||
|
||||||
|
wkb_second.reserve(SRID_SIZE + WKB_HEADER_SIZE))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
wkb_first.q_append(SRID_PLACEHOLDER);
|
||||||
|
wkb_second.q_append(SRID_PLACEHOLDER);
|
||||||
|
|
||||||
|
if (this->point_n(i, &wkb_first) ||
|
||||||
|
this->point_n((i == num_points) ? 1 : i + 1, &wkb_second))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!(point_first=
|
||||||
|
Geometry::construct(&buffer_first, wkb_first.ptr(),
|
||||||
|
wkb_first.length())) ||
|
||||||
|
!(point_second=
|
||||||
|
Geometry::construct(&buffer_second, wkb_second.ptr(),
|
||||||
|
wkb_second.length())))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
double x1, x2, y1, y2;
|
||||||
|
if (((Gis_point *) point_first)->get_xy(&x1, &y1) ||
|
||||||
|
((Gis_point *) point_second)->get_xy(&x2, &y2))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
area+= (x1 * y2) - (x2 * y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
*result= (area < 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const Geometry::Class_info *Gis_line_string::get_class_info() const
|
const Geometry::Class_info *Gis_line_string::get_class_info() const
|
||||||
{
|
{
|
||||||
return &linestring_class;
|
return &linestring_class;
|
||||||
@ -2444,6 +2497,68 @@ single_point_ring:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Gis_polygon::make_clockwise(String *result) const
|
||||||
|
{
|
||||||
|
String ring_wkb= 0;
|
||||||
|
uint32 num_interior_ring;
|
||||||
|
Geometry *ring;
|
||||||
|
Geometry_buffer buffer;
|
||||||
|
int is_clockwise;
|
||||||
|
uint32 ring_points;
|
||||||
|
|
||||||
|
if(ring_wkb.reserve(SRID_SIZE + WKB_HEADER_SIZE) ||
|
||||||
|
result->reserve(SRID_SIZE + WKB_HEADER_SIZE))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (this->num_interior_ring(&num_interior_ring) ||
|
||||||
|
this->exterior_ring(&ring_wkb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result->length(0);
|
||||||
|
result->append((char) wkb_ndr);
|
||||||
|
result->q_append((uint32) wkb_polygon);
|
||||||
|
result->q_append((uint32) num_interior_ring + 1);
|
||||||
|
result->append(ring_wkb.ptr() + WKB_HEADER_SIZE,
|
||||||
|
ring_wkb.length() - WKB_HEADER_SIZE);
|
||||||
|
|
||||||
|
for(uint32 i= 1; i <= num_interior_ring; i++)
|
||||||
|
{
|
||||||
|
ring_wkb.length(0);
|
||||||
|
ring_wkb.q_append(SRID_PLACEHOLDER);
|
||||||
|
if (this->interior_ring_n(i, &ring_wkb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!(ring= Geometry::construct(&buffer, ring_wkb.ptr(),
|
||||||
|
ring_wkb.length())))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ring->is_clockwise(&is_clockwise))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (is_clockwise)
|
||||||
|
{
|
||||||
|
result->append(ring_wkb.ptr() + WKB_HEADER_SIZE + SRID_SIZE,
|
||||||
|
ring_wkb.length() - (WKB_HEADER_SIZE + SRID_SIZE));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ring->num_points(&ring_points))
|
||||||
|
return 1;
|
||||||
|
result->q_append((uint32) ring_points);
|
||||||
|
|
||||||
|
for (uint32 i= ring_points; i > 0; i--)
|
||||||
|
{
|
||||||
|
String point= 0;
|
||||||
|
ring->point_n(i, &point);
|
||||||
|
result->append(point.ptr() + WKB_HEADER_SIZE,
|
||||||
|
point.length() - WKB_HEADER_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const Geometry::Class_info *Gis_polygon::get_class_info() const
|
const Geometry::Class_info *Gis_polygon::get_class_info() const
|
||||||
{
|
{
|
||||||
return &polygon_class;
|
return &polygon_class;
|
||||||
@ -3777,6 +3892,43 @@ int Gis_multi_polygon::store_shapes(Gcalc_shape_transporter *trn) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Gis_multi_polygon::make_clockwise(String *result) const
|
||||||
|
{
|
||||||
|
Geometry_buffer buffer;
|
||||||
|
uint32 num_polygons;
|
||||||
|
Geometry *polygon;
|
||||||
|
|
||||||
|
if(this->num_geometries(&num_polygons) ||
|
||||||
|
result->reserve(SRID_SIZE + WKB_HEADER_SIZE))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result->q_append((char) wkb_ndr);
|
||||||
|
result->q_append((uint32) wkb_multipolygon);
|
||||||
|
result->q_append((uint32) num_polygons);
|
||||||
|
for (uint32 i= 1; i <= num_polygons; i++)
|
||||||
|
{
|
||||||
|
String wkb= 0, clockwise_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) ||
|
||||||
|
!(polygon= Geometry::construct(&buffer, wkb.ptr(), wkb.length())))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if(polygon->make_clockwise(&clockwise_wkb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result->q_append((char) wkb_ndr);
|
||||||
|
result->q_append((uint32) wkb_polygon);
|
||||||
|
result->append(clockwise_wkb.ptr() + WKB_HEADER_SIZE,
|
||||||
|
clockwise_wkb.length() - WKB_HEADER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const Geometry::Class_info *Gis_multi_polygon::get_class_info() const
|
const Geometry::Class_info *Gis_multi_polygon::get_class_info() const
|
||||||
{
|
{
|
||||||
return &multipolygon_class;
|
return &multipolygon_class;
|
||||||
@ -4428,6 +4580,53 @@ int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Gis_geometry_collection::make_clockwise(String *result) const
|
||||||
|
{
|
||||||
|
Geometry_buffer buffer;
|
||||||
|
uint32 num_geometries;
|
||||||
|
Geometry *geometry;
|
||||||
|
|
||||||
|
if(this->num_geometries(&num_geometries) ||
|
||||||
|
result->reserve(SRID_SIZE + WKB_HEADER_SIZE))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result->q_append((char) wkb_ndr);
|
||||||
|
result->q_append((uint32) wkb_geometrycollection);
|
||||||
|
result->q_append((uint32) num_geometries);
|
||||||
|
for (uint32 i= 1; i <= num_geometries; i++)
|
||||||
|
{
|
||||||
|
String wkb= 0, clockwise_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;
|
||||||
|
|
||||||
|
result->q_append((char) wkb_ndr);
|
||||||
|
result->q_append((uint32) geometry->get_class_info()->m_type_id);
|
||||||
|
if (geometry->get_class_info()->m_type_id == Geometry::wkb_polygon ||
|
||||||
|
geometry->get_class_info()->m_type_id == Geometry::wkb_multipolygon ||
|
||||||
|
geometry->get_class_info()->m_type_id ==
|
||||||
|
Geometry::wkb_geometrycollection)
|
||||||
|
{
|
||||||
|
if(geometry->make_clockwise(&clockwise_wkb))
|
||||||
|
return 1;
|
||||||
|
result->append(clockwise_wkb.ptr() + WKB_HEADER_SIZE,
|
||||||
|
clockwise_wkb.length() - WKB_HEADER_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result->append(wkb.ptr() + SRID_SIZE + WKB_HEADER_SIZE,
|
||||||
|
wkb.length() - (SRID_SIZE + WKB_HEADER_SIZE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const Geometry::Class_info *Gis_geometry_collection::get_class_info() const
|
const Geometry::Class_info *Gis_geometry_collection::get_class_info() const
|
||||||
{
|
{
|
||||||
return &geometrycollection_class;
|
return &geometrycollection_class;
|
||||||
|
@ -305,7 +305,8 @@ public:
|
|||||||
virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
|
virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
|
||||||
virtual int geometry_n(uint32 num, String *result) const { return -1; }
|
virtual int geometry_n(uint32 num, String *result) const { return -1; }
|
||||||
virtual int store_shapes(Gcalc_shape_transporter *trn) const=0;
|
virtual int store_shapes(Gcalc_shape_transporter *trn) const=0;
|
||||||
|
virtual int is_clockwise(int *result) const { return -1; }
|
||||||
|
virtual int make_clockwise(String *result) const{ return -1; }
|
||||||
public:
|
public:
|
||||||
static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
|
static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
|
||||||
|
|
||||||
@ -498,6 +499,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int store_shapes(Gcalc_shape_transporter *trn) const override;
|
int store_shapes(Gcalc_shape_transporter *trn) const override;
|
||||||
|
int is_clockwise(int *result) const override;
|
||||||
const Class_info *get_class_info() const override;
|
const Class_info *get_class_info() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -533,6 +535,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int store_shapes(Gcalc_shape_transporter *trn) const override;
|
int store_shapes(Gcalc_shape_transporter *trn) const override;
|
||||||
|
int make_clockwise(String *result) const override;
|
||||||
const Class_info *get_class_info() const override;
|
const Class_info *get_class_info() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -634,6 +637,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int store_shapes(Gcalc_shape_transporter *trn) const override;
|
int store_shapes(Gcalc_shape_transporter *trn) const override;
|
||||||
|
int make_clockwise(String *result) const override;
|
||||||
const Class_info *get_class_info() const override;
|
const Class_info *get_class_info() const override;
|
||||||
uint init_from_opresult(String *bin, const char *opres, uint res_len) override;
|
uint init_from_opresult(String *bin, const char *opres, uint res_len) override;
|
||||||
};
|
};
|
||||||
@ -663,6 +667,7 @@ public:
|
|||||||
int geometry_n(uint32 num, String *result) const override;
|
int geometry_n(uint32 num, String *result) const override;
|
||||||
bool dimension(uint32 *dim, const char **end) const override;
|
bool dimension(uint32 *dim, const char **end) const override;
|
||||||
int store_shapes(Gcalc_shape_transporter *trn) const override;
|
int store_shapes(Gcalc_shape_transporter *trn) const override;
|
||||||
|
int make_clockwise(String *result) const override;
|
||||||
const Class_info *get_class_info() const override;
|
const Class_info *get_class_info() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user