mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-13467: Feature request: Support for ST_Distance_Sphere()
- Cherry-pick 51e48b9f89
- vscode gitignore
- Thanks Robin Dupret for the review.
Reviewed by:daniel@mariadb.org
holyfoot@mariadb.com
This commit is contained in:
10
.gitignore
vendored
10
.gitignore
vendored
@ -507,3 +507,13 @@ FakesAssemblies/
|
||||
|
||||
# QtCreator && CodeBlocks
|
||||
*.cbp
|
||||
compile_commands.json
|
||||
.clang-format
|
||||
.kscope/
|
||||
.vimrc
|
||||
.editorconfig
|
||||
.kateconfig
|
||||
*.kdev4
|
||||
|
||||
# Visual Studio Code workspace
|
||||
.vscode/
|
||||
|
@ -807,3 +807,114 @@ SRID(GEOMETRYFROMTEXT(' MULTIPOINT(8 4,5 0,7 8,6 9,3 4,7 3,5 5) '))));
|
||||
ASTEXT(ST_BUFFER(POLYGONFROMTEXT(' POLYGON((9 9,5 2,4 5,9 9))'),
|
||||
SRID(GEOMETRYFROMTEXT(' MULTIPOINT(8 4,5 0,7 8,6 9,3 4,7 3,5 5) '))))
|
||||
POLYGON((9 9,5 2,4 5,9 9))
|
||||
#
|
||||
# MDEV-13467 Feature request: Support for ST_Distance_Sphere()
|
||||
#
|
||||
SELECT ST_DISTANCE_SPHERE();
|
||||
ERROR 42000: Incorrect parameter count in the call to native function 'ST_DISTANCE_SPHERE'
|
||||
SELECT ST_DISTANCE_SPHERE(NULL);
|
||||
ERROR 42000: Incorrect parameter count in the call to native function 'ST_DISTANCE_SPHERE'
|
||||
SELECT ST_DISTANCE_SPHERE(NULL, NULL);
|
||||
ST_DISTANCE_SPHERE(NULL, NULL)
|
||||
NULL
|
||||
SELECT ST_DISTANCE_SPHERE(NULL, NULL, 3);
|
||||
ST_DISTANCE_SPHERE(NULL, NULL, 3)
|
||||
NULL
|
||||
SELECT ST_DISTANCE_SPHERE(NULL, 1, 3);
|
||||
ST_DISTANCE_SPHERE(NULL, 1, 3)
|
||||
NULL
|
||||
SELECT ST_DISTANCE_SPHERE(1, NULL, 3);
|
||||
ST_DISTANCE_SPHERE(1, NULL, 3)
|
||||
NULL
|
||||
SELECT ST_DISTANCE_SPHERE(1, 1);
|
||||
ERROR 22023: Invalid GIS data provided to function ST_Distance_Sphere.
|
||||
SELECT ST_DISTANCE_SPHERE(1, 1, 3);
|
||||
ERROR 22023: Invalid GIS data provided to function ST_Distance_Sphere.
|
||||
SELECT ST_DISTANCE_SPHERE(1, 1, NULL);
|
||||
ST_DISTANCE_SPHERE(1, 1, NULL)
|
||||
NULL
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('LINESTRING(0 0, 1 1)'));
|
||||
ERROR HY000: Internal error: st_distance_sphere
|
||||
# Test Points and radius
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'));
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'))
|
||||
157249.0357231545
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(-1 -1)'), ST_GEOMFROMTEXT('POINT(-2 -2)')), 10);
|
||||
TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(-1 -1)'), ST_GEOMFROMTEXT('POINT(-2 -2)')), 10)
|
||||
157225.0865419108
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 1);
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 1)
|
||||
0.024682056391766436
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 0);
|
||||
ERROR HY000: Internal error: Radius must be greater than zero.
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), -1);
|
||||
ERROR HY000: Internal error: Radius must be greater than zero.
|
||||
# Test longitude/lattitude
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10);
|
||||
TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10)
|
||||
157225.0865419108
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(2 1)')), 10);
|
||||
TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(2 1)')), 10)
|
||||
222355.4901806686
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10);
|
||||
TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10)
|
||||
222389.3645969269
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(2 1)'));
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(2 1)'))
|
||||
157249.0357231545
|
||||
# Test Points - Multipoints
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1)'));
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1)'))
|
||||
157249.0357231545
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 1)'), ST_GEOMFROMTEXT('POINT(0 0)'));
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 1)'), ST_GEOMFROMTEXT('POINT(0 0)'))
|
||||
157249.0357231545
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'));
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'))
|
||||
157249.0357231545
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'));
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'))
|
||||
157249.0357231545
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'), 1);
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'), 1)
|
||||
0.024682056391766436
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'), 1);
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'), 1)
|
||||
0.024682056391766436
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1, 3 4)'), 1);
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1, 3 4)'), 1)
|
||||
0.024682056391766436
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1,5 6)'), 1);
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1,5 6)'), 1)
|
||||
0.024682056391766436
|
||||
# Test Multipoints - Multipoints
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'));
|
||||
ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'))
|
||||
0
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )')), 10);
|
||||
TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )')), 10)
|
||||
314282.5644496733
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )')), 10);
|
||||
TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )')), 10)
|
||||
314282.5644496733
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),1), 17);
|
||||
TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),1), 17)
|
||||
0.04933028646581131
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),0);
|
||||
ERROR HY000: Internal error: Radius must be greater than zero.
|
||||
set @pt1 = ST_GeomFromText('POINT(190 -30)');
|
||||
set @pt2 = ST_GeomFromText('POINT(-30 50)');
|
||||
SELECT ST_Distance_Sphere(@pt1, @pt2);
|
||||
ERROR HY000: Out of range error: Longitude should be [-180,180] in function ST_Distance_Sphere.
|
||||
set @pt1 = ST_GeomFromText('POINT(135 -30)');
|
||||
set @pt2 = ST_GeomFromText('POINT(-30 91)');
|
||||
SELECT ST_Distance_Sphere(@pt1, @pt2);
|
||||
ERROR HY000: Out of range error: Latitude should be [-90,90] in function ST_Distance_Sphere.
|
||||
set @zenica = ST_GeomFromText('POINT(17.907743 44.203438)');
|
||||
set @sarajevo = ST_GeomFromText('POINT(18.413076 43.856258)');
|
||||
SELECT TRUNCATE(ST_Distance_Sphere(@zenica, @sarajevo), 10);
|
||||
TRUNCATE(ST_Distance_Sphere(@zenica, @sarajevo), 10)
|
||||
55878.5933759170
|
||||
SELECT TRUNCATE(ST_Distance_Sphere(@sarajevo, @zenica), 10);
|
||||
TRUNCATE(ST_Distance_Sphere(@sarajevo, @zenica), 10)
|
||||
55878.5933759170
|
||||
|
@ -393,7 +393,6 @@ insert into t1 values (1);
|
||||
insert into t1 values (1.11);
|
||||
--error 1416
|
||||
insert into t1 values ("qwerty");
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
--error ER_BAD_NULL_ERROR
|
||||
insert into t1 values (ST_pointfromtext('point(1,1)'));
|
||||
|
||||
@ -437,7 +436,6 @@ select
|
||||
ST_y(b) IS NULL
|
||||
from t1;
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
select
|
||||
MBRwithin(b, b) IS NULL, MBRcontains(b, b) IS NULL, MBRoverlaps(b, b) IS NULL,
|
||||
MBRequals(b, b) IS NULL, MBRdisjoint(b, b) IS NULL, ST_touches(b, b) IS NULL,
|
||||
@ -466,7 +464,6 @@ DROP TABLE t1;
|
||||
#
|
||||
CREATE TABLE `t1` ( `col9` set('a'), `col89` date);
|
||||
INSERT IGNORE INTO `t1` VALUES ('','0000-00-00');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
select ST_geomfromtext(col9,col89) as a from t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
@ -623,17 +620,11 @@ SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRwithin FROM t1 a1 JOIN
|
||||
|
||||
# MBROverlaps needs a few more tests, with point and line dimensions
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @vert1 = ST_GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @horiz1 = ST_GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @horiz2 = ST_GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @horiz3 = ST_GeomFromText('POLYGON ((2 0, 3 0, 2 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @point1 = ST_GeomFromText('POLYGON ((0 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @point2 = ST_GeomFromText('POLYGON ((-2 0))');
|
||||
|
||||
SELECT GROUP_CONCAT(a1.name ORDER BY a1.name) AS MBRoverlaps FROM t1 a1 WHERE MBROverlaps(a1.square, @vert1) GROUP BY a1.name;
|
||||
@ -772,10 +763,8 @@ SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUA
|
||||
--echo # BUG#51875: crash when loading data into geometry function ST_polyfromwkb
|
||||
--echo #
|
||||
SET @a=0x00000000030000000100000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440;
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @a=ST_POLYFROMWKB(@a);
|
||||
SET @a=0x00000000030000000000000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440;
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @a=ST_POLYFROMWKB(@a);
|
||||
|
||||
|
||||
@ -899,7 +888,6 @@ DROP TABLE g1;
|
||||
CREATE TABLE g1(a TEXT NOT NULL, KEY(a(255)));
|
||||
|
||||
INSERT INTO g1 VALUES ('a'),('a');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SELECT 1 FROM g1 WHERE a >= ANY
|
||||
(SELECT 1 FROM g1 WHERE a = ST_geomfromtext('') OR a) ;
|
||||
|
||||
@ -1447,5 +1435,4 @@ DROP DATABASE gis_ogs;
|
||||
--echo # Bug#13362660 ASSERTION `FIELD_POS < FIELD_COUNT' FAILED. IN PROTOCOL_TEXT::STORE
|
||||
--echo #
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SELECT ST_Union('', ''), md5(1);
|
||||
|
@ -47,7 +47,6 @@ ST_GeomFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))'));
|
||||
CREATE INDEX linestring_index ON linestring(linestring_nokey(5));
|
||||
ALTER TABLE linestring ADD KEY (linestring_key(5));
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SELECT ST_AsText(linestring_nokey) FROM linestring FORCE KEY (
|
||||
linestring_key ) WHERE ST_CONTAINS( ST_GeomFromText('POLYGON( ( 3923 2815 , 4246
|
||||
2122 , 4028 2971 , 4017 3019 , 3923 2815 ) )') , linestring_key ) AND
|
||||
|
@ -1141,7 +1141,6 @@ insert into `t1` values(
|
||||
linestring(point(1,1),point(1,1))
|
||||
);
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
--error ER_BAD_NULL_ERROR
|
||||
insert into `t1` values
|
||||
(
|
||||
|
@ -388,7 +388,6 @@ insert into t1 values (1.11);
|
||||
--error 1416
|
||||
insert into t1 values ("qwerty");
|
||||
--error 1048
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
insert into t1 values (ST_pointfromtext('point(1,1)'));
|
||||
|
||||
drop table t1;
|
||||
@ -431,7 +430,6 @@ select
|
||||
ST_y(b) IS NULL
|
||||
from t1;
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
select
|
||||
MBRwithin(b, b) IS NULL, MBRcontains(b, b) IS NULL, MBRoverlaps(b, b) IS NULL,
|
||||
MBRequals(b, b) IS NULL, MBRdisjoint(b, b) IS NULL, ST_touches(b, b) IS NULL,
|
||||
@ -460,7 +458,6 @@ DROP TABLE t1;
|
||||
#
|
||||
CREATE TABLE `t1` ( `col9` set('a'), `col89` date);
|
||||
INSERT IGNORE INTO `t1` VALUES ('','0000-00-00');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
select ST_geomfromtext(col9,col89) as a from t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
@ -617,17 +614,11 @@ SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRwithin FROM t1 a1 JOIN
|
||||
|
||||
# MBROverlaps needs a few more tests, with point and line dimensions
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @vert1 = ST_GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @horiz1 = ST_GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @horiz2 = ST_GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @horiz3 = ST_GeomFromText('POLYGON ((2 0, 3 0, 2 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @point1 = ST_GeomFromText('POLYGON ((0 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @point2 = ST_GeomFromText('POLYGON ((-2 0))');
|
||||
|
||||
SELECT GROUP_CONCAT(a1.name ORDER BY a1.name) AS MBRoverlaps FROM t1 a1 WHERE MBROverlaps(a1.square, @vert1) GROUP BY a1.name;
|
||||
@ -766,10 +757,8 @@ SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUA
|
||||
--echo # BUG#51875: crash when loading data into geometry function ST_polyfromwkb
|
||||
--echo #
|
||||
SET @a=0x00000000030000000100000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440;
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @a=ST_POLYFROMWKB(@a);
|
||||
SET @a=0x00000000030000000000000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440;
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @a=ST_POLYFROMWKB(@a);
|
||||
|
||||
|
||||
@ -901,7 +890,6 @@ DROP TABLE g1;
|
||||
CREATE TABLE g1(a TEXT NOT NULL, KEY(a(255)));
|
||||
|
||||
INSERT INTO g1 VALUES ('a'),('a');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SELECT 1 FROM g1 WHERE a >= ANY
|
||||
(SELECT 1 FROM g1 WHERE a = ST_geomfromtext('') OR a) ;
|
||||
|
||||
@ -1440,5 +1428,4 @@ DROP DATABASE gis_ogs;
|
||||
--echo # Bug#13362660 ASSERTION `FIELD_POS < FIELD_COUNT' FAILED. IN PROTOCOL_TEXT::STORE
|
||||
--echo #
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SELECT ST_Union('', ''), md5(1);
|
||||
|
@ -122,7 +122,6 @@ SELECT ST_Equals(ST_PointFromText('POINT (12 13)'),ST_PointFromText('POINT (12 1
|
||||
--echo # BUG#11759650/51979: UNION/INTERSECTION OF POLYGONS CRASHES MYSQL
|
||||
--echo #
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SELECT ST_ASTEXT(ST_UNION(ST_GEOMFROMTEXT('POLYGON((525000 183300,525400
|
||||
183300,525400 18370, 525000 183700,525000 183300))'),
|
||||
ST_geomfromtext('POLYGON((525298.67 183511.53,525296.57
|
||||
@ -140,7 +139,6 @@ ST_geomfromtext('POLYGON((525298.67 183511.53,525296.57
|
||||
183491.55))'))) st_u;
|
||||
|
||||
SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F;
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SELECT ST_ASTEXT(ST_TOUCHES(@a, ST_GEOMFROMTEXT('point(0 0)'))) t;
|
||||
|
||||
|
||||
|
@ -78,17 +78,11 @@ SELECT name, ST_AsText(square) from t1 where MBRWithin(@p, square);
|
||||
|
||||
# MBROverlaps needs a few more tests, with point and line dimensions
|
||||
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @vert1 = ST_GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @horiz1 = ST_GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @horiz2 = ST_GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @horiz3 = ST_GeomFromText('POLYGON ((2 0, 3 0, 2 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @point1 = ST_GeomFromText('POLYGON ((0 0))');
|
||||
# --error ER_GIS_INVALID_DATA
|
||||
SET @point2 = ST_GeomFromText('POLYGON ((-2 0))');
|
||||
|
||||
SELECT GROUP_CONCAT(a1.name ORDER BY a1.name) AS MBRoverlaps FROM t1 a1 WHERE MBROverlaps(a1.square, @vert1) GROUP BY a1.name;
|
||||
|
@ -393,3 +393,81 @@ with cte1 as( select (st_symdifference(point(1,1),point(1,1))) as a1 ), cte2 a
|
||||
|
||||
--source include/gis_debug.inc
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-13467 Feature request: Support for ST_Distance_Sphere()
|
||||
--echo #
|
||||
|
||||
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
|
||||
SELECT ST_DISTANCE_SPHERE();
|
||||
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
|
||||
SELECT ST_DISTANCE_SPHERE(NULL);
|
||||
SELECT ST_DISTANCE_SPHERE(NULL, NULL);
|
||||
# NULL args and optional radius will return NULL
|
||||
SELECT ST_DISTANCE_SPHERE(NULL, NULL, 3);
|
||||
# At least 1 NULL arg and optional radius will return NULL
|
||||
SELECT ST_DISTANCE_SPHERE(NULL, 1, 3);
|
||||
# At least 1 NULL arg and optional radius will return NULL
|
||||
SELECT ST_DISTANCE_SPHERE(1, NULL, 3);
|
||||
# Return ER_GIS_INVALID_DATA for invalid geometry
|
||||
--error ER_GIS_INVALID_DATA
|
||||
SELECT ST_DISTANCE_SPHERE(1, 1);
|
||||
--error ER_GIS_INVALID_DATA
|
||||
SELECT ST_DISTANCE_SPHERE(1, 1, 3);
|
||||
# Return NULL if radius is NULL
|
||||
SELECT ST_DISTANCE_SPHERE(1, 1, NULL);
|
||||
# Wrong geometry
|
||||
--error ER_INTERNAL_ERROR
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('LINESTRING(0 0, 1 1)'));
|
||||
|
||||
--echo # Test Points and radius
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'));
|
||||
# make bb x86 happy
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(-1 -1)'), ST_GEOMFROMTEXT('POINT(-2 -2)')), 10);
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 1);
|
||||
--error ER_INTERNAL_ERROR
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 0);
|
||||
--error ER_INTERNAL_ERROR
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), -1);
|
||||
--echo # Test longitude/lattitude
|
||||
# make bb x86 happy
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10);
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(2 1)')), 10);
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10);
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(2 1)'));
|
||||
--echo # Test Points - Multipoints
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1)'));
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 1)'), ST_GEOMFROMTEXT('POINT(0 0)'));
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'));
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'));
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'), 1);
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'), 1);
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1, 3 4)'), 1);
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1,5 6)'), 1);
|
||||
--echo # Test Multipoints - Multipoints
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'));
|
||||
# make bb x86 happy
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )')), 10);
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )')), 10);
|
||||
# make bb x86 happy
|
||||
SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),1), 17);
|
||||
--error ER_INTERNAL_ERROR
|
||||
SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),0);
|
||||
|
||||
# Longitude out of range [-180,180]
|
||||
set @pt1 = ST_GeomFromText('POINT(190 -30)');
|
||||
set @pt2 = ST_GeomFromText('POINT(-30 50)');
|
||||
--error ER_STD_OUT_OF_RANGE_ERROR
|
||||
SELECT ST_Distance_Sphere(@pt1, @pt2);
|
||||
|
||||
# Latitude out of range [-90, 90]
|
||||
set @pt1 = ST_GeomFromText('POINT(135 -30)');
|
||||
set @pt2 = ST_GeomFromText('POINT(-30 91)');
|
||||
--error ER_STD_OUT_OF_RANGE_ERROR
|
||||
SELECT ST_Distance_Sphere(@pt1, @pt2);
|
||||
|
||||
# POINT in form (longitude[-180, 180] latitude[-90, 90])
|
||||
set @zenica = ST_GeomFromText('POINT(17.907743 44.203438)');
|
||||
set @sarajevo = ST_GeomFromText('POINT(18.413076 43.856258)');
|
||||
SELECT TRUNCATE(ST_Distance_Sphere(@zenica, @sarajevo), 10);
|
||||
SELECT TRUNCATE(ST_Distance_Sphere(@sarajevo, @zenica), 10);
|
||||
|
@ -202,7 +202,6 @@ public:
|
||||
@return An item representing the function call
|
||||
*/
|
||||
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) = 0;
|
||||
|
||||
protected:
|
||||
/** Constructor. */
|
||||
Create_func_arg2() {}
|
||||
@ -229,7 +228,6 @@ public:
|
||||
@return An item representing the function call
|
||||
*/
|
||||
virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0;
|
||||
|
||||
protected:
|
||||
/** Constructor. */
|
||||
Create_func_arg3() {}
|
||||
@ -975,6 +973,19 @@ class Create_func_distance : public Create_func_arg2
|
||||
Create_func_distance() {}
|
||||
virtual ~Create_func_distance() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_distance_sphere: public Create_native_func
|
||||
{
|
||||
public:
|
||||
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
|
||||
static Create_func_distance_sphere s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_distance_sphere() {}
|
||||
virtual ~Create_func_distance_sphere() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -4761,6 +4772,26 @@ Create_func_glength::create_1_arg(THD *thd, Item *arg1)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_glength(thd, arg1);
|
||||
}
|
||||
|
||||
|
||||
Create_func_distance_sphere Create_func_distance_sphere::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_distance_sphere::create_native(THD *thd, LEX_STRING name,
|
||||
List<Item> *item_list)
|
||||
{
|
||||
int arg_count= 0;
|
||||
|
||||
if (item_list != NULL)
|
||||
arg_count= item_list->elements;
|
||||
|
||||
if (arg_count < 2)
|
||||
{
|
||||
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
|
||||
return NULL;
|
||||
}
|
||||
return new (thd->mem_root) Item_func_sphere_distance(thd, *item_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -7051,6 +7082,7 @@ static Native_func_registry func_array[] =
|
||||
{ { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_within)},
|
||||
{ { C_STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)},
|
||||
{ { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)},
|
||||
{ { C_STRING_WITH_LEN("ST_DISTANCE_SPHERE") }, GEOM_BUILDER(Create_func_distance_sphere)},
|
||||
{ { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)},
|
||||
{ { C_STRING_WITH_LEN("SUBTIME") }, BUILDER(Create_func_subtime)},
|
||||
{ { C_STRING_WITH_LEN("TAN") }, BUILDER(Create_func_tan)},
|
||||
|
@ -2537,11 +2537,151 @@ mem_error:
|
||||
}
|
||||
|
||||
|
||||
double Item_func_sphere_distance::val_real()
|
||||
{
|
||||
/* To test null_value of item, first get well-known bytes as a backups */
|
||||
String bak1, bak2;
|
||||
String *arg1= args[0]->val_str(&bak1);
|
||||
String *arg2= args[1]->val_str(&bak2);
|
||||
double distance= 0.0;
|
||||
double sphere_radius= 6370986.0; // Default radius equals Earth radius
|
||||
|
||||
null_value= (args[0]->null_value || args[1]->null_value);
|
||||
if (null_value)
|
||||
{
|
||||
goto handle_errors;
|
||||
}
|
||||
|
||||
if (arg_count == 3)
|
||||
{
|
||||
sphere_radius= args[2]->val_real();
|
||||
// Radius cannot be Null
|
||||
if (args[2]->null_value)
|
||||
{
|
||||
null_value= true;
|
||||
goto handle_errors;
|
||||
}
|
||||
if (sphere_radius <= 0)
|
||||
{
|
||||
my_error(ER_INTERNAL_ERROR, MYF(0), "Radius must be greater than zero.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Geometry_buffer buffer1, buffer2;
|
||||
Geometry *g1, *g2;
|
||||
if (!(g1= Geometry::construct(&buffer1, arg1->ptr(), arg1->length())) ||
|
||||
!(g2= Geometry::construct(&buffer2, arg2->ptr(), arg2->length())))
|
||||
{
|
||||
my_error(ER_GIS_INVALID_DATA, MYF(0), "ST_Distance_Sphere");
|
||||
goto handle_errors;
|
||||
}
|
||||
// Method allowed for points and multipoints
|
||||
if (!(g1->get_class_info()->m_type_id == Geometry::wkb_point ||
|
||||
g1->get_class_info()->m_type_id == Geometry::wkb_multipoint) ||
|
||||
!(g2->get_class_info()->m_type_id == Geometry::wkb_point ||
|
||||
g2->get_class_info()->m_type_id == Geometry::wkb_multipoint))
|
||||
{
|
||||
// Generate error message in case different geometry is used?
|
||||
my_error(ER_INTERNAL_ERROR, MYF(0), func_name());
|
||||
return 0;
|
||||
}
|
||||
distance= spherical_distance_points(g1, g2, sphere_radius);
|
||||
if (distance < 0)
|
||||
{
|
||||
my_error(ER_INTERNAL_ERROR, MYF(0), "Returned distance cannot be negative.");
|
||||
return 1;
|
||||
}
|
||||
return distance;
|
||||
|
||||
handle_errors:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
double Item_func_sphere_distance::spherical_distance_points(Geometry *g1,
|
||||
Geometry *g2,
|
||||
const double r)
|
||||
{
|
||||
double res= 0.0;
|
||||
// Length for the single point (25 Bytes)
|
||||
uint32 len= SRID_SIZE + POINT_DATA_SIZE + WKB_HEADER_SIZE;
|
||||
int error= 0;
|
||||
|
||||
switch (g2->get_class_info()->m_type_id)
|
||||
{
|
||||
case Geometry::wkb_point:
|
||||
// Optimization for point-point case
|
||||
if (g1->get_class_info()->m_type_id == Geometry::wkb_point)
|
||||
{
|
||||
res= static_cast<Gis_point *>(g2)->calculate_haversine(g1, r, &error);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Optimization for single point in Multipoint
|
||||
if (g1->get_data_size() == len)
|
||||
{
|
||||
res= static_cast<Gis_point *>(g2)->calculate_haversine(g1, r, &error);
|
||||
}
|
||||
else
|
||||
{
|
||||
// There are multipoints in g1
|
||||
// g1 is MultiPoint and calculate MP.sphericaldistance from g2 Point
|
||||
if (g1->get_data_size() != GET_SIZE_ERROR)
|
||||
static_cast<Gis_point *>(g2)->spherical_distance_multipoints(
|
||||
(Gis_multi_point *)g1, r, &res, &error);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Geometry::wkb_multipoint:
|
||||
// Optimization for point-point case
|
||||
if (g1->get_class_info()->m_type_id == Geometry::wkb_point)
|
||||
{
|
||||
// Optimization for single point in Multipoint g2
|
||||
if (g2->get_data_size() == len)
|
||||
{
|
||||
res= static_cast<Gis_point *>(g1)->calculate_haversine(g2, r, &error);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g2->get_data_size() != GET_SIZE_ERROR)
|
||||
// g1 is a point (casted to multi_point) and g2 multipoint
|
||||
static_cast<Gis_point *>(g1)->spherical_distance_multipoints(
|
||||
(Gis_multi_point *)g2, r, &res, &error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Multipoints in g1 and g2 - no optimization
|
||||
static_cast<Gis_multi_point *>(g1)->spherical_distance_multipoints(
|
||||
(Gis_multi_point *)g2, r, &res, &error);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
goto handle_error;
|
||||
|
||||
handle_error:
|
||||
if (error > 0)
|
||||
my_error(ER_STD_OUT_OF_RANGE_ERROR, MYF(0),
|
||||
"Longitude should be [-180,180]", "ST_Distance_Sphere");
|
||||
else if(error < 0)
|
||||
my_error(ER_STD_OUT_OF_RANGE_ERROR, MYF(0),
|
||||
"Latitude should be [-90,90]", "ST_Distance_Sphere");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
String *Item_func_pointonsurface::val_str(String *str)
|
||||
{
|
||||
Gcalc_operation_transporter trn(&func, &collector);
|
||||
|
||||
DBUG_ENTER("Item_func_pointonsurface::val_real");
|
||||
DBUG_ENTER("Item_func_pointonsurface::val_str");
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
String *res= args[0]->val_str(&tmp_value);
|
||||
Geometry_buffer buffer;
|
||||
|
@ -714,6 +714,20 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Item_func_sphere_distance: public Item_real_func
|
||||
{
|
||||
double spherical_distance_points(Geometry *g1, Geometry *g2,
|
||||
const double sphere_r);
|
||||
public:
|
||||
Item_func_sphere_distance(THD *thd, List<Item> &list):
|
||||
Item_real_func(thd, list) {}
|
||||
double val_real();
|
||||
const char *func_name() const { return "st_distance_sphere"; }
|
||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||
{ return get_item_copy<Item_func_sphere_distance>(thd, mem_root, this); }
|
||||
};
|
||||
|
||||
|
||||
class Item_func_pointonsurface: public Item_geometry_func
|
||||
{
|
||||
String tmp_value;
|
||||
|
188
sql/spatial.cc
188
sql/spatial.cc
@ -1032,6 +1032,119 @@ const Geometry::Class_info *Gis_point::get_class_info() const
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function to calculate haversine.
|
||||
Taking as arguments Point and Multipoint geometries.
|
||||
Multipoint geometry has to be single point only.
|
||||
It is up to caller to ensure valid input.
|
||||
|
||||
@param g pointer to the Geometry
|
||||
@param r sphere radius
|
||||
@param error pointer describing the error in case of the boundary conditions
|
||||
|
||||
@return distance in case without error, it is caclulcated distance (non-negative),
|
||||
in case error exist, negative value.
|
||||
*/
|
||||
double Gis_point::calculate_haversine(const Geometry *g,
|
||||
const double sphere_radius,
|
||||
int *error)
|
||||
{
|
||||
DBUG_ASSERT(sphere_radius > 0);
|
||||
double x1r, x2r, y1r, y2r, dlong, dlat, res;
|
||||
|
||||
// This check is done only for optimization purposes where we know it will
|
||||
// be one and only one point in Multipoint
|
||||
if (g->get_class_info()->m_type_id == Geometry::wkb_multipoint)
|
||||
{
|
||||
const char point_size= 4 + WKB_HEADER_SIZE + POINT_DATA_SIZE+1; //1 for the type
|
||||
char point_temp[point_size];
|
||||
memset(point_temp+4, Geometry::wkb_point, 1);
|
||||
memcpy(point_temp+5, static_cast<const Gis_multi_point *>(g)->get_data_ptr()+5, 4);
|
||||
memcpy(point_temp+4+WKB_HEADER_SIZE, g->get_data_ptr()+4+WKB_HEADER_SIZE,
|
||||
POINT_DATA_SIZE);
|
||||
point_temp[point_size-1]= '\0';
|
||||
Geometry_buffer gbuff;
|
||||
Geometry *gg= Geometry::construct(&gbuff, point_temp, point_size-1);
|
||||
DBUG_ASSERT(gg);
|
||||
if (static_cast<Gis_point *>(gg)->get_xy_radian(&x2r, &y2r))
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (static_cast<const Gis_point *>(g)->get_xy_radian(&x2r, &y2r))
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
if (this->get_xy_radian(&x1r, &y1r))
|
||||
DBUG_ASSERT(0);
|
||||
// Check boundary conditions: longitude[-180,180]
|
||||
if (!((x2r >= -M_PI && x2r <= M_PI) && (x1r >= -M_PI && x1r <= M_PI)))
|
||||
{
|
||||
*error=1;
|
||||
return -1;
|
||||
}
|
||||
// Check boundary conditions: lattitude[-90,90]
|
||||
if (!((y2r >= -M_PI/2 && y2r <= M_PI/2) && (y1r >= -M_PI/2 && y1r <= M_PI/2)))
|
||||
{
|
||||
*error=-1;
|
||||
return -1;
|
||||
}
|
||||
dlat= sin((y2r - y1r)/2)*sin((y2r - y1r)/2);
|
||||
dlong= sin((x2r - x1r)/2)*sin((x2r - x1r)/2);
|
||||
res= 2*sphere_radius*asin((sqrt(dlat + cos(y1r)*cos(y2r)*dlong)));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function that calculate spherical distance of Point from Multipoint geometries.
|
||||
In case there is single point in Multipoint geometries calculate_haversine()
|
||||
can handle such case. Otherwise, new geometry (Point) has to be constructed.
|
||||
|
||||
@param g pointer to the Geometry
|
||||
@param r sphere radius
|
||||
@param result pointer to the result
|
||||
@param err pointer to the error obtained from calculate_haversin()
|
||||
|
||||
@return state
|
||||
@retval TRUE failed
|
||||
@retval FALSE success
|
||||
*/
|
||||
int Gis_point::spherical_distance_multipoints(Geometry *g, const double r,
|
||||
double *result, int *err)
|
||||
{
|
||||
uint32 num_of_points2;
|
||||
// To find the minimum radius it cannot be greater than Earth radius
|
||||
double res= 6370986.0;
|
||||
double temp_res= 0.0;
|
||||
const uint32 len= 4 + WKB_HEADER_SIZE + POINT_DATA_SIZE + 1;
|
||||
char s[len];
|
||||
g->num_geometries(&num_of_points2);
|
||||
DBUG_ASSERT(num_of_points2 >= 1);
|
||||
if (num_of_points2 == 1)
|
||||
{
|
||||
*result= this->calculate_haversine(g, r, err);
|
||||
return 0;
|
||||
}
|
||||
for (uint32 i=1; i <= num_of_points2; i++)
|
||||
{
|
||||
Geometry_buffer buff_temp;
|
||||
Geometry *temp;
|
||||
|
||||
// First 4 bytes are handled already, make sure to create a Point
|
||||
memset(s + 4, Geometry::wkb_point, 1);
|
||||
memcpy(s + 5, g->get_data_ptr() + 5, 4);
|
||||
memcpy(s + 4 + WKB_HEADER_SIZE, g->get_data_ptr() + 4 + WKB_HEADER_SIZE*i +\
|
||||
POINT_DATA_SIZE*(i-1), POINT_DATA_SIZE);
|
||||
s[len-1]= '\0';
|
||||
temp= Geometry::construct(&buff_temp, s, len);
|
||||
DBUG_ASSERT(temp);
|
||||
temp_res= this->calculate_haversine(temp, r, err);
|
||||
if (res > temp_res)
|
||||
res= temp_res;
|
||||
}
|
||||
*result= res;
|
||||
return 0;
|
||||
}
|
||||
/***************************** LineString *******************************/
|
||||
|
||||
uint32 Gis_line_string::get_data_size() const
|
||||
@ -2162,6 +2275,81 @@ const Geometry::Class_info *Gis_multi_point::get_class_info() const
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function that calculate spherical distance of Multipoints geometries.
|
||||
In case there is single point in Multipoint geometries calculate_haversine()
|
||||
can handle such case. Otherwise, new geometry (Point) has to be constructed.
|
||||
|
||||
@param g pointer to the Geometry
|
||||
@param r sphere radius
|
||||
@param result pointer to the result
|
||||
@param err pointer to the error obtained from calculate_haversin()
|
||||
|
||||
@return state
|
||||
@retval TRUE failed
|
||||
@retval FALSE success
|
||||
*/
|
||||
int Gis_multi_point::spherical_distance_multipoints(Geometry *g, const double r,
|
||||
double *result, int *err)
|
||||
{
|
||||
const uint32 len= 4 + WKB_HEADER_SIZE + POINT_DATA_SIZE + 1;
|
||||
// Check how many points are stored in Multipoints
|
||||
uint32 num_of_points1, num_of_points2;
|
||||
// To find the minimum radius it cannot be greater than Earth radius
|
||||
double res= 6370986.0;
|
||||
|
||||
/* From Item_func_sphere_distance::spherical_distance_points,
|
||||
we are sure that there will be multiple points and we have to construct
|
||||
Point geometry and return the smallest result.
|
||||
*/
|
||||
num_geometries(&num_of_points1);
|
||||
DBUG_ASSERT(num_of_points1 >= 1);
|
||||
g->num_geometries(&num_of_points2);
|
||||
DBUG_ASSERT(num_of_points2 >= 1);
|
||||
|
||||
for (uint32 i=1; i <= num_of_points1; i++)
|
||||
{
|
||||
Geometry_buffer buff_temp;
|
||||
Geometry *temp;
|
||||
double temp_res= 0.0;
|
||||
char s[len];
|
||||
// First 4 bytes are handled already, make sure to create a Point
|
||||
memset(s + 4, Geometry::wkb_point, 1);
|
||||
memcpy(s + 5, this->get_data_ptr() + 5, 4);
|
||||
memcpy(s + 4 + WKB_HEADER_SIZE, this->get_data_ptr() + 4 + WKB_HEADER_SIZE*i +\
|
||||
POINT_DATA_SIZE*(i-1), POINT_DATA_SIZE);
|
||||
s[len-1]= '\0';
|
||||
temp= Geometry::construct(&buff_temp, s, len);
|
||||
DBUG_ASSERT(temp);
|
||||
// Optimization for single Multipoint
|
||||
if (num_of_points2 == 1)
|
||||
{
|
||||
*result= static_cast<Gis_point *>(temp)->calculate_haversine(g, r, err);
|
||||
return 0;
|
||||
}
|
||||
for (uint32 j=1; j<= num_of_points2; j++)
|
||||
{
|
||||
Geometry_buffer buff_temp2;
|
||||
Geometry *temp2;
|
||||
char s2[len];
|
||||
// First 4 bytes are handled already, make sure to create a Point
|
||||
memset(s2 + 4, Geometry::wkb_point, 1);
|
||||
memcpy(s2 + 5, g->get_data_ptr() + 5, 4);
|
||||
memcpy(s2 + 4 + WKB_HEADER_SIZE, g->get_data_ptr() + 4 + WKB_HEADER_SIZE*j +\
|
||||
POINT_DATA_SIZE*(j-1), POINT_DATA_SIZE);
|
||||
s2[len-1]= '\0';
|
||||
temp2= Geometry::construct(&buff_temp2, s2, len);
|
||||
DBUG_ASSERT(temp2);
|
||||
temp_res= static_cast<Gis_point *>(temp)->calculate_haversine(temp2, r, err);
|
||||
if (res > temp_res)
|
||||
res= temp_res;
|
||||
}
|
||||
}
|
||||
*result= res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***************************** MultiLineString *******************************/
|
||||
|
||||
uint32 Gis_multi_line_string::get_data_size() const
|
||||
|
@ -332,6 +332,11 @@ public:
|
||||
m_data+= WKB_HEADER_SIZE;
|
||||
}
|
||||
|
||||
const char *get_data_ptr() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
bool envelope(String *result) const;
|
||||
static Class_info *ci_collection[wkb_last+1];
|
||||
|
||||
@ -410,6 +415,17 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_xy_radian(double *x, double *y) const
|
||||
{
|
||||
if (!get_xy(x, y))
|
||||
{
|
||||
*x= (*x)*M_PI/180;
|
||||
*y= (*y)*M_PI/180;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_x(double *x) const
|
||||
{
|
||||
if (no_data(m_data, SIZEOF_STORED_DOUBLE))
|
||||
@ -436,6 +452,10 @@ public:
|
||||
}
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const;
|
||||
const Class_info *get_class_info() const;
|
||||
double calculate_haversine(const Geometry *g, const double sphere_radius,
|
||||
int *error);
|
||||
int spherical_distance_multipoints(Geometry *g, const double r, double *result,
|
||||
int *error);
|
||||
};
|
||||
|
||||
|
||||
@ -535,6 +555,8 @@ public:
|
||||
}
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const;
|
||||
const Class_info *get_class_info() const;
|
||||
int spherical_distance_multipoints(Geometry *g, const double r, double *res,
|
||||
int *error);
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user