mirror of
https://github.com/MariaDB/server.git
synced 2026-05-15 03:17:20 +02:00
MDEV-4045 Missing OGC Spatial functions.
Missing GIS functions added:
IsRing()
PointOnSurface
PointOnSurface
Relate
Distance
Intersection
ConvexHull
Other old OpenGis standard inconsistencies fixed.
This commit is contained in:
parent
7b55b67de5
commit
d0d6284cab
9 changed files with 996 additions and 101 deletions
|
|
@ -1326,6 +1326,18 @@ WHERE name = 'Route 5'
|
|||
AND aliases = 'Main Street';
|
||||
IsEmpty(centerline)
|
||||
0
|
||||
# Conformance Item T12
|
||||
SELECT IsSimple(shore)
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
IsSimple(shore)
|
||||
1
|
||||
# Conformance Item T13
|
||||
SELECT AsText(ST_Boundary(boundary))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
AsText(ST_Boundary(boundary))
|
||||
LINESTRING(67 13,67 18,59 18,59 13,67 13)
|
||||
# Conformance Item T14
|
||||
SELECT AsText(Envelope(boundary))
|
||||
FROM named_places
|
||||
|
|
@ -1356,6 +1368,17 @@ FROM road_segments
|
|||
WHERE fid = 102;
|
||||
AsText(EndPoint(centerline))
|
||||
POINT(44 31)
|
||||
SELECT IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
1
|
||||
# Conformance Item T20
|
||||
SELECT IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
0
|
||||
# Conformance Item T21
|
||||
SELECT GLength(centerline)
|
||||
FROM road_segments
|
||||
|
|
@ -1380,6 +1403,11 @@ FROM named_places
|
|||
WHERE name = 'Goose Island';
|
||||
AsText(Centroid(boundary))
|
||||
POINT(63 15.5)
|
||||
SELECT ST_Contains(boundary, PointOnSurface(boundary))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
ST_Contains(boundary, PointOnSurface(boundary))
|
||||
1
|
||||
# Conformance Item T26
|
||||
SELECT Area(boundary)
|
||||
FROM named_places
|
||||
|
|
@ -1434,6 +1462,12 @@ FROM ponds
|
|||
WHERE fid = 120;
|
||||
AsText(Centroid(shores))
|
||||
POINT(25 42)
|
||||
# Conformance Item T35
|
||||
SELECT Contains(shores, PointOnSurface(shores))
|
||||
FROM ponds
|
||||
WHERE fid = 120;
|
||||
Contains(shores, PointOnSurface(shores))
|
||||
1
|
||||
# Conformance Item T36
|
||||
SELECT Area(shores)
|
||||
FROM ponds
|
||||
|
|
@ -1462,6 +1496,20 @@ WHERE streams.name = 'Cam Stream'
|
|||
AND lakes.name = 'Blue Lake';
|
||||
ST_Touches(centerline, shore)
|
||||
1
|
||||
# Conformance Item T40
|
||||
SELECT ST_Within(footprint, boundary)
|
||||
FROM named_places, buildings
|
||||
WHERE named_places.name = 'Ashton'
|
||||
AND buildings.address = '215 Main Street';
|
||||
ST_Within(footprint, boundary)
|
||||
1
|
||||
# Conformance Item T41
|
||||
SELECT ST_Overlaps(forests.boundary, named_places.boundary)
|
||||
FROM forests, named_places
|
||||
WHERE forests.name = 'Green Forest'
|
||||
AND named_places.name = 'Ashton';
|
||||
ST_Overlaps(forests.boundary, named_places.boundary)
|
||||
1
|
||||
# Conformance Item T42
|
||||
SELECT Crosses(road_segments.centerline, divided_routes.centerlines)
|
||||
FROM road_segments, divided_routes
|
||||
|
|
@ -1483,6 +1531,13 @@ WHERE forests.name = 'Green Forest'
|
|||
AND named_places.name = 'Ashton';
|
||||
ST_Contains(forests.boundary, named_places.boundary)
|
||||
0
|
||||
# Conformance Item T45
|
||||
SELECT ST_Relate(forests.boundary, named_places.boundary, 'TTTTTTTTT')
|
||||
FROM forests, named_places
|
||||
WHERE forests.name = 'Green Forest'
|
||||
AND named_places.name = 'Ashton';
|
||||
ST_Relate(forests.boundary, named_places.boundary, 'TTTTTTTTT')
|
||||
1
|
||||
# Conformance Item T46
|
||||
SELECT ST_Distance(position, boundary)
|
||||
FROM bridges, named_places
|
||||
|
|
@ -1490,6 +1545,13 @@ WHERE bridges.name = 'Cam Bridge'
|
|||
AND named_places.name = 'Ashton';
|
||||
ST_Distance(position, boundary)
|
||||
12
|
||||
# Conformance Item T47
|
||||
SELECT AsText(ST_Intersection(centerline, shore))
|
||||
FROM streams, lakes
|
||||
WHERE streams.name = 'Cam Stream'
|
||||
AND lakes.name = 'Blue Lake';
|
||||
AsText(ST_Intersection(centerline, shore))
|
||||
POINT(52 18)
|
||||
# Conformance Item T48
|
||||
SELECT AsText(ST_Difference(named_places.boundary, forests.boundary))
|
||||
FROM named_places, forests
|
||||
|
|
@ -1516,6 +1578,12 @@ FROM buildings, bridges
|
|||
WHERE ST_Contains(ST_Buffer(bridges.position, 15.0), buildings.footprint) = 1;
|
||||
count(*)
|
||||
1
|
||||
# Conformance Item T52
|
||||
SELECT AsText(ConvexHull(shore))
|
||||
FROM lakes
|
||||
WHERE lakes.name = 'Blue Lake';
|
||||
AsText(ConvexHull(shore))
|
||||
POLYGON((48 6,52 18,66 23,73 9,48 6))
|
||||
DROP DATABASE gis_ogs;
|
||||
USE test;
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1119,33 +1119,27 @@ FROM named_places
|
|||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T10
|
||||
# TODO: ST_SRID() alias
|
||||
SELECT SRID(boundary)
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T11
|
||||
# TODO: ST_IsEmpty() alias
|
||||
SELECT IsEmpty(centerline)
|
||||
FROM road_segments
|
||||
WHERE name = 'Route 5'
|
||||
AND aliases = 'Main Street';
|
||||
|
||||
# FIXME: get wrong result:0, expected 1.
|
||||
#--echo # Conformance Item T12
|
||||
# TODO: ST_IsSimple() alias
|
||||
#SELECT IsSimple(shore)
|
||||
#FROM lakes
|
||||
#WHERE name = 'Blue Lake';
|
||||
--echo # Conformance Item T12
|
||||
SELECT IsSimple(shore)
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T13
|
||||
#SELECT AsText(Boundary((boundary),101)
|
||||
#FROM named_places
|
||||
#WHERE name = 'Goose Island';
|
||||
--echo # Conformance Item T13
|
||||
SELECT AsText(ST_Boundary(boundary))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T14
|
||||
# TODO: ST_Envelope( ) alias
|
||||
# FIXME: we get anticlockwise, GIS suggests clockwise
|
||||
SELECT AsText(Envelope(boundary))
|
||||
FROM named_places
|
||||
|
|
@ -1170,122 +1164,100 @@ FROM road_segments
|
|||
WHERE fid = 102;
|
||||
|
||||
--echo # Conformance Item T18
|
||||
# TODO: ST_EndPoint
|
||||
SELECT AsText(EndPoint(centerline))
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T19
|
||||
# TODO: ST_LineFromWKB() alias
|
||||
#SELECT IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
#FROM named_places
|
||||
#WHERE name = 'Goose Island';
|
||||
SELECT IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T20
|
||||
#SELECT IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
#FROM named_places
|
||||
#WHERE name = 'Goose Island';
|
||||
--echo # Conformance Item T20
|
||||
SELECT IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T21
|
||||
# TODO: ST_Length() alias
|
||||
SELECT GLength(centerline)
|
||||
FROM road_segments
|
||||
WHERE fid = 106;
|
||||
|
||||
--echo # Conformance Item T22
|
||||
# TODO: ST_NumPoints() alias
|
||||
SELECT NumPoints(centerline)
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
|
||||
--echo # Conformance Item T23
|
||||
# TODO: ST_PointN() alias
|
||||
SELECT AsText(PointN(centerline, 1))
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
|
||||
--echo # Conformance Item T24
|
||||
# TODO: ST_Centroid() alias
|
||||
SELECT AsText(Centroid(boundary))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T25
|
||||
#SELECT Contains(boundary, PointOnSurface(boundary))
|
||||
#FROM named_places
|
||||
#WHERE name = 'Goose Island';
|
||||
SELECT ST_Contains(boundary, PointOnSurface(boundary))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T26
|
||||
# TODO: ST_Area() alias
|
||||
SELECT Area(boundary)
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T27
|
||||
# TODO: ST_ExteriorRing() alias
|
||||
SELECT AsText(ExteriorRing(shore))
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
|
||||
--echo # Conformance Item T28
|
||||
# TODO: ST_NumInteriorRings() alias
|
||||
SELECT NumInteriorRings(shore)
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
|
||||
--echo # Conformance Item T29
|
||||
# TODO: ST_InteriorRingN() alias
|
||||
SELECT AsText(InteriorRingN(shore, 1))
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
|
||||
--echo # Conformance Item T30
|
||||
# TODO: ST_NumGeometries() alias
|
||||
SELECT NumGeometries(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T31
|
||||
# TODO: ST_GeometryN() alias
|
||||
SELECT AsText(GeometryN(centerlines, 2))
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T32
|
||||
# TODO: ST_IsClosed() alias
|
||||
SELECT IsClosed(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T33
|
||||
# TODO: ST_Length() alias
|
||||
SELECT GLength(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T34
|
||||
# TODO: ST_Centroid() alias
|
||||
SELECT AsText(Centroid(shores))
|
||||
FROM ponds
|
||||
WHERE fid = 120;
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T35
|
||||
#SELECT Contains(shores, PointOnSurface(shores))
|
||||
#FROM ponds
|
||||
#WHERE fid = 120;
|
||||
--echo # Conformance Item T35
|
||||
SELECT Contains(shores, PointOnSurface(shores))
|
||||
FROM ponds
|
||||
WHERE fid = 120;
|
||||
|
||||
--echo # Conformance Item T36
|
||||
# TODO: ST_Area() alias
|
||||
SELECT Area(shores)
|
||||
FROM ponds
|
||||
WHERE fid = 120;
|
||||
|
||||
--echo # Conformance Item T37
|
||||
# TODO: ST_PolyFromText() alias
|
||||
SELECT ST_Equals(boundary,
|
||||
PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1))
|
||||
FROM named_places
|
||||
|
|
@ -1303,22 +1275,19 @@ FROM streams, lakes
|
|||
WHERE streams.name = 'Cam Stream'
|
||||
AND lakes.name = 'Blue Lake';
|
||||
|
||||
# FIXME: wrong result: get 0, expected 1
|
||||
#--echo # Conformance Item T40
|
||||
#SELECT ST_Within(boundary, footprint)
|
||||
#FROM named_places, buildings
|
||||
#WHERE named_places.name = 'Ashton'
|
||||
#AND buildings.address = '215 Main Street';
|
||||
--echo # Conformance Item T40
|
||||
SELECT ST_Within(footprint, boundary)
|
||||
FROM named_places, buildings
|
||||
WHERE named_places.name = 'Ashton'
|
||||
AND buildings.address = '215 Main Street';
|
||||
|
||||
# FIXME: wrong result: get 0, expected 1
|
||||
#--echo # Conformance Item T41
|
||||
#SELECT ST_Overlaps(forests.boundary, named_places.boundary)
|
||||
#FROM forests, named_places
|
||||
#WHERE forests.name = 'Green Forest'
|
||||
#AND named_places.name = 'Ashton';
|
||||
--echo # Conformance Item T41
|
||||
SELECT ST_Overlaps(forests.boundary, named_places.boundary)
|
||||
FROM forests, named_places
|
||||
WHERE forests.name = 'Green Forest'
|
||||
AND named_places.name = 'Ashton';
|
||||
|
||||
--echo # Conformance Item T42
|
||||
# FIXME: TODO: ST_Crosses() alias
|
||||
SELECT Crosses(road_segments.centerline, divided_routes.centerlines)
|
||||
FROM road_segments, divided_routes
|
||||
WHERE road_segments.fid = 102
|
||||
|
|
@ -1336,12 +1305,11 @@ FROM forests, named_places
|
|||
WHERE forests.name = 'Green Forest'
|
||||
AND named_places.name = 'Ashton';
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T45
|
||||
#SELECT Relate(forests.boundary, named_places.boundary, 'TTTTTTTTT')
|
||||
#FROM forests, named_places
|
||||
#WHERE forests.name = 'Green Forest'
|
||||
#AND named_places.name = 'Ashton';
|
||||
--echo # Conformance Item T45
|
||||
SELECT ST_Relate(forests.boundary, named_places.boundary, 'TTTTTTTTT')
|
||||
FROM forests, named_places
|
||||
WHERE forests.name = 'Green Forest'
|
||||
AND named_places.name = 'Ashton';
|
||||
|
||||
--echo # Conformance Item T46
|
||||
SELECT ST_Distance(position, boundary)
|
||||
|
|
@ -1349,12 +1317,11 @@ FROM bridges, named_places
|
|||
WHERE bridges.name = 'Cam Bridge'
|
||||
AND named_places.name = 'Ashton';
|
||||
|
||||
# FIXME: wrong result: NULL, expected 12
|
||||
#--echo # Conformance Item T47
|
||||
#SELECT AsText(ST_Intersection(centerline, shore))
|
||||
#FROM streams, lakes
|
||||
#WHERE streams.name = 'Cam Stream'
|
||||
#AND lakes.name = 'Blue Lake';
|
||||
--echo # Conformance Item T47
|
||||
SELECT AsText(ST_Intersection(centerline, shore))
|
||||
FROM streams, lakes
|
||||
WHERE streams.name = 'Cam Stream'
|
||||
AND lakes.name = 'Blue Lake';
|
||||
|
||||
--echo # Conformance Item T48
|
||||
SELECT AsText(ST_Difference(named_places.boundary, forests.boundary))
|
||||
|
|
@ -1379,11 +1346,10 @@ SELECT count(*)
|
|||
FROM buildings, bridges
|
||||
WHERE ST_Contains(ST_Buffer(bridges.position, 15.0), buildings.footprint) = 1;
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T52
|
||||
#SELECT AsText(ConvexHull(shore))
|
||||
#FROM lakes
|
||||
#WHERE lakes.name = 'Blue Lake';
|
||||
--echo # Conformance Item T52
|
||||
SELECT AsText(ConvexHull(shore))
|
||||
FROM lakes
|
||||
WHERE lakes.name = 'Blue Lake';
|
||||
|
||||
DROP DATABASE gis_ogs;
|
||||
USE test;
|
||||
|
|
|
|||
|
|
@ -1961,7 +1961,7 @@ double Gcalc_scan_iterator::get_h() const
|
|||
state.pi->calc_xy(&x, &next_y);
|
||||
}
|
||||
else
|
||||
next_y= state.pi->y;
|
||||
next_y= state.pi->next ? state.pi->get_next()->y : 0.0;
|
||||
return next_y - cur_y;
|
||||
}
|
||||
|
||||
|
|
@ -1974,7 +1974,7 @@ double Gcalc_scan_iterator::get_sp_x(const point *sp) const
|
|||
dy= sp->next_pi->y - sp->pi->y;
|
||||
if (fabs(dy) < 1e-12)
|
||||
return sp->pi->x;
|
||||
return (sp->next_pi->x - sp->pi->x) * dy;
|
||||
return sp->pi->x + (sp->next_pi->x - sp->pi->x) * dy;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -513,7 +513,35 @@ protected:
|
|||
Create_func_centroid() {}
|
||||
virtual ~Create_func_centroid() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
class Create_func_convexhull : public Create_func_arg1
|
||||
{
|
||||
public:
|
||||
virtual Item *create_1_arg(THD *thd, Item *arg1);
|
||||
|
||||
static Create_func_convexhull s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_convexhull() {}
|
||||
virtual ~Create_func_convexhull() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_pointonsurface : public Create_func_arg1
|
||||
{
|
||||
public:
|
||||
virtual Item *create_1_arg(THD *thd, Item *arg1);
|
||||
|
||||
static Create_func_pointonsurface s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_pointonsurface() {}
|
||||
virtual ~Create_func_pointonsurface() {}
|
||||
};
|
||||
|
||||
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
|
||||
|
||||
class Create_func_char_length : public Create_func_arg1
|
||||
|
|
@ -1015,7 +1043,19 @@ protected:
|
|||
Create_func_envelope() {}
|
||||
virtual ~Create_func_envelope() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
class Create_func_boundary : public Create_func_arg1
|
||||
{
|
||||
public:
|
||||
virtual Item *create_1_arg(THD *thd, Item *arg1);
|
||||
|
||||
static Create_func_boundary s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_boundary() {}
|
||||
virtual ~Create_func_boundary() {}
|
||||
};
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
|
|
@ -1466,6 +1506,19 @@ protected:
|
|||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
class Create_func_relate : public Create_func_arg3
|
||||
{
|
||||
public:
|
||||
virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
|
||||
|
||||
static Create_func_relate s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_relate() {}
|
||||
virtual ~Create_func_relate() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_mbr_intersects : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
|
|
@ -1596,6 +1649,19 @@ protected:
|
|||
Create_func_isclosed() {}
|
||||
virtual ~Create_func_isclosed() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_isring : public Create_func_arg1
|
||||
{
|
||||
public:
|
||||
virtual Item *create_1_arg(THD *thd, Item *arg1);
|
||||
|
||||
static Create_func_isring s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_isring() {}
|
||||
virtual ~Create_func_isring() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -3338,7 +3404,25 @@ Create_func_centroid::create_1_arg(THD *thd, Item *arg1)
|
|||
{
|
||||
return new (thd->mem_root) Item_func_centroid(arg1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Create_func_convexhull Create_func_convexhull::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_convexhull::create_1_arg(THD *thd, Item *arg1)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_convexhull(arg1);
|
||||
}
|
||||
|
||||
|
||||
Create_func_pointonsurface Create_func_pointonsurface::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_pointonsurface::create_1_arg(THD *thd, Item *arg1)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_pointonsurface(arg1);
|
||||
}
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
|
||||
|
||||
Create_func_char_length Create_func_char_length::s_singleton;
|
||||
|
|
@ -3819,6 +3903,15 @@ Create_func_envelope::create_1_arg(THD *thd, Item *arg1)
|
|||
{
|
||||
return new (thd->mem_root) Item_func_envelope(arg1);
|
||||
}
|
||||
|
||||
|
||||
Create_func_boundary Create_func_boundary::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_boundary::create_1_arg(THD *thd, Item *arg1)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_boundary(arg1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -4329,6 +4422,15 @@ Create_func_interiorringn::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
|||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Create_func_relate Create_func_relate::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_relate::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *matrix)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, matrix);
|
||||
}
|
||||
|
||||
|
||||
Create_func_mbr_intersects Create_func_mbr_intersects::s_singleton;
|
||||
|
||||
Item*
|
||||
|
|
@ -4429,10 +4531,17 @@ Create_func_isclosed::create_1_arg(THD *thd, Item *arg1)
|
|||
{
|
||||
return new (thd->mem_root) Item_func_isclosed(arg1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Create_func_isring Create_func_isring::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_isring::create_1_arg(THD *thd, Item *arg1)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_isring(arg1);
|
||||
}
|
||||
|
||||
|
||||
Create_func_isempty Create_func_isempty::s_singleton;
|
||||
|
||||
Item*
|
||||
|
|
@ -4440,7 +4549,7 @@ Create_func_isempty::create_1_arg(THD *thd, Item *arg1)
|
|||
{
|
||||
return new (thd->mem_root) Item_func_isempty(arg1);
|
||||
}
|
||||
#endif
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
|
||||
|
||||
Create_func_isnull Create_func_isnull::s_singleton;
|
||||
|
|
@ -5656,6 +5765,7 @@ static Native_func_registry func_array[] =
|
|||
{ { C_STRING_WITH_LEN("BINLOG_GTID_POS") }, BUILDER(Create_func_binlog_gtid_pos)},
|
||||
{ { C_STRING_WITH_LEN("BIT_COUNT") }, BUILDER(Create_func_bit_count)},
|
||||
{ { C_STRING_WITH_LEN("BIT_LENGTH") }, BUILDER(Create_func_bit_length)},
|
||||
{ { C_STRING_WITH_LEN("BOUNDARY") }, GEOM_BUILDER(Create_func_boundary)},
|
||||
{ { C_STRING_WITH_LEN("BUFFER") }, GEOM_BUILDER(Create_func_buffer)},
|
||||
{ { C_STRING_WITH_LEN("CEIL") }, BUILDER(Create_func_ceiling)},
|
||||
{ { C_STRING_WITH_LEN("CEILING") }, BUILDER(Create_func_ceiling)},
|
||||
|
|
@ -5673,6 +5783,7 @@ static Native_func_registry func_array[] =
|
|||
{ { C_STRING_WITH_LEN("CONNECTION_ID") }, BUILDER(Create_func_connection_id)},
|
||||
{ { C_STRING_WITH_LEN("CONV") }, BUILDER(Create_func_conv)},
|
||||
{ { C_STRING_WITH_LEN("CONVERT_TZ") }, BUILDER(Create_func_convert_tz)},
|
||||
{ { C_STRING_WITH_LEN("CONVEXHULL") }, GEOM_BUILDER(Create_func_convexhull)},
|
||||
{ { C_STRING_WITH_LEN("COS") }, BUILDER(Create_func_cos)},
|
||||
{ { C_STRING_WITH_LEN("COT") }, BUILDER(Create_func_cot)},
|
||||
{ { C_STRING_WITH_LEN("CRC32") }, BUILDER(Create_func_crc32)},
|
||||
|
|
@ -5737,6 +5848,7 @@ static Native_func_registry func_array[] =
|
|||
{ { C_STRING_WITH_LEN("ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
|
||||
{ { C_STRING_WITH_LEN("ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
|
||||
{ { C_STRING_WITH_LEN("ISNULL") }, BUILDER(Create_func_isnull)},
|
||||
{ { C_STRING_WITH_LEN("ISRING") }, GEOM_BUILDER(Create_func_isring)},
|
||||
{ { C_STRING_WITH_LEN("ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
|
||||
{ { C_STRING_WITH_LEN("IS_FREE_LOCK") }, BUILDER(Create_func_is_free_lock)},
|
||||
{ { C_STRING_WITH_LEN("IS_USED_LOCK") }, BUILDER(Create_func_is_used_lock)},
|
||||
|
|
@ -5803,6 +5915,7 @@ static Native_func_registry func_array[] =
|
|||
{ { C_STRING_WITH_LEN("POINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("POINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("POINTN") }, GEOM_BUILDER(Create_func_pointn)},
|
||||
{ { C_STRING_WITH_LEN("POINTONSURFACE") }, GEOM_BUILDER(Create_func_pointonsurface)},
|
||||
{ { C_STRING_WITH_LEN("POLYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("POLYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("POLYGONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
|
|
@ -5839,9 +5952,11 @@ static Native_func_registry func_array[] =
|
|||
{ { C_STRING_WITH_LEN("ST_ASTEXT") }, GEOM_BUILDER(Create_func_as_wkt)},
|
||||
{ { C_STRING_WITH_LEN("ST_ASWKB") }, GEOM_BUILDER(Create_func_as_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_ASWKT") }, GEOM_BUILDER(Create_func_as_wkt)},
|
||||
{ { C_STRING_WITH_LEN("ST_BOUNDARY") }, GEOM_BUILDER(Create_func_boundary)},
|
||||
{ { C_STRING_WITH_LEN("ST_BUFFER") }, GEOM_BUILDER(Create_func_buffer)},
|
||||
{ { C_STRING_WITH_LEN("ST_CENTROID") }, GEOM_BUILDER(Create_func_centroid)},
|
||||
{ { C_STRING_WITH_LEN("ST_CONTAINS") }, GEOM_BUILDER(Create_func_contains)},
|
||||
{ { C_STRING_WITH_LEN("ST_CONVEXHULL") }, GEOM_BUILDER(Create_func_convexhull)},
|
||||
{ { C_STRING_WITH_LEN("ST_CROSSES") }, GEOM_BUILDER(Create_func_crosses)},
|
||||
{ { C_STRING_WITH_LEN("ST_DIFFERENCE") }, GEOM_BUILDER(Create_func_difference)},
|
||||
{ { C_STRING_WITH_LEN("ST_DIMENSION") }, GEOM_BUILDER(Create_func_dimension)},
|
||||
|
|
@ -5870,6 +5985,7 @@ static Native_func_registry func_array[] =
|
|||
{ { C_STRING_WITH_LEN("ST_INTERSECTION") }, GEOM_BUILDER(Create_func_intersection)},
|
||||
{ { C_STRING_WITH_LEN("ST_ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
|
||||
{ { C_STRING_WITH_LEN("ST_ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
|
||||
{ { C_STRING_WITH_LEN("ST_ISRING") }, GEOM_BUILDER(Create_func_isring)},
|
||||
{ { C_STRING_WITH_LEN("ST_ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
|
||||
{ { C_STRING_WITH_LEN("ST_LENGTH") }, GEOM_BUILDER(Create_func_glength)},
|
||||
{ { C_STRING_WITH_LEN("ST_LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
|
|
@ -5883,10 +5999,12 @@ static Native_func_registry func_array[] =
|
|||
{ { C_STRING_WITH_LEN("ST_POINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_POINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_POINTN") }, GEOM_BUILDER(Create_func_pointn)},
|
||||
{ { C_STRING_WITH_LEN("ST_POINTONSURFACE") }, GEOM_BUILDER(Create_func_pointonsurface)},
|
||||
{ { C_STRING_WITH_LEN("ST_POLYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_POLYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_POLYGONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_POLYGONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_RELATE") }, GEOM_BUILDER(Create_func_relate)},
|
||||
{ { C_STRING_WITH_LEN("ST_SRID") }, GEOM_BUILDER(Create_func_srid)},
|
||||
{ { C_STRING_WITH_LEN("ST_STARTPOINT") }, GEOM_BUILDER(Create_func_startpoint)},
|
||||
{ { C_STRING_WITH_LEN("ST_SYMDIFFERENCE") }, GEOM_BUILDER(Create_func_symdifference)},
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public:
|
|||
SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC,
|
||||
SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC,
|
||||
SP_STARTPOINT,SP_ENDPOINT,SP_EXTERIORRING,
|
||||
SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN,
|
||||
SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN, SP_RELATE_FUNC,
|
||||
NOT_FUNC, NOT_ALL_FUNC,
|
||||
NOW_FUNC, TRIG_COND_FUNC,
|
||||
SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
|
||||
|
|
|
|||
|
|
@ -218,6 +218,130 @@ String *Item_func_envelope::val_str(String *str)
|
|||
}
|
||||
|
||||
|
||||
int Item_func_boundary::Transporter::single_point(double x, double y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Item_func_boundary::Transporter::start_line()
|
||||
{
|
||||
n_points= 0;
|
||||
current_type= Gcalc_function::shape_line;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Item_func_boundary::Transporter::complete_line()
|
||||
{
|
||||
current_type= (Gcalc_function::shape_type) 0;
|
||||
if (n_points > 1)
|
||||
return m_receiver->single_point(last_x, last_y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Item_func_boundary::Transporter::start_poly()
|
||||
{
|
||||
current_type= Gcalc_function::shape_polygon;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Item_func_boundary::Transporter::complete_poly()
|
||||
{
|
||||
current_type= (Gcalc_function::shape_type) 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Item_func_boundary::Transporter::start_ring()
|
||||
{
|
||||
n_points= 0;
|
||||
return m_receiver->start_shape(Gcalc_function::shape_line);
|
||||
}
|
||||
|
||||
|
||||
int Item_func_boundary::Transporter::complete_ring()
|
||||
{
|
||||
if (n_points > 1)
|
||||
{
|
||||
m_receiver->add_point(last_x, last_y);
|
||||
}
|
||||
m_receiver->complete_shape();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Item_func_boundary::Transporter::add_point(double x, double y)
|
||||
{
|
||||
++n_points;
|
||||
if (current_type== Gcalc_function::shape_polygon)
|
||||
{
|
||||
/* Polygon's ring case */
|
||||
if (n_points == 1)
|
||||
{
|
||||
last_x= x;
|
||||
last_y= y;
|
||||
}
|
||||
return m_receiver->add_point(x, y);
|
||||
}
|
||||
|
||||
if (current_type== Gcalc_function::shape_line)
|
||||
{
|
||||
/* Line's case */
|
||||
last_x= x;
|
||||
last_y= y;
|
||||
if (n_points == 1)
|
||||
return m_receiver->single_point(x, y);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Item_func_boundary::Transporter::start_collection(int n_objects)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
String *Item_func_boundary::val_str(String *str_value)
|
||||
{
|
||||
DBUG_ENTER("Item_func_boundary::val_str");
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
String arg_val;
|
||||
String *swkb= args[0]->val_str(&arg_val);
|
||||
Geometry_buffer buffer;
|
||||
Geometry *g;
|
||||
uint32 srid= 0;
|
||||
Transporter trn(&res_receiver);
|
||||
|
||||
if ((null_value=
|
||||
args[0]->null_value ||
|
||||
!(g= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
if (g->store_shapes(&trn))
|
||||
goto mem_error;
|
||||
|
||||
str_value->set_charset(&my_charset_bin);
|
||||
if (str_value->reserve(SRID_SIZE, 512))
|
||||
goto mem_error;
|
||||
str_value->length(0);
|
||||
str_value->q_append(srid);
|
||||
|
||||
if (!Geometry::create_from_opresult(&buffer, str_value, res_receiver))
|
||||
goto mem_error;
|
||||
|
||||
res_receiver.reset();
|
||||
DBUG_RETURN(str_value);
|
||||
|
||||
mem_error:
|
||||
null_value= 1;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
Field::geometry_type Item_func_centroid::get_geometry_type() const
|
||||
{
|
||||
return Field::GEOM_POINT;
|
||||
|
|
@ -248,6 +372,289 @@ String *Item_func_centroid::val_str(String *str)
|
|||
}
|
||||
|
||||
|
||||
int Item_func_convexhull::add_node_to_line(ch_node **p_cur, int dir,
|
||||
const Gcalc_heap::Info *pi)
|
||||
{
|
||||
ch_node *new_node;
|
||||
ch_node *cur= *p_cur;
|
||||
|
||||
while (cur->prev)
|
||||
{
|
||||
int v_sign= Gcalc_scan_iterator::point::cmp_dx_dy(
|
||||
cur->prev->pi, cur->pi, cur->pi, pi);
|
||||
if (v_sign*dir <0)
|
||||
break;
|
||||
new_node= cur;
|
||||
cur= cur->prev;
|
||||
res_heap.free_item(new_node);
|
||||
}
|
||||
if (!(new_node= new_ch_node()))
|
||||
return 1;
|
||||
cur->next= new_node;
|
||||
new_node->prev= cur;
|
||||
new_node->pi= pi;
|
||||
*p_cur= new_node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef HEAVY_CONVEX_HULL
|
||||
String *Item_func_convexhull::val_str(String *str_value)
|
||||
{
|
||||
Geometry_buffer buffer;
|
||||
Geometry *geom= NULL;
|
||||
MBR mbr;
|
||||
const char *c_end;
|
||||
Gcalc_operation_transporter trn(&func, &collector);
|
||||
uint32 srid= 0;
|
||||
ch_node *left_first, *left_cur, *right_first, *right_cur;
|
||||
Gcalc_heap::Info *cur_pi;
|
||||
|
||||
DBUG_ENTER("Item_func_convexhull::val_str");
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
String *swkb= args[0]->val_str(&tmp_value);
|
||||
|
||||
if ((null_value=
|
||||
args[0]->null_value ||
|
||||
!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
geom->get_mbr(&mbr, &c_end);
|
||||
collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
|
||||
if ((null_value= geom->store_shapes(&trn)))
|
||||
{
|
||||
str_value= 0;
|
||||
goto mem_error;
|
||||
}
|
||||
|
||||
collector.prepare_operation();
|
||||
if (!(cur_pi= collector.get_first()))
|
||||
goto build_result; /* An EMPTY GEOMETRY */
|
||||
|
||||
if (!cur_pi->get_next())
|
||||
{
|
||||
/* Single point. */
|
||||
if (res_receiver.single_point(cur_pi->x, cur_pi->y))
|
||||
goto mem_error;
|
||||
goto build_result;
|
||||
}
|
||||
|
||||
left_cur= left_first= new_ch_node();
|
||||
right_cur= right_first= new_ch_node();
|
||||
right_first->prev= left_first->prev= 0;
|
||||
right_first->pi= left_first->pi= cur_pi;
|
||||
|
||||
while ((cur_pi= cur_pi->get_next()))
|
||||
{
|
||||
/* Handle left part of the hull, then the right part. */
|
||||
if (add_node_to_line(&left_cur, 1, cur_pi))
|
||||
goto mem_error;
|
||||
if (add_node_to_line(&right_cur, -1, cur_pi))
|
||||
goto mem_error;
|
||||
}
|
||||
|
||||
left_cur->next= 0;
|
||||
if (left_first->get_next()->get_next() == NULL &&
|
||||
right_cur->prev->prev == NULL)
|
||||
{
|
||||
/* We only have 2 nodes in the result, so we create a polyline. */
|
||||
if (res_receiver.start_shape(Gcalc_function::shape_line) ||
|
||||
res_receiver.add_point(left_first->pi->x, left_first->pi->y) ||
|
||||
res_receiver.add_point(left_cur->pi->x, left_cur->pi->y) ||
|
||||
res_receiver.complete_shape())
|
||||
|
||||
goto mem_error;
|
||||
|
||||
goto build_result;
|
||||
}
|
||||
|
||||
if (res_receiver.start_shape(Gcalc_function::shape_polygon))
|
||||
goto mem_error;
|
||||
|
||||
while (left_first)
|
||||
{
|
||||
if (res_receiver.add_point(left_first->pi->x, left_first->pi->y))
|
||||
goto mem_error;
|
||||
left_first= left_first->get_next();
|
||||
}
|
||||
|
||||
/* Skip last point in the right part as it coincides */
|
||||
/* with the last one in the left. */
|
||||
right_cur= right_cur->prev;
|
||||
while (right_cur->prev)
|
||||
{
|
||||
if (res_receiver.add_point(right_cur->pi->x, right_cur->pi->y))
|
||||
goto mem_error;
|
||||
right_cur= right_cur->prev;
|
||||
}
|
||||
res_receiver.complete_shape();
|
||||
|
||||
build_result:
|
||||
str_value->set_charset(&my_charset_bin);
|
||||
if (str_value->reserve(SRID_SIZE, 512))
|
||||
goto mem_error;
|
||||
str_value->length(0);
|
||||
str_value->q_append(srid);
|
||||
|
||||
if (!Geometry::create_from_opresult(&buffer, str_value, res_receiver))
|
||||
goto mem_error;
|
||||
|
||||
mem_error:
|
||||
collector.reset();
|
||||
func.reset();
|
||||
res_receiver.reset();
|
||||
res_heap.reset();
|
||||
DBUG_RETURN(str_value);
|
||||
}
|
||||
|
||||
#else /*HEAVY_CONVEX_HULL*/
|
||||
String *Item_func_convexhull::val_str(String *str_value)
|
||||
{
|
||||
Geometry_buffer buffer;
|
||||
Geometry *geom= NULL;
|
||||
MBR mbr;
|
||||
const char *c_end;
|
||||
Gcalc_operation_transporter trn(&func, &collector);
|
||||
const Gcalc_scan_iterator::event_point *ev;
|
||||
uint32 srid= 0;
|
||||
ch_node *left_first, *left_cur, *right_first, *right_cur;
|
||||
|
||||
DBUG_ENTER("Item_func_convexhull::val_str");
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
String *swkb= args[0]->val_str(&tmp_value);
|
||||
|
||||
if ((null_value=
|
||||
args[0]->null_value ||
|
||||
!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
geom->get_mbr(&mbr, &c_end);
|
||||
collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
|
||||
if ((null_value= geom->store_shapes(&trn)))
|
||||
{
|
||||
str_value= 0;
|
||||
goto mem_error;
|
||||
}
|
||||
|
||||
collector.prepare_operation();
|
||||
scan_it.init(&collector);
|
||||
scan_it.killed= (int *) &(current_thd->killed);
|
||||
|
||||
if (!scan_it.more_points())
|
||||
goto build_result; /* An EMPTY GEOMETRY */
|
||||
|
||||
if (scan_it.step())
|
||||
goto mem_error;
|
||||
|
||||
if (!scan_it.more_points())
|
||||
{
|
||||
/* Single point. */
|
||||
if (res_receiver.single_point(scan_it.get_events()->pi->x,
|
||||
scan_it.get_events()->pi->y))
|
||||
goto mem_error;
|
||||
goto build_result;
|
||||
}
|
||||
|
||||
left_cur= left_first= new_ch_node();
|
||||
right_cur= right_first= new_ch_node();
|
||||
right_first->prev= left_first->prev= 0;
|
||||
right_first->pi= left_first->pi= scan_it.get_events()->pi;
|
||||
|
||||
while (scan_it.more_points())
|
||||
{
|
||||
if (scan_it.step())
|
||||
goto mem_error;
|
||||
ev= scan_it.get_events();
|
||||
|
||||
/* Skip the intersections-only events. */
|
||||
while (ev->event == scev_intersection)
|
||||
{
|
||||
ev= ev->get_next();
|
||||
if (!ev)
|
||||
goto skip_point;
|
||||
}
|
||||
|
||||
{
|
||||
Gcalc_point_iterator pit(&scan_it);
|
||||
if (!pit.point() || scan_it.get_event_position() == pit.point())
|
||||
{
|
||||
/* Handle left part of the hull. */
|
||||
if (add_node_to_line(&left_cur, 1, ev->pi))
|
||||
goto mem_error;
|
||||
}
|
||||
if (pit.point())
|
||||
{
|
||||
/* Check the rightmost point */
|
||||
for(; pit.point()->c_get_next(); ++pit)
|
||||
;
|
||||
}
|
||||
if (!pit.point() || pit.point()->event ||
|
||||
scan_it.get_event_position() == pit.point()->c_get_next())
|
||||
{
|
||||
/* Handle right part of the hull. */
|
||||
if (add_node_to_line(&right_cur, -1, ev->pi))
|
||||
goto mem_error;
|
||||
}
|
||||
}
|
||||
skip_point:;
|
||||
}
|
||||
|
||||
left_cur->next= 0;
|
||||
if (left_first->get_next()->get_next() == NULL &&
|
||||
right_cur->prev->prev == NULL)
|
||||
{
|
||||
/* We only have 2 nodes in the result, so we create a polyline. */
|
||||
if (res_receiver.start_shape(Gcalc_function::shape_line) ||
|
||||
res_receiver.add_point(left_first->pi->x, left_first->pi->y) ||
|
||||
res_receiver.add_point(left_cur->pi->x, left_cur->pi->y) ||
|
||||
res_receiver.complete_shape())
|
||||
|
||||
goto mem_error;
|
||||
|
||||
goto build_result;
|
||||
}
|
||||
|
||||
if (res_receiver.start_shape(Gcalc_function::shape_polygon))
|
||||
goto mem_error;
|
||||
|
||||
while (left_first)
|
||||
{
|
||||
if (res_receiver.add_point(left_first->pi->x, left_first->pi->y))
|
||||
goto mem_error;
|
||||
left_first= left_first->get_next();
|
||||
}
|
||||
|
||||
/* Skip last point in the right part as it coincides */
|
||||
/* with the last one in the left. */
|
||||
right_cur= right_cur->prev;
|
||||
while (right_cur->prev)
|
||||
{
|
||||
if (res_receiver.add_point(right_cur->pi->x, right_cur->pi->y))
|
||||
goto mem_error;
|
||||
right_cur= right_cur->prev;
|
||||
}
|
||||
res_receiver.complete_shape();
|
||||
|
||||
build_result:
|
||||
str_value->set_charset(&my_charset_bin);
|
||||
if (str_value->reserve(SRID_SIZE, 512))
|
||||
goto mem_error;
|
||||
str_value->length(0);
|
||||
str_value->q_append(srid);
|
||||
|
||||
if (!Geometry::create_from_opresult(&buffer, str_value, res_receiver))
|
||||
goto mem_error;
|
||||
|
||||
mem_error:
|
||||
collector.reset();
|
||||
func.reset();
|
||||
res_receiver.reset();
|
||||
res_heap.reset();
|
||||
DBUG_RETURN(str_value);
|
||||
}
|
||||
#endif /*HEAVY_CONVEX_HULL*/
|
||||
|
||||
|
||||
/*
|
||||
Spatial decomposition functions
|
||||
*/
|
||||
|
|
@ -593,12 +1000,17 @@ longlong Item_func_spatial_mbr_rel::val_int()
|
|||
|
||||
Item_func_spatial_rel::Item_func_spatial_rel(Item *a,Item *b,
|
||||
enum Functype sp_rel) :
|
||||
Item_bool_func2(a,b), collector()
|
||||
Item_int_func(a,b), collector()
|
||||
{
|
||||
spatial_rel = sp_rel;
|
||||
}
|
||||
|
||||
|
||||
Item_func_spatial_rel::Item_func_spatial_rel(Item *a,Item *b, Item *mask) :
|
||||
Item_int_func(a,b,mask), spatial_rel(SP_RELATE_FUNC)
|
||||
{}
|
||||
|
||||
|
||||
Item_func_spatial_rel::~Item_func_spatial_rel()
|
||||
{
|
||||
}
|
||||
|
|
@ -623,6 +1035,8 @@ const char *Item_func_spatial_rel::func_name() const
|
|||
return "st_crosses";
|
||||
case SP_OVERLAPS_FUNC:
|
||||
return "st_overlaps";
|
||||
case SP_RELATE_FUNC:
|
||||
return "st_relate";
|
||||
default:
|
||||
DBUG_ASSERT(0); // Should never happened
|
||||
return "sp_unknown";
|
||||
|
|
@ -661,6 +1075,84 @@ static double distance_points(const Gcalc_heap::Info *a,
|
|||
}
|
||||
|
||||
|
||||
static Gcalc_function::op_type op_matrix(int n)
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
return Gcalc_function::op_border;
|
||||
case 1:
|
||||
return Gcalc_function::op_internals;
|
||||
case 2:
|
||||
return (Gcalc_function::op_type)
|
||||
((int) Gcalc_function::op_not | (int) Gcalc_function::op_union);
|
||||
};
|
||||
GCALC_DBUG_ASSERT(FALSE);
|
||||
return Gcalc_function::op_any;
|
||||
}
|
||||
|
||||
|
||||
static int setup_relate_func(Geometry *g1, Geometry *g2,
|
||||
Gcalc_operation_transporter *trn, Gcalc_function *func,
|
||||
const char *mask)
|
||||
{
|
||||
int do_store_shapes=1;
|
||||
uint shape_a, shape_b;
|
||||
uint n_operands= 0;
|
||||
int last_shape_pos;
|
||||
|
||||
last_shape_pos= func->get_next_expression_pos();
|
||||
func->add_operation(Gcalc_function::op_intersection, 0);
|
||||
for (int nc=0; nc<9; nc++)
|
||||
{
|
||||
uint cur_op;
|
||||
|
||||
cur_op= Gcalc_function::op_intersection;
|
||||
switch (mask[nc])
|
||||
{
|
||||
case '*':
|
||||
continue;
|
||||
case 'T':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
cur_op|= Gcalc_function::v_find_t;
|
||||
break;
|
||||
case 'F':
|
||||
cur_op|= Gcalc_function::v_find_f;
|
||||
break;
|
||||
};
|
||||
++n_operands;
|
||||
if (func->reserve_op_buffer(1))
|
||||
return 1;
|
||||
func->add_operation(cur_op, 2);
|
||||
|
||||
func->add_operation(op_matrix(nc/3), 1);
|
||||
if (do_store_shapes)
|
||||
{
|
||||
shape_a= func->get_next_expression_pos();
|
||||
if (g1->store_shapes(trn))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
func->repeat_expression(shape_a);
|
||||
func->add_operation(op_matrix(nc%3), 1);
|
||||
if (do_store_shapes)
|
||||
{
|
||||
shape_b= func->get_next_expression_pos();
|
||||
if (g2->store_shapes(trn))
|
||||
return 1;
|
||||
do_store_shapes= 0;
|
||||
}
|
||||
else
|
||||
func->repeat_expression(shape_b);
|
||||
}
|
||||
|
||||
func->add_operands_to_op(last_shape_pos, n_operands);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define GIS_ZERO 0.00000000001
|
||||
|
||||
longlong Item_func_spatial_rel::val_int()
|
||||
|
|
@ -669,6 +1161,7 @@ longlong Item_func_spatial_rel::val_int()
|
|||
DBUG_ASSERT(fixed == 1);
|
||||
String *res1;
|
||||
String *res2;
|
||||
String *res3;
|
||||
Geometry_buffer buffer1, buffer2;
|
||||
Geometry *g1, *g2;
|
||||
int result= 0;
|
||||
|
|
@ -736,6 +1229,8 @@ longlong Item_func_spatial_rel::val_int()
|
|||
case SP_OVERLAPS_FUNC:
|
||||
case SP_CROSSES_FUNC:
|
||||
func.add_operation(Gcalc_function::op_intersection, 2);
|
||||
if (func.reserve_op_buffer(1))
|
||||
break;
|
||||
func.add_operation(Gcalc_function::v_find_t |
|
||||
Gcalc_function::op_intersection, 2);
|
||||
shape_a= func.get_next_expression_pos();
|
||||
|
|
@ -744,6 +1239,8 @@ longlong Item_func_spatial_rel::val_int()
|
|||
shape_b= func.get_next_expression_pos();
|
||||
if ((null_value= g2->store_shapes(&trn)))
|
||||
break;
|
||||
if (func.reserve_op_buffer(7))
|
||||
break;
|
||||
func.add_operation(Gcalc_function::v_find_t |
|
||||
Gcalc_function::op_intersection, 2);
|
||||
func.add_operation(Gcalc_function::v_find_t |
|
||||
|
|
@ -756,6 +1253,8 @@ longlong Item_func_spatial_rel::val_int()
|
|||
func.repeat_expression(shape_a);
|
||||
break;
|
||||
case SP_TOUCHES_FUNC:
|
||||
if (func.reserve_op_buffer(2))
|
||||
break;
|
||||
func.add_operation(Gcalc_function::op_intersection, 2);
|
||||
func.add_operation(Gcalc_function::v_find_f |
|
||||
Gcalc_function::op_not |
|
||||
|
|
@ -775,6 +1274,13 @@ longlong Item_func_spatial_rel::val_int()
|
|||
func.add_operation(Gcalc_function::op_border, 1);
|
||||
func.repeat_expression(shape_b);
|
||||
break;
|
||||
case SP_RELATE_FUNC:
|
||||
res3= args[2]->val_str(&tmp_matrix);
|
||||
if ((null_value= args[2]->null_value))
|
||||
break;
|
||||
null_value= (res3->length() != 9) ||
|
||||
setup_relate_func(g1, g2, &trn, &func, res3->ptr());
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(FALSE);
|
||||
break;
|
||||
|
|
@ -859,7 +1365,7 @@ String *Item_func_spatial_operation::val_str(String *str_value)
|
|||
str_value->length(0);
|
||||
str_value->q_append(srid);
|
||||
|
||||
if (Geometry::create_from_opresult(&buffer1, str_value, res_receiver))
|
||||
if (!Geometry::create_from_opresult(&buffer1, str_value, res_receiver))
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
|
|
@ -1319,7 +1825,7 @@ String *Item_func_buffer::val_str(String *str_value)
|
|||
str_value->length(0);
|
||||
str_value->q_append(srid);
|
||||
|
||||
if (Geometry::create_from_opresult(&buffer, str_value, res_receiver))
|
||||
if (!Geometry::create_from_opresult(&buffer, str_value, res_receiver))
|
||||
goto mem_error;
|
||||
|
||||
null_value= 0;
|
||||
|
|
@ -1423,6 +1929,30 @@ longlong Item_func_isclosed::val_int()
|
|||
return (longlong) isclosed;
|
||||
}
|
||||
|
||||
|
||||
longlong Item_func_isring::val_int()
|
||||
{
|
||||
/* It's actually a combination of two functions - IsClosed and IsSimple */
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
String tmp;
|
||||
String *swkb= args[0]->val_str(&tmp);
|
||||
Geometry_buffer buffer;
|
||||
Geometry *geom;
|
||||
int isclosed= 0; // In case of error
|
||||
|
||||
null_value= (!swkb ||
|
||||
args[0]->null_value ||
|
||||
!(geom=
|
||||
Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
|
||||
geom->is_closed(&isclosed));
|
||||
|
||||
if (!isclosed)
|
||||
return 0;
|
||||
|
||||
return Item_func_issimple::val_int();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Numerical functions
|
||||
*/
|
||||
|
|
@ -1739,6 +2269,121 @@ mem_error:
|
|||
}
|
||||
|
||||
|
||||
String *Item_func_pointonsurface::val_str(String *str)
|
||||
{
|
||||
Gcalc_operation_transporter trn(&func, &collector);
|
||||
|
||||
DBUG_ENTER("Item_func_pointonsurface::val_real");
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
String *res= args[0]->val_str(&tmp_value);
|
||||
Geometry_buffer buffer;
|
||||
Geometry *g;
|
||||
MBR mbr;
|
||||
const char *c_end;
|
||||
double px, py, x0, y0;
|
||||
String *result= 0;
|
||||
const Gcalc_scan_iterator::point *pprev= NULL;
|
||||
uint32 srid;
|
||||
|
||||
|
||||
null_value= 1;
|
||||
if ((args[0]->null_value ||
|
||||
!(g= Geometry::construct(&buffer, res->ptr(), res->length())) ||
|
||||
g->get_mbr(&mbr, &c_end)))
|
||||
goto mem_error;
|
||||
|
||||
collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
|
||||
|
||||
if (g->store_shapes(&trn))
|
||||
goto mem_error;
|
||||
|
||||
collector.prepare_operation();
|
||||
scan_it.init(&collector);
|
||||
|
||||
while (scan_it.more_points())
|
||||
{
|
||||
if (scan_it.step())
|
||||
goto mem_error;
|
||||
|
||||
if (scan_it.get_h() > GIS_ZERO)
|
||||
{
|
||||
y0= scan_it.get_y();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scan_it.more_points())
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (scan_it.step())
|
||||
goto mem_error;
|
||||
|
||||
for (Gcalc_point_iterator pit(&scan_it); pit.point(); ++pit)
|
||||
{
|
||||
if (pprev == NULL)
|
||||
{
|
||||
pprev= pit.point();
|
||||
continue;
|
||||
}
|
||||
x0= scan_it.get_sp_x(pprev);
|
||||
px= scan_it.get_sp_x(pit.point());
|
||||
if (px - x0 > GIS_ZERO)
|
||||
{
|
||||
if (scan_it.get_h() > GIS_ZERO)
|
||||
{
|
||||
px= (px + x0) / 2.0;
|
||||
py= scan_it.get_y();
|
||||
}
|
||||
else
|
||||
{
|
||||
px= (px + x0) / 2.0;
|
||||
py= (y0 + scan_it.get_y()) / 2.0;
|
||||
}
|
||||
null_value= 0;
|
||||
break;
|
||||
}
|
||||
pprev= NULL;
|
||||
}
|
||||
|
||||
if (null_value)
|
||||
goto exit;
|
||||
|
||||
str->set_charset(&my_charset_bin);
|
||||
if (str->reserve(SRID_SIZE, 512))
|
||||
goto mem_error;
|
||||
|
||||
str->length(0);
|
||||
srid= uint4korr(res->ptr());
|
||||
str->q_append(srid);
|
||||
|
||||
if (Geometry::create_point(str, px, py))
|
||||
goto mem_error;
|
||||
|
||||
result= str;
|
||||
|
||||
exit:
|
||||
collector.reset();
|
||||
func.reset();
|
||||
scan_it.reset();
|
||||
DBUG_RETURN(result);
|
||||
|
||||
mem_error:
|
||||
collector.reset();
|
||||
func.reset();
|
||||
scan_it.reset();
|
||||
null_value= 1;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
Field::geometry_type Item_func_pointonsurface::get_geometry_type() const
|
||||
{
|
||||
return Field::GEOM_POINT;
|
||||
}
|
||||
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
longlong Item_func_gis_debug::val_int()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -93,6 +93,39 @@ public:
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
// #define HEAVY_CONVEX_HULL
|
||||
class Item_func_convexhull: public Item_geometry_func
|
||||
{
|
||||
class ch_node: public Gcalc_dyn_list::Item
|
||||
{
|
||||
public:
|
||||
const Gcalc_heap::Info *pi;
|
||||
ch_node *prev;
|
||||
Gcalc_dyn_list::Item *next;
|
||||
ch_node *get_next() { return (ch_node *) next; }
|
||||
};
|
||||
|
||||
Gcalc_heap collector;
|
||||
Gcalc_function func;
|
||||
Gcalc_dyn_list res_heap;
|
||||
|
||||
Gcalc_result_receiver res_receiver;
|
||||
String tmp_value;
|
||||
#ifdef HEAVY_CONVEX_HULL
|
||||
Gcalc_scan_iterator scan_it;
|
||||
#endif /*HEAVY_CONVEX_HULL*/
|
||||
ch_node *new_ch_node() { return (ch_node *) res_heap.new_item(); }
|
||||
int add_node_to_line(ch_node **p_cur, int dir, const Gcalc_heap::Info *pi);
|
||||
public:
|
||||
Item_func_convexhull(Item *a): Item_geometry_func(a),
|
||||
res_heap(8192, sizeof(ch_node))
|
||||
{}
|
||||
const char *func_name() const { return "st_convexhull"; }
|
||||
String *val_str(String *);
|
||||
};
|
||||
|
||||
|
||||
class Item_func_centroid: public Item_geometry_func
|
||||
{
|
||||
public:
|
||||
|
|
@ -111,6 +144,38 @@ public:
|
|||
Field::geometry_type get_geometry_type() const;
|
||||
};
|
||||
|
||||
|
||||
class Item_func_boundary: public Item_geometry_func
|
||||
{
|
||||
class Transporter : public Gcalc_shape_transporter
|
||||
{
|
||||
Gcalc_result_receiver *m_receiver;
|
||||
uint n_points;
|
||||
Gcalc_function::shape_type current_type;
|
||||
double last_x, last_y;
|
||||
public:
|
||||
Transporter(Gcalc_result_receiver *receiver) :
|
||||
Gcalc_shape_transporter(NULL), m_receiver(receiver)
|
||||
{}
|
||||
int single_point(double x, double y);
|
||||
int start_line();
|
||||
int complete_line();
|
||||
int start_poly();
|
||||
int complete_poly();
|
||||
int start_ring();
|
||||
int complete_ring();
|
||||
int add_point(double x, double y);
|
||||
|
||||
int start_collection(int n_objects);
|
||||
};
|
||||
Gcalc_result_receiver res_receiver;
|
||||
public:
|
||||
Item_func_boundary(Item *a): Item_geometry_func(a) {}
|
||||
const char *func_name() const { return "st_boundary"; }
|
||||
String *val_str(String *);
|
||||
};
|
||||
|
||||
|
||||
class Item_func_point: public Item_geometry_func
|
||||
{
|
||||
public:
|
||||
|
|
@ -229,15 +294,16 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class Item_func_spatial_rel: public Item_bool_func2
|
||||
class Item_func_spatial_rel: public Item_int_func
|
||||
{
|
||||
enum Functype spatial_rel;
|
||||
Gcalc_heap collector;
|
||||
Gcalc_scan_iterator scan_it;
|
||||
Gcalc_function func;
|
||||
String tmp_value1,tmp_value2;
|
||||
String tmp_value1,tmp_value2, tmp_matrix;
|
||||
public:
|
||||
Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel);
|
||||
Item_func_spatial_rel(Item *a, Item *b, Item *matrix);
|
||||
virtual ~Item_func_spatial_rel();
|
||||
longlong val_int();
|
||||
enum Functype functype() const
|
||||
|
|
@ -253,6 +319,9 @@ public:
|
|||
|
||||
void fix_length_and_dec() { maybe_null= 1; }
|
||||
bool is_null() { (void) val_int(); return null_value; }
|
||||
bool is_bool_func() { return 1; }
|
||||
uint decimal_precision() const { return 1; }
|
||||
optimize_type select_optimize() const { return OPTIMIZE_OP; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -369,6 +438,14 @@ public:
|
|||
void fix_length_and_dec() { maybe_null= 1; }
|
||||
};
|
||||
|
||||
class Item_func_isring: public Item_func_issimple
|
||||
{
|
||||
public:
|
||||
Item_func_isring(Item *a): Item_func_issimple(a) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "st_isring"; }
|
||||
};
|
||||
|
||||
class Item_func_dimension: public Item_int_func
|
||||
{
|
||||
String value;
|
||||
|
|
@ -497,6 +574,20 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class Item_func_pointonsurface: public Item_geometry_func
|
||||
{
|
||||
String tmp_value;
|
||||
Gcalc_heap collector;
|
||||
Gcalc_function func;
|
||||
Gcalc_scan_iterator scan_it;
|
||||
public:
|
||||
Item_func_pointonsurface(Item *a): Item_geometry_func(a) {}
|
||||
const char *func_name() const { return "st_pointonsurface"; }
|
||||
String *val_str(String *);
|
||||
Field::geometry_type get_geometry_type() const;
|
||||
};
|
||||
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
class Item_func_gis_debug: public Item_int_func
|
||||
{
|
||||
|
|
|
|||
|
|
@ -291,19 +291,18 @@ Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer,
|
|||
}
|
||||
|
||||
|
||||
int Geometry::create_from_opresult(Geometry_buffer *g_buf,
|
||||
Geometry *Geometry::create_from_opresult(Geometry_buffer *g_buf,
|
||||
String *res, Gcalc_result_receiver &rr)
|
||||
{
|
||||
uint32 geom_type= rr.get_result_typeid();
|
||||
Geometry *obj= create_by_typeid(g_buf, geom_type);
|
||||
|
||||
if (!obj || res->reserve(WKB_HEADER_SIZE, 512))
|
||||
return 1;
|
||||
return NULL;
|
||||
|
||||
res->q_append((char) wkb_ndr);
|
||||
res->q_append(geom_type);
|
||||
return obj->init_from_opresult(res, rr.result(), rr.length()) == 0 &&
|
||||
rr.length();
|
||||
return obj->init_from_opresult(res, rr.result(), rr.length()) ? obj : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -386,7 +385,7 @@ bool Geometry::create_point(String *result, const char *data) const
|
|||
1 Can't reallocate 'result'
|
||||
*/
|
||||
|
||||
bool Geometry::create_point(String *result, double x, double y) const
|
||||
bool Geometry::create_point(String *result, double x, double y)
|
||||
{
|
||||
if (result->reserve(1 + 4 + POINT_DATA_SIZE))
|
||||
return 1;
|
||||
|
|
@ -2221,6 +2220,13 @@ uint Gis_geometry_collection::init_from_opresult(String *bin,
|
|||
return 0;
|
||||
bin->q_append(n_objects);
|
||||
|
||||
if (res_len == 0)
|
||||
{
|
||||
/* Special case of GEOMETRYCOLLECTION EMPTY. */
|
||||
opres+= 1;
|
||||
goto empty_geom;
|
||||
}
|
||||
|
||||
while (res_len)
|
||||
{
|
||||
switch ((Gcalc_function::shape_type) uint4korr(opres))
|
||||
|
|
@ -2244,6 +2250,7 @@ uint Gis_geometry_collection::init_from_opresult(String *bin,
|
|||
res_len-= g_len;
|
||||
n_objects++;
|
||||
}
|
||||
empty_geom:
|
||||
bin->write_at_position(no_pos, n_objects);
|
||||
return (uint) (opres - opres_orig);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ public:
|
|||
bool init_stream=1);
|
||||
static Geometry *create_from_wkb(Geometry_buffer *buffer,
|
||||
const char *wkb, uint32 len, String *res);
|
||||
static int create_from_opresult(Geometry_buffer *g_buf,
|
||||
static Geometry *create_from_opresult(Geometry_buffer *g_buf,
|
||||
String *res, Gcalc_result_receiver &rr);
|
||||
int as_wkt(String *wkt, const char **end);
|
||||
|
||||
|
|
@ -316,6 +316,7 @@ public:
|
|||
bool envelope(String *result) const;
|
||||
static Class_info *ci_collection[wkb_last+1];
|
||||
|
||||
static bool create_point(String *result, double x, double y);
|
||||
protected:
|
||||
static Class_info *find_class(int type_id)
|
||||
{
|
||||
|
|
@ -326,7 +327,6 @@ protected:
|
|||
const char *append_points(String *txt, uint32 n_points,
|
||||
const char *data, uint32 offset) const;
|
||||
bool create_point(String *result, const char *data) const;
|
||||
bool create_point(String *result, double x, double y) const;
|
||||
const char *get_mbr_for_points(MBR *mbr, const char *data, uint offset)
|
||||
const;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue