Commit 5123f59e authored by Alexey Botchkov's avatar Alexey Botchkov

fixed bugs

855485  ST_CROSSES returns different result than PostGIS for overlapping polygons
855487  ST_WITHIN returns wrong result for partially overlapping polygons
855492  ST_WITHIN returns TRUE on point on the edge of a polygon
855497  ST_ENVELOPE of GEOMETRYCOLLECTION EMPTY returns NULL and not GEOMETRYCOLLECTION EMPTY
855503  ST_EQUALS reports TRUE between a POLYGON and a MULTILINESTRING
855505  ST_TOUCHES reports TRUE for intersecting polygon and linestring

        Changed the way weird functions like Crosses or Touches treated.
        Added BORDER handling to the Gcalc_function.

per-file comments:
  mysql-test/r/gis-precise.result
        GIS bugs fixed.
        test result updated.
  mysql-test/t/gis-precise.test
        GIS bugs fixed.
        test cases added.
  sql/gcalc_slicescan.h
        GIS bugs fixed.
  sql/gcalc_tools.cc
        GIS bugs fixed.
  sql/gcalc_tools.h
        GIS bugs fixed.
  sql/item_create.cc
        GIS bugs fixed.
  sql/item_geofunc.cc
        GIS bugs fixed.
  sql/item_geofunc.h
        GIS bugs fixed.
  sql/spatial.cc
        GIS bugs fixed.
parent d0f2e1e5
...@@ -7,7 +7,7 @@ select 0, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFro ...@@ -7,7 +7,7 @@ select 0, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFro
0 0 0 0
select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POINT(10 10)')); select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POINT(10 10)'));
1 ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POINT(10 10)')) 1 ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POINT(10 10)'))
1 1 1 0
select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))')); select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
1 ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))')) 1 ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'))
1 1 1 1
...@@ -25,48 +25,90 @@ insert into t1 values ...@@ -25,48 +25,90 @@ insert into t1 values
(GeomFromText('POINT(8 2)')), (GeomFromText('POINT(8 4)')), (GeomFromText('POINT(8 6)')), (GeomFromText('POINT(8 8)')); (GeomFromText('POINT(8 2)')), (GeomFromText('POINT(8 4)')), (GeomFromText('POINT(8 6)')), (GeomFromText('POINT(8 8)'));
select astext(g) from t1 where ST_Within(g, GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))')); select astext(g) from t1 where ST_Within(g, GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'));
astext(g) astext(g)
POINT(2 2)
POINT(2 4)
POINT(2 6)
POINT(2 8)
POINT(4 2) POINT(4 2)
POINT(4 4) POINT(4 4)
POINT(4 6) POINT(4 6)
POINT(4 8)
POINT(6 2) POINT(6 2)
POINT(6 4) POINT(6 4)
POINT(6 6) POINT(6 6)
POINT(6 8)
POINT(8 2)
POINT(8 4)
POINT(8 6)
POINT(8 8)
select 'Contains'; select 'Contains';
Contains Contains
Contains Contains
select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g); select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g);
astext(g) astext(g)
POINT(2 2)
POINT(2 4)
POINT(2 6)
POINT(2 8)
POINT(4 2)
POINT(4 4) POINT(4 4)
POINT(4 6)
POINT(4 8)
POINT(6 2) POINT(6 2)
POINT(6 4) POINT(6 4)
POINT(6 6) POINT(6 6)
POINT(6 8)
POINT(8 2)
POINT(8 4)
POINT(8 6)
POINT(8 8)
select 'Intersects'; select 'Intersects';
Intersects Intersects
Intersects Intersects
select astext(g) from t1 where ST_Intersects(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g); select astext(g) from t1 where ST_Intersects(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g);
astext(g) astext(g)
POINT(4 4)
POINT(6 2)
POINT(6 4)
POINT(6 6)
select 'Contains'; select 'Contains';
Contains Contains
Contains Contains
select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g); select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g);
astext(g) astext(g)
POINT(2 2)
POINT(2 4)
POINT(2 6)
POINT(2 8)
POINT(4 2)
POINT(4 4) POINT(4 4)
POINT(4 6)
POINT(4 8)
POINT(6 2) POINT(6 2)
POINT(6 4) POINT(6 4)
POINT(6 6) POINT(6 6)
POINT(6 8)
POINT(8 2)
POINT(8 4)
POINT(8 6)
POINT(8 8)
select 'Contains2'; select 'Contains2';
Contains2 Contains2
Contains2 Contains2
select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1), (5.01 3.01, 6 5, 9 5, 8 3, 5.01 3.01))'), g); select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1), (5.01 3.01, 6 5, 9 5, 8 3, 5.01 3.01))'), g);
astext(g) astext(g)
POINT(2 2)
POINT(2 4)
POINT(2 6)
POINT(2 8)
POINT(4 2)
POINT(4 4) POINT(4 4)
POINT(4 6)
POINT(4 8)
POINT(6 2) POINT(6 2)
POINT(6 4)
POINT(6 6) POINT(6 6)
POINT(6 8)
POINT(8 2)
POINT(8 4) POINT(8 4)
POINT(8 6)
POINT(8 8)
DROP TABLE t1; DROP TABLE t1;
select 0, ST_Within(GeomFromText('LINESTRING(15 15, 50 50, 60 60)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))')); select 0, ST_Within(GeomFromText('LINESTRING(15 15, 50 50, 60 60)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
0 ST_Within(GeomFromText('LINESTRING(15 15, 50 50, 60 60)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))')) 0 ST_Within(GeomFromText('LINESTRING(15 15, 50 50, 60 60)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'))
...@@ -94,7 +136,7 @@ ST_Intersects(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('P ...@@ -94,7 +136,7 @@ ST_Intersects(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('P
1 1
select ST_contains(GeomFromText('MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)), ((6 6, 6 11, 11 11, 11 6, 6 6)))'), GeomFromText('POINT(5 10)')); select ST_contains(GeomFromText('MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)), ((6 6, 6 11, 11 11, 11 6, 6 6)))'), GeomFromText('POINT(5 10)'));
ST_contains(GeomFromText('MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)), ((6 6, 6 11, 11 11, 11 6, 6 6)))'), GeomFromText('POINT(5 10)')) ST_contains(GeomFromText('MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)), ((6 6, 6 11, 11 11, 11 6, 6 6)))'), GeomFromText('POINT(5 10)'))
0 1
select ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 15, 15 15, 15 10, 10 10))')); select ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 15, 15 15, 15 10, 10 10))'));
ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 15, 15 15, 15 10, 10 10))')) ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 15, 15 15, 15 10, 10 10))'))
1 1
...@@ -177,10 +219,10 @@ st_touches(geomfromtext('point(0 0)'), geomfromtext('point(1 1)')) ...@@ -177,10 +219,10 @@ st_touches(geomfromtext('point(0 0)'), geomfromtext('point(1 1)'))
0 0
select st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 1)')); select st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 1)'));
st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 1)')) st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 1)'))
1 0
select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 1)')); select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 1)'));
st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 1)')) st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 1)'))
1 0
select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)')); select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)'));
st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)')) st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)'))
0 0
...@@ -189,7 +231,7 @@ st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 ...@@ -189,7 +231,7 @@ st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1
0 0
select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1.2, 1 0, 2 0, 1 1.2))')); select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1.2, 1 0, 2 0, 1 1.2))'));
st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1.2, 1 0, 2 0, 1 1.2))')) st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1.2, 1 0, 2 0, 1 1.2))'))
0 1
select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))')); select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))'));
st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))')) st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))'))
1 1
...@@ -319,7 +361,7 @@ PolygonFromText(' POLYGON( ( 2 2 , 3 2 , 3 3 , 2 5 , 2 2 ) ) ') ) ) ...@@ -319,7 +361,7 @@ PolygonFromText(' POLYGON( ( 2 2 , 3 2 , 3 3 , 2 5 , 2 2 ) ) ') ) )
POLYGON((2 0,2 5,3 3,3 2,7 5,2 0)) POLYGON((2 0,2 5,3 3,3 2,7 5,2 0))
SELECT AsText(ST_INTERSECTION(LinestringFromText('LINESTRING(1 1, 2 2)'), GeometryFromText('LINESTRING(3 3, 4 4)'))); SELECT AsText(ST_INTERSECTION(LinestringFromText('LINESTRING(1 1, 2 2)'), GeometryFromText('LINESTRING(3 3, 4 4)')));
AsText(ST_INTERSECTION(LinestringFromText('LINESTRING(1 1, 2 2)'), GeometryFromText('LINESTRING(3 3, 4 4)'))) AsText(ST_INTERSECTION(LinestringFromText('LINESTRING(1 1, 2 2)'), GeometryFromText('LINESTRING(3 3, 4 4)')))
GEOMETRYCOLLECTION() GEOMETRYCOLLECTION EMPTY
SELECT AsText(ST_UNION(GEOMETRYFROMTEXT('POINT(8 1)') ,MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 5, 2 5, 2 4, 3 4, 3 5))'))); SELECT AsText(ST_UNION(GEOMETRYFROMTEXT('POINT(8 1)') ,MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 5, 2 5, 2 4, 3 4, 3 5))')));
AsText(ST_UNION(GEOMETRYFROMTEXT('POINT(8 1)') ,MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 5, 2 5, 2 4, 3 4, 3 5))'))) AsText(ST_UNION(GEOMETRYFROMTEXT('POINT(8 1)') ,MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 5, 2 5, 2 4, 3 4, 3 5))')))
GEOMETRYCOLLECTION(POINT(8 1),LINESTRING(2 4,2 5,3 5,3 4,2 4)) GEOMETRYCOLLECTION(POINT(8 1),LINESTRING(2 4,2 5,3 5,3 4,2 4))
...@@ -355,17 +397,6 @@ ST_NUMGEOMETRIES(ST_DIFFERENCE ( ...@@ -355,17 +397,6 @@ ST_NUMGEOMETRIES(ST_DIFFERENCE (
ST_UNION ( ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 4 , 5 0 , 2 9 , 6 2 , 0 2 ) , ( 4 3 , 5 6 , 9 4 , 0 7 , 7 2 , 2 0 , 8 2 ) , ( 5 0 , 1 5 , 3 7 , 7 7 ) , ( 2 3 , 9 5 , 2 0 , 8 1 ) , ( 0 9 , 9 3 , 2 8 , 8 1 , 9 4 ) MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 4 , 5 0 , 2 9 , 6 2 , 0 2 ) , ( 4 3 , 5 6 , 9 4 , 0 7 , 7 2 , 2 0 , 8 2 ) , ( 5 0 , 1 5 , 3 7 , 7 7 ) , ( 2 3 , 9 5 , 2 0 , 8 1 ) , ( 0 9 , 9 3 , 2 8 , 8 1 , 9 4 )
123 123
SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER (
ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 7 3 , 1 8 , 4 0 , 7 9 ) , ( 5 4 , 9 8 , 7 4 , 3 7 ) , ( 5 8 , 5 4 , 9 2 , 5 6 ) , ( 4 0 , 3 2 , 0 1 , 3 9 ) , ( 2 0 , 3 5 , 9 5 , 0 9 ) ) ' ) ,
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 4 5 , 3 0 , 3 1 , 4 7 , 4 2 ) , ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' )
) , 1
)));
ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER (
ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 7 3 , 1 8 , 4 0 , 7 9 ) , ( 5 4 , 9 8 , 7 4 , 3 7 ) , ( 5 8 , 5 4 , 9 2 , 5 6 ) , ( 4 0 , 3 2 , 0 1 , 3 9 ) , ( 2 0 , 3 5 , 9 5 , 0 9 ) ) ' ) ,
MULTILINESTRI
653
SELECT ASTEXT(ST_DIFFERENCE ( SELECT ASTEXT(ST_DIFFERENCE (
POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) , POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) ,
ST_UNION ( ST_UNION (
...@@ -414,9 +445,24 @@ NULL ...@@ -414,9 +445,24 @@ NULL
SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ; SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ;
ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 ,
NULL NULL
SELECT ST_NUMGEOMETRIES( ST_SYMDIFFERENCE ( ST_SYMDIFFERENCE ( ST_INTERSECTION ( MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 6 4 , 3 7 , 9 4 , 3 8 ) , ( 2 2 , 2 9 , 1 2 , 9 8 ) ) ' ) , ST_SYMDIFFERENCE ( MULTIPOINTFROMTEXT( ' MULTIPOINT( 6 1 , 3 8 , 3 3 , 0 6 , 7 2 , 3 4 ) ' ) , ST_BUFFER ( ST_UNION ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 6 2 , 1 3 , 2 2 , 2 2 ) ) ) ' ) , GEOMETRYFROMTEXT( ' MULTILINESTRING( ( 1 4 , 9 9 , 3 0 , 6 6 ) , ( 3 5 , 1 0 , 5 8 , 6 1 ) , ( 8 9 , 6 1 , 5 1 , 6 2 ) , ( 2 2 , 7 5 , 5 8 , 6 9 , 3 0 ) , ( 8 0 , 8 4 , 6 7 , 5 5 ) ) ' ) ) , NUMPOINTS( EXTERIORRING( POLYGONFROMTEXT( ' POLYGON( ( 0 0 , 2 1 , 8 2 , 0 0 ) ) ' ) ) ) ) ) ) , ST_INTERSECTION ( POLYGONFROMTEXT( ' POLYGON( ( 2 3, 5 7 , 3 7 , 4 1 , 0 5, 2 3 ) ) ' ) , MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 3 , 1 4 , 6 4 , 9 1 , 3 4 , 1 8 ) , ( 9 9 , 0 3 , 1 7 , 9 9 ) ) ' ) ) ) , POLYGONFROMTEXT( ' POLYGON( ( 1 3, 7 2 , 1 5 , 3 8 , 5 0, 1 3) ) ' ) ) ) ;
ST_NUMGEOMETRIES( ST_SYMDIFFERENCE ( ST_SYMDIFFERENCE ( ST_INTERSECTION ( MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 6 4 , 3 7 , 9 4 , 3 8 ) , ( 2 2 , 2 9 , 1 2 , 9 8 ) ) ' ) , ST_SYMDIFFERENCE ( MULTIPOINTFROMTEXT( ' MULTIPOINT( 6 1 , 3 8 , 3 3 , 0 6
25
SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') )); SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') ));
ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)) ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5))
MULTIPOINT(7 5,7 5.14285714285714,5.9 5.3,5.8 5.6,3 7) MULTIPOINT(7 5,7 5.14285714285714,5.9 5.3,5.8 5.6,3 7)
SELECT ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) '));
ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) '))
0
SELECT ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') );
ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') )
0
SELECT ST_WITHIN( POINTFROMTEXT(' POINT(1 2 ) ') , MULTIPOLYGONFROMTEXT(' MULTIPOLYGON( ( (0 5, 3 5, 3 0, 0 0, 0 5), ( 1 1 , 2 1 , 2 4, 1 4, 1 1 ) ) ) '));
ST_WITHIN( POINTFROMTEXT(' POINT(1 2 ) ') , MULTIPOLYGONFROMTEXT(' MULTIPOLYGON( ( (0 5, 3 5, 3 0, 0 0, 0 5), ( 1 1 , 2 1 , 2 4, 1 4, 1 1 ) ) ) '))
1
select ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY')));
ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY')))
NULL
SELECT ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') );
ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') )
0
SELECT ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') );
ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') )
0
...@@ -237,14 +237,6 @@ SELECT ST_NUMGEOMETRIES(ST_DIFFERENCE ( ...@@ -237,14 +237,6 @@ SELECT ST_NUMGEOMETRIES(ST_DIFFERENCE (
)); ));
#bug 841638 Assertion `!m_prev || m_prev->x != x || m_prev->y != y' failed in Gcalc_shape_transporter::int_add_point in maria-5.3-gis
SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER (
ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 7 3 , 1 8 , 4 0 , 7 9 ) , ( 5 4 , 9 8 , 7 4 , 3 7 ) , ( 5 8 , 5 4 , 9 2 , 5 6 ) , ( 4 0 , 3 2 , 0 1 , 3 9 ) , ( 2 0 , 3 5 , 9 5 , 0 9 ) ) ' ) ,
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 4 5 , 3 0 , 3 1 , 4 7 , 4 2 ) , ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' )
) , 1
)));
#bug 841745 ssertion `!sp0->is_bottom()' failed in Gcalc_scan_iterator::find_intersections in maria-5.3-gis #bug 841745 ssertion `!sp0->is_bottom()' failed in Gcalc_scan_iterator::find_intersections in maria-5.3-gis
SELECT ASTEXT(ST_DIFFERENCE ( SELECT ASTEXT(ST_DIFFERENCE (
POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) , POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) ,
...@@ -279,10 +271,30 @@ SELECT ST_BUFFER ( ...@@ -279,10 +271,30 @@ SELECT ST_BUFFER (
) ; ) ;
SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ; SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ;
#bug 848901 Assertion `fabs(cur_isc->x-m_cur_intersection->x) + fabs(cur_isc->y-m_cur_intersection->y) < 0.000000000001' failed in Gcalc_scan_iterator::intersection_scan() in maria-5.3-gis
SELECT ST_NUMGEOMETRIES( ST_SYMDIFFERENCE ( ST_SYMDIFFERENCE ( ST_INTERSECTION ( MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 6 4 , 3 7 , 9 4 , 3 8 ) , ( 2 2 , 2 9 , 1 2 , 9 8 ) ) ' ) , ST_SYMDIFFERENCE ( MULTIPOINTFROMTEXT( ' MULTIPOINT( 6 1 , 3 8 , 3 3 , 0 6 , 7 2 , 3 4 ) ' ) , ST_BUFFER ( ST_UNION ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 6 2 , 1 3 , 2 2 , 2 2 ) ) ) ' ) , GEOMETRYFROMTEXT( ' MULTILINESTRING( ( 1 4 , 9 9 , 3 0 , 6 6 ) , ( 3 5 , 1 0 , 5 8 , 6 1 ) , ( 8 9 , 6 1 , 5 1 , 6 2 ) , ( 2 2 , 7 5 , 5 8 , 6 9 , 3 0 ) , ( 8 0 , 8 4 , 6 7 , 5 5 ) ) ' ) ) , NUMPOINTS( EXTERIORRING( POLYGONFROMTEXT( ' POLYGON( ( 0 0 , 2 1 , 8 2 , 0 0 ) ) ' ) ) ) ) ) ) , ST_INTERSECTION ( POLYGONFROMTEXT( ' POLYGON( ( 2 3, 5 7 , 3 7 , 4 1 , 0 5, 2 3 ) ) ' ) , MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 3 , 1 4 , 6 4 , 9 1 , 3 4 , 1 8 ) , ( 9 9 , 0 3 , 1 7 , 9 9 ) ) ' ) ) ) , POLYGONFROMTEXT( ' POLYGON( ( 1 3, 7 2 , 1 5 , 3 8 , 5 0, 1 3) ) ' ) ) ) ;
#bug 848939 Wrong result with ST_INTERSECTION between linestrings and a polygon in 5.3-gis #bug 848939 Wrong result with ST_INTERSECTION between linestrings and a polygon in 5.3-gis
SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') )); SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') ));
#bug 855485 ST_CROSSES returns different result than PostGIS for overlapping polygons
SELECT ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) '));
#bug 855487 ST_WITHIN returns wrong result for partially overlapping polygons
SELECT ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') );
#bug 855492 ST_WITHIN returns TRUE on point on the edge of a polygon
SELECT ST_WITHIN( POINTFROMTEXT(' POINT(1 2 ) ') , MULTIPOLYGONFROMTEXT(' MULTIPOLYGON( ( (0 5, 3 5, 3 0, 0 0, 0 5), ( 1 1 , 2 1 , 2 4, 1 4, 1 1 ) ) ) '));
#bug 855497 ST_ENVELOPE of GEOMETRYCOLLECTION EMPTY returns NULL and not GEOMETRYCOLLECTION EMPTY
select ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY')));
#bug 855503 ST_EQUALS reports TRUE between a POLYGON and a MULTILINESTRING
SELECT ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') );
#bug 855505 ST_TOUCHES reports TRUE for intersecting polygon and linestring
SELECT ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') );
...@@ -307,6 +307,7 @@ public: ...@@ -307,6 +307,7 @@ public:
virtual int complete_ring()=0; virtual int complete_ring()=0;
virtual int add_point(double x, double y)=0; virtual int add_point(double x, double y)=0;
virtual int start_collection(int n_objects) { return 0; } virtual int start_collection(int n_objects) { return 0; }
virtual int empty_shape() { return 0; }
int start_simple_poly() int start_simple_poly()
{ {
return start_poly() || start_ring(); return start_poly() || start_ring();
......
...@@ -43,7 +43,7 @@ gcalc_shape_info Gcalc_function::add_new_shape(uint32 shape_id, ...@@ -43,7 +43,7 @@ gcalc_shape_info Gcalc_function::add_new_shape(uint32 shape_id,
in prefix style. in prefix style.
*/ */
void Gcalc_function::add_operation(op_type operation, uint32 n_operands) void Gcalc_function::add_operation(uint operation, uint32 n_operands)
{ {
uint32 op_code= (uint32 ) operation + n_operands; uint32 op_code= (uint32 ) operation + n_operands;
function_buffer.q_append(op_code); function_buffer.q_append(op_code);
...@@ -84,6 +84,15 @@ int Gcalc_function::single_shape_op(shape_type shape_kind, gcalc_shape_info *si) ...@@ -84,6 +84,15 @@ int Gcalc_function::single_shape_op(shape_type shape_kind, gcalc_shape_info *si)
} }
int Gcalc_function::repeat_expression(uint32 exp_pos)
{
if (reserve_op_buffer(1))
return 1;
add_operation(op_repeat, exp_pos);
return 0;
}
/* /*
Specify how many arguments we're going to have. Specify how many arguments we're going to have.
*/ */
...@@ -109,42 +118,61 @@ int Gcalc_function::alloc_states() ...@@ -109,42 +118,61 @@ int Gcalc_function::alloc_states()
if (function_buffer.reserve((n_shapes+1) * 2 * sizeof(int))) if (function_buffer.reserve((n_shapes+1) * 2 * sizeof(int)))
return 1; return 1;
i_states= (int *) (function_buffer.ptr() + ALIGN_SIZE(function_buffer.length())); i_states= (int *) (function_buffer.ptr() + ALIGN_SIZE(function_buffer.length()));
saved_i_states= i_states + (n_shapes + 1); b_states= i_states + (n_shapes + 1);
return 0; return 0;
} }
void Gcalc_function::save_states() int Gcalc_function::count_internal(const char *cur_func, uint set_type,
{ const char **end)
memcpy(saved_i_states, i_states, (n_shapes+1) * sizeof(int));
}
void Gcalc_function::restore_states()
{
memcpy(i_states, saved_i_states, (n_shapes+1) * sizeof(int));
}
int Gcalc_function::count_internal()
{ {
int c_op= uint4korr(cur_func); uint c_op= uint4korr(cur_func);
op_type next_func= (op_type) (c_op & op_any); op_type next_func= (op_type) (c_op & op_any);
int mask= (c_op & op_not) ? 1:0; int mask= (c_op & op_not) ? 1:0;
int n_ops= c_op & ~op_any; uint n_ops= c_op & ~(op_any | op_not | v_mask);
uint n_shape= c_op & ~(op_any | op_not | v_mask); /* same as n_ops */
value v_state= (value) (c_op & v_mask);
int result; int result;
const char *sav_cur_func= cur_func;
cur_func+= 4; cur_func+= 4;
if (next_func == op_shape) if (next_func == op_shape)
return i_states[c_op & ~(op_any | op_not)] ^ mask; {
if (set_type == 0)
result= i_states[n_shape] | b_states[n_shape];
else if (set_type == op_border)
result= b_states[n_shape];
else if (set_type == op_internals)
result= i_states[n_shape] && !b_states[n_shape];
goto exit;
}
if (next_func == op_false)
{
result= 0;
goto exit;
}
if (next_func == op_border || next_func == op_internals)
{
result= count_internal(cur_func, next_func, &cur_func);
goto exit;
}
if (next_func == op_repeat)
{
result= count_internal(function_buffer.ptr() + n_ops, set_type, 0);
goto exit;
}
if (n_ops == 0) if (n_ops == 0)
return mask; return mask;
result= count_internal(); result= count_internal(cur_func, set_type, &cur_func);
while (--n_ops) while (--n_ops)
{ {
int next_res= count_internal(); int next_res= count_internal(cur_func, set_type, &cur_func);
switch (next_func) switch (next_func)
{ {
case op_union: case op_union:
...@@ -159,15 +187,59 @@ int Gcalc_function::count_internal() ...@@ -159,15 +187,59 @@ int Gcalc_function::count_internal()
case op_difference: case op_difference:
result= result & !next_res; result= result & !next_res;
break; break;
case op_backdifference:
result= !result & next_res;
break;
default: default:
DBUG_ASSERT(FALSE); DBUG_ASSERT(FALSE);
}; };
} }
return result ^ mask; exit:
result^= mask;
if (v_state != v_empty)
{
switch (v_state)
{
case v_find_t:
if (result)
{
c_op= (c_op & ~v_mask) | v_t_found;
int4store(sav_cur_func, c_op);
};
break;
case v_find_f:
if (!result)
{
c_op= (c_op & ~v_mask) | v_f_found;
int4store(sav_cur_func, c_op);
};
break;
case v_t_found:
result= 1;
break;
case v_f_found:
result= 0;
break;
default:
DBUG_ASSERT(0);
};
}
if (end)
*end= cur_func;
return result;
}
void Gcalc_function::clear_i_states()
{
for (uint i= 0; i < n_shapes; i++)
i_states[i]= 0;
}
void Gcalc_function::clear_b_states()
{
for (uint i= 0; i < n_shapes; i++)
b_states[i]= 0;
} }
...@@ -183,7 +255,7 @@ void Gcalc_function::reset() ...@@ -183,7 +255,7 @@ void Gcalc_function::reset()
} }
int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it) int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it)
{ {
const Gcalc_scan_iterator::point *eq_start, *cur_eq, *events; const Gcalc_scan_iterator::point *eq_start, *cur_eq, *events;
...@@ -194,31 +266,58 @@ int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it) ...@@ -194,31 +266,58 @@ int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it)
events= scan_it.get_events(); events= scan_it.get_events();
/* these kinds of events don't change the function */ /* these kinds of events don't change the function */
if (events->simple_event())
continue;
Gcalc_point_iterator pit(&scan_it); Gcalc_point_iterator pit(&scan_it);
clear_state(); clear_b_states();
clear_i_states();
/* Walk to the event, marking polygons we met */ /* Walk to the event, marking polygons we met */
for (; pit.point() != scan_it.get_event_position(); ++pit) for (; pit.point() != scan_it.get_event_position(); ++pit)
{ {
gcalc_shape_info si= pit.point()->get_shape(); gcalc_shape_info si= pit.point()->get_shape();
if ((get_shape_kind(si) == Gcalc_function::shape_polygon)) if ((get_shape_kind(si) == Gcalc_function::shape_polygon))
invert_state(si); invert_i_state(si);
}
if (events->simple_event())
{
if (events->event == scev_end)
set_b_state(events->get_shape());
if (count())
return 1;
clear_b_states();
continue;
} }
save_states();
/* Check the status of the event point */ /* Check the status of the event point */
for (; events; events= events->get_next()) for (; events; events= events->get_next())
set_on_state(events->get_shape()); {
gcalc_shape_info si= events->get_shape();
if (events->event == scev_thread ||
events->event == scev_end ||
(get_shape_kind(si) == Gcalc_function::shape_polygon))
set_b_state(si);
else if (get_shape_kind(si) == Gcalc_function::shape_line)
invert_i_state(si);
}
if (count()) if (count())
return 1; return 1;
/* Set back states changed in the loop above. */
for (events= scan_it.get_events(); events; events= events->get_next())
{
gcalc_shape_info si= events->get_shape();
if (events->event == scev_thread ||
events->event == scev_end ||
(get_shape_kind(si) == Gcalc_function::shape_polygon))
clear_b_state(si);
else if (get_shape_kind(si) == Gcalc_function::shape_line)
invert_i_state(si);
}
if (scan_it.get_event_position() == scan_it.get_event_end()) if (scan_it.get_event_position() == scan_it.get_event_end())
continue; continue;
/* Check the status after the event */ /* Check the status after the event */
restore_states();
eq_start= pit.point(); eq_start= pit.point();
do do
{ {
...@@ -226,18 +325,28 @@ int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it) ...@@ -226,18 +325,28 @@ int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it)
if (pit.point() != scan_it.get_event_end() && if (pit.point() != scan_it.get_event_end() &&
eq_start->cmp_dx_dy(pit.point()) == 0) eq_start->cmp_dx_dy(pit.point()) == 0)
continue; continue;
save_states();
for (cur_eq= eq_start; cur_eq != pit.point(); for (cur_eq= eq_start; cur_eq != pit.point();
cur_eq= cur_eq->get_next()) cur_eq= cur_eq->get_next())
set_on_state(cur_eq->get_shape()); {
gcalc_shape_info si= cur_eq->get_shape();
if (get_shape_kind(si) == Gcalc_function::shape_polygon)
set_b_state(si);
else
invert_i_state(si);
}
if (count()) if (count())
return 1; return 1;
restore_states();
for (cur_eq= eq_start; cur_eq != pit.point(); cur_eq= cur_eq->get_next()) for (cur_eq= eq_start; cur_eq != pit.point(); cur_eq= cur_eq->get_next())
{ {
gcalc_shape_info si= cur_eq->get_shape(); gcalc_shape_info si= cur_eq->get_shape();
if ((get_shape_kind(si) == Gcalc_function::shape_polygon)) if ((get_shape_kind(si) == Gcalc_function::shape_polygon))
invert_state(si); {
clear_b_state(si);
invert_i_state(si);
}
else
invert_i_state(cur_eq->get_shape());
} }
if (count()) if (count())
return 1; return 1;
...@@ -313,6 +422,15 @@ int Gcalc_operation_transporter::start_collection(int n_objects) ...@@ -313,6 +422,15 @@ int Gcalc_operation_transporter::start_collection(int n_objects)
} }
int Gcalc_operation_transporter::empty_shape()
{
if (m_fn->reserve_op_buffer(1))
return 1;
m_fn->add_operation(Gcalc_function::op_false, 0);
return 0;
}
int Gcalc_result_receiver::start_shape(Gcalc_function::shape_type shape) int Gcalc_result_receiver::start_shape(Gcalc_function::shape_type shape)
{ {
if (buffer.reserve(4*2, 512)) if (buffer.reserve(4*2, 512))
...@@ -661,7 +779,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -661,7 +779,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
if (ca_counter == 11522) if (ca_counter == 11522)
call_checkpoint(89); call_checkpoint(89);
#endif /*NO_TESTING*/ #endif /*NO_TESTING*/
m_fn->clear_state(); m_fn->clear_i_states();
/* Walk to the event, remembering what is needed. */ /* Walk to the event, remembering what is needed. */
#ifndef NO_TESTING #ifndef NO_TESTING
if (si->get_event_position() == pi.point()) if (si->get_event_position() == pi.point())
...@@ -678,7 +796,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -678,7 +796,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
prev_range= prev_state ? cur_t : 0; prev_range= prev_state ? cur_t : 0;
} }
if (m_fn->get_shape_kind(pi.get_shape()) == Gcalc_function::shape_polygon) if (m_fn->get_shape_kind(pi.get_shape()) == Gcalc_function::shape_polygon)
m_fn->invert_state(pi.get_shape()); m_fn->invert_i_state(pi.get_shape());
} }
events= si->get_events(); events= si->get_events();
...@@ -800,6 +918,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -800,6 +918,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
eq_start= pi.point(); eq_start= pi.point();
eq_thread= point_thread= *starting_t_hook; eq_thread= point_thread= *starting_t_hook;
m_fn->clear_b_states();
while (eq_start != si->get_event_end()) while (eq_start != si->get_event_end())
{ {
const Gcalc_scan_iterator::point *cur_eq; const Gcalc_scan_iterator::point *cur_eq;
...@@ -812,17 +931,16 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -812,17 +931,16 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
eq_start->cmp_dx_dy(pi.point()) == 0) eq_start->cmp_dx_dy(pi.point()) == 0)
continue; continue;
m_fn->save_states();
for (cur_eq= eq_start; cur_eq != pi.point(); cur_eq= cur_eq->get_next()) for (cur_eq= eq_start; cur_eq != pi.point(); cur_eq= cur_eq->get_next())
m_fn->set_on_state(cur_eq->get_shape()); m_fn->set_b_state(cur_eq->get_shape());
in_state= m_fn->count(); in_state= m_fn->count();
m_fn->restore_states(); m_fn->clear_b_states();
for (cur_eq= eq_start; cur_eq != pi.point(); cur_eq= cur_eq->get_next()) for (cur_eq= eq_start; cur_eq != pi.point(); cur_eq= cur_eq->get_next())
{ {
gcalc_shape_info si= cur_eq->get_shape(); gcalc_shape_info si= cur_eq->get_shape();
if ((m_fn->get_shape_kind(si) == Gcalc_function::shape_polygon)) if ((m_fn->get_shape_kind(si) == Gcalc_function::shape_polygon))
m_fn->invert_state(si); m_fn->invert_i_state(si);
} }
after_state= m_fn->count(); after_state= m_fn->count();
if (prev_state != after_state) if (prev_state != after_state)
...@@ -844,14 +962,15 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -844,14 +962,15 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
if (!sav_prev_state && !m_poly_borders && !m_lines) if (!sav_prev_state && !m_poly_borders && !m_lines)
{ {
/* Check if we need to add the event point itself */ /* Check if we need to add the event point itself */
m_fn->clear_state(); m_fn->clear_i_states();
/* b_states supposed to be clean already */
for (pi.restart(si); pi.point() != si->get_event_position(); ++pi) for (pi.restart(si); pi.point() != si->get_event_position(); ++pi)
{ {
if (m_fn->get_shape_kind(pi.get_shape()) == Gcalc_function::shape_polygon) if (m_fn->get_shape_kind(pi.get_shape()) == Gcalc_function::shape_polygon)
m_fn->invert_state(pi.get_shape()); m_fn->invert_i_state(pi.get_shape());
} }
for (events= si->get_events(); events; events= events->get_next()) for (events= si->get_events(); events; events= events->get_next())
m_fn->set_on_state(events->get_shape()); m_fn->set_b_state(events->get_shape());
return m_fn->count() ? add_single_point(si) : 0; return m_fn->count() ? add_single_point(si) : 0;
} }
......
...@@ -43,23 +43,35 @@ class Gcalc_function ...@@ -43,23 +43,35 @@ class Gcalc_function
private: private:
String shapes_buffer; String shapes_buffer;
String function_buffer; String function_buffer;
const char *cur_func;
int *i_states; int *i_states;
int *saved_i_states; int *b_states;
uint32 cur_object_id; uint32 cur_object_id;
uint n_shapes; uint n_shapes;
int count_internal(); int count_internal(const char *cur_func, uint set_type,
const char **end);
public: public:
enum value
{
v_empty= 0x0000000,
v_find_t= 0x1000000,
v_find_f= 0x2000000,
v_t_found= 0x3000000,
v_f_found= 0x4000000,
v_mask= 0x7000000
};
enum op_type enum op_type
{ {
op_shape= 0,
op_not= 0x80000000, op_not= 0x80000000,
op_shape= 0x00000000,
op_union= 0x10000000, op_union= 0x10000000,
op_intersection= 0x20000000, op_intersection= 0x20000000,
op_symdifference= 0x30000000, op_symdifference= 0x30000000,
op_difference= 0x40000000, op_difference= 0x40000000,
op_backdifference= 0x50000000, op_repeat= 0x50000000,
op_any= 0x70000000 op_border= 0x60000000,
op_internals= 0x70000000,
op_false= 0x08000000,
op_any= 0x78000000 /* The mask to get any of the operations */
}; };
enum shape_type enum shape_type
{ {
...@@ -75,10 +87,11 @@ public: ...@@ -75,10 +87,11 @@ public:
Also adds the shape to the list of operands. Also adds the shape to the list of operands.
*/ */
int single_shape_op(shape_type shape_kind, gcalc_shape_info *si); int single_shape_op(shape_type shape_kind, gcalc_shape_info *si);
void add_operation(op_type operation, uint32 n_operands); void add_operation(uint operation, uint32 n_operands);
void add_not_operation(op_type operation, uint32 n_operands); void add_not_operation(op_type operation, uint32 n_operands);
uint32 get_next_operation_pos() { return function_buffer.length(); } uint32 get_next_expression_pos() { return function_buffer.length(); }
void add_operands_to_op(uint32 operation_pos, uint32 n_operands); void add_operands_to_op(uint32 operation_pos, uint32 n_operands);
int repeat_expression(uint32 exp_pos);
void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; } void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; }
int reserve_shape_buffer(uint n_shapes); int reserve_shape_buffer(uint n_shapes);
int reserve_op_buffer(uint n_ops); int reserve_op_buffer(uint n_ops);
...@@ -90,20 +103,20 @@ public: ...@@ -90,20 +103,20 @@ public:
void set_states(int *shape_states) { i_states= shape_states; } void set_states(int *shape_states) { i_states= shape_states; }
int alloc_states(); int alloc_states();
void invert_state(gcalc_shape_info shape) { i_states[shape]^= 1; } void invert_i_state(gcalc_shape_info shape) { i_states[shape]^= 1; }
void set_on_state(gcalc_shape_info shape) { i_states[shape]= 1; } void set_b_state(gcalc_shape_info shape) { b_states[shape]= 1; }
int get_state(gcalc_shape_info shape) { return i_states[shape]; } void clear_b_state(gcalc_shape_info shape) { b_states[shape]= 0; }
void save_states(); int get_state(gcalc_shape_info shape)
void restore_states(); { return i_states[shape] | b_states[shape]; }
int get_i_state(gcalc_shape_info shape) { return i_states[shape]; }
int get_b_state(gcalc_shape_info shape) { return b_states[shape]; }
int count() int count()
{ { return count_internal(function_buffer.ptr(), 0, 0); }
cur_func= function_buffer.ptr(); void clear_i_states();
return count_internal(); void clear_b_states();
}
void clear_state() { bzero(i_states, n_shapes * sizeof(int)); }
void reset(); void reset();
int find_function(Gcalc_scan_iterator &scan_it); int check_function(Gcalc_scan_iterator &scan_it);
}; };
...@@ -132,6 +145,7 @@ public: ...@@ -132,6 +145,7 @@ public:
int complete_ring(); int complete_ring();
int add_point(double x, double y); int add_point(double x, double y);
int start_collection(int n_objects); int start_collection(int n_objects);
int empty_shape();
}; };
......
...@@ -5144,7 +5144,7 @@ static Native_func_registry func_array[] = ...@@ -5144,7 +5144,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("ENCRYPT") }, BUILDER(Create_func_encrypt)}, { { C_STRING_WITH_LEN("ENCRYPT") }, BUILDER(Create_func_encrypt)},
{ { C_STRING_WITH_LEN("ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)}, { { C_STRING_WITH_LEN("ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
{ { C_STRING_WITH_LEN("ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)}, { { C_STRING_WITH_LEN("ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)},
{ { C_STRING_WITH_LEN("EQUALS") }, GEOM_BUILDER(Create_func_mbr_equals)}, { { C_STRING_WITH_LEN("EQUALS") }, GEOM_BUILDER(Create_func_equals)},
{ { C_STRING_WITH_LEN("EXP") }, BUILDER(Create_func_exp)}, { { C_STRING_WITH_LEN("EXP") }, BUILDER(Create_func_exp)},
{ { C_STRING_WITH_LEN("EXPORT_SET") }, BUILDER(Create_func_export_set)}, { { C_STRING_WITH_LEN("EXPORT_SET") }, BUILDER(Create_func_export_set)},
{ { C_STRING_WITH_LEN("EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)}, { { C_STRING_WITH_LEN("EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
...@@ -5283,7 +5283,7 @@ static Native_func_registry func_array[] = ...@@ -5283,7 +5283,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("ST_DISTANCE") }, GEOM_BUILDER(Create_func_distance)}, { { C_STRING_WITH_LEN("ST_DISTANCE") }, GEOM_BUILDER(Create_func_distance)},
{ { C_STRING_WITH_LEN("ST_ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)}, { { C_STRING_WITH_LEN("ST_ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
{ { C_STRING_WITH_LEN("ST_ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)}, { { C_STRING_WITH_LEN("ST_ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)},
{ { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_mbr_equals)}, { { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_equals)},
{ { C_STRING_WITH_LEN("ST_EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)}, { { C_STRING_WITH_LEN("ST_EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
{ { C_STRING_WITH_LEN("ST_GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)}, { { C_STRING_WITH_LEN("ST_GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
{ { C_STRING_WITH_LEN("ST_GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)}, { { C_STRING_WITH_LEN("ST_GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
...@@ -5323,7 +5323,7 @@ static Native_func_registry func_array[] = ...@@ -5323,7 +5323,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("ST_SYMDIFFERENCE") }, GEOM_BUILDER(Create_func_symdifference)}, { { C_STRING_WITH_LEN("ST_SYMDIFFERENCE") }, GEOM_BUILDER(Create_func_symdifference)},
{ { C_STRING_WITH_LEN("ST_TOUCHES") }, GEOM_BUILDER(Create_func_touches)}, { { C_STRING_WITH_LEN("ST_TOUCHES") }, GEOM_BUILDER(Create_func_touches)},
{ { C_STRING_WITH_LEN("ST_UNION") }, GEOM_BUILDER(Create_func_union)}, { { C_STRING_WITH_LEN("ST_UNION") }, GEOM_BUILDER(Create_func_union)},
{ { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_mbr_within)}, { { 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_X") }, GEOM_BUILDER(Create_func_x)},
{ { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)}, { { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)},
{ { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)}, { { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)},
......
...@@ -660,6 +660,7 @@ static double distance_points(const Gcalc_heap::Info *a, ...@@ -660,6 +660,7 @@ static double distance_points(const Gcalc_heap::Info *a,
Calculates the distance between objects. Calculates the distance between objects.
*/ */
#ifdef TMP_BLOCK
static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si, static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si,
Gcalc_function *func, Gcalc_scan_iterator *scan_it) Gcalc_function *func, Gcalc_scan_iterator *scan_it)
{ {
...@@ -786,139 +787,11 @@ exit: ...@@ -786,139 +787,11 @@ exit:
mem_error: mem_error:
DBUG_RETURN(1); DBUG_RETURN(1);
} }
#endif /*TMP_BLOCK*/
#define GIS_ZERO 0.00000000001 #define GIS_ZERO 0.00000000001
int Item_func_spatial_rel::func_touches()
{
bool above_cur_point;
double x1, x2, y1, y2, ex, ey;
double distance, area;
int result= 0;
int cur_func= 0;
Gcalc_operation_transporter trn(&func, &collector);
String *res1= args[0]->val_str(&tmp_value1);
String *res2= args[1]->val_str(&tmp_value2);
Geometry_buffer buffer1, buffer2;
Geometry *g1, *g2;
int obj2_si;
DBUG_ENTER("Item_func_spatial_rel::func_touches");
DBUG_ASSERT(fixed == 1);
if ((null_value= (args[0]->null_value || args[1]->null_value ||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())))))
goto mem_error;
if ((g1->get_class_info()->m_type_id == Geometry::wkb_point) &&
(g2->get_class_info()->m_type_id == Geometry::wkb_point))
{
if (((Gis_point *) g1)->get_xy(&x1, &y1) ||
((Gis_point *) g2)->get_xy(&x2, &y2))
goto mem_error;
ex= x2 - x1;
ey= y2 - y1;
DBUG_RETURN((ex * ex + ey * ey) < GIS_ZERO);
}
if (func.reserve_op_buffer(1))
goto mem_error;
func.add_operation(Gcalc_function::op_intersection, 2);
if (g1->store_shapes(&trn))
goto mem_error;
obj2_si= func.get_nshapes();
if (g2->store_shapes(&trn) || func.alloc_states())
goto mem_error;
collector.prepare_operation();
scan_it.init(&collector);
if (calc_distance(&distance, &collector, obj2_si, &func, &scan_it))
goto mem_error;
if (distance > GIS_ZERO)
goto exit;
scan_it.reset();
scan_it.init(&collector);
above_cur_point= false;
distance= DBL_MAX;
while (scan_it.more_trapezoids())
{
if (scan_it.step())
goto mem_error;
func.clear_state();
for (Gcalc_trapezoid_iterator ti(&scan_it); ti.more(); ++ti)
{
gcalc_shape_info si= ti.lb()->get_shape();
if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon))
{
func.invert_state(si);
cur_func= func.count();
}
if (cur_func)
{
area= scan_it.get_h() *
((scan_it.get_sp_x(ti.rb()) - scan_it.get_sp_x(ti.lb())) +
(scan_it.get_sp_x(ti.rt()) - scan_it.get_sp_x(ti.lt())));
if (area > GIS_ZERO)
{
result= 0;
goto exit;
}
}
}
}
result= 1;
exit:
collector.reset();
func.reset();
scan_it.reset();
DBUG_RETURN(result);
mem_error:
null_value= 1;
DBUG_RETURN(0);
}
int Item_func_spatial_rel::func_equals()
{
Gcalc_heap::Info *pi_s1, *pi_s2;
Gcalc_heap::Info *cur_pi= collector.get_first();
double d;
if (!cur_pi)
return 1;
do {
pi_s1= cur_pi;
pi_s2= 0;
while ((cur_pi= cur_pi->get_next()))
{
d= fabs(pi_s1->x - cur_pi->x) + fabs(pi_s1->y - cur_pi->y);
if (d > GIS_ZERO)
break;
if (!pi_s2 && pi_s1->shape != cur_pi->shape)
pi_s2= cur_pi;
}
if (!pi_s2)
return 0;
} while (cur_pi);
return 1;
}
longlong Item_func_spatial_rel::val_int() longlong Item_func_spatial_rel::val_int()
{ {
DBUG_ENTER("Item_func_spatial_rel::val_int"); DBUG_ENTER("Item_func_spatial_rel::val_int");
...@@ -929,9 +802,7 @@ longlong Item_func_spatial_rel::val_int() ...@@ -929,9 +802,7 @@ longlong Item_func_spatial_rel::val_int()
Geometry *g1, *g2; Geometry *g1, *g2;
int result= 0; int result= 0;
int mask= 0; int mask= 0;
uint shape_a, shape_b;
if (spatial_rel == SP_TOUCHES_FUNC)
DBUG_RETURN(func_touches());
res1= args[0]->val_str(&tmp_value1); res1= args[0]->val_str(&tmp_value1);
res2= args[1]->val_str(&tmp_value2); res2= args[1]->val_str(&tmp_value2);
...@@ -940,56 +811,103 @@ longlong Item_func_spatial_rel::val_int() ...@@ -940,56 +811,103 @@ longlong Item_func_spatial_rel::val_int()
if (func.reserve_op_buffer(1)) if (func.reserve_op_buffer(1))
DBUG_RETURN(0); DBUG_RETURN(0);
if ((null_value=
(args[0]->null_value || args[1]->null_value ||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())))))
goto exit;
switch (spatial_rel) { switch (spatial_rel) {
case SP_CONTAINS_FUNC: case SP_CONTAINS_FUNC:
mask= 1; mask= 1;
func.add_operation(Gcalc_function::op_backdifference, 2); func.add_operation(Gcalc_function::op_difference, 2);
/* Mind the g2 goes first. */
null_value= g2->store_shapes(&trn) || g1->store_shapes(&trn);
break; break;
case SP_WITHIN_FUNC: case SP_WITHIN_FUNC:
mask= 1; mask= 1;
func.add_operation(Gcalc_function::op_difference, 2); func.add_operation(Gcalc_function::op_difference, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break; break;
case SP_EQUALS_FUNC: case SP_EQUALS_FUNC:
mask= 1;
func.add_operation(Gcalc_function::op_symdifference, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break; break;
case SP_DISJOINT_FUNC: case SP_DISJOINT_FUNC:
mask= 1; mask= 1;
func.add_operation(Gcalc_function::op_intersection, 2); func.add_operation(Gcalc_function::op_intersection, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break; break;
case SP_INTERSECTS_FUNC: case SP_INTERSECTS_FUNC:
func.add_operation(Gcalc_function::op_intersection, 2); func.add_operation(Gcalc_function::op_intersection, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break; break;
case SP_OVERLAPS_FUNC: case SP_OVERLAPS_FUNC:
func.add_operation(Gcalc_function::op_backdifference, 2);
break;
case SP_CROSSES_FUNC: case SP_CROSSES_FUNC:
func.add_operation(Gcalc_function::op_intersection, 2); func.add_operation(Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_intersection, 2);
shape_a= func.get_next_expression_pos();
if ((null_value= g1->store_shapes(&trn)))
break;
shape_b= func.get_next_expression_pos();
if ((null_value= g2->store_shapes(&trn)))
break;
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_difference, 2);
func.repeat_expression(shape_a);
func.repeat_expression(shape_b);
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_difference, 2);
func.repeat_expression(shape_b);
func.repeat_expression(shape_a);
break;
case SP_TOUCHES_FUNC:
func.add_operation(Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::v_find_f |
Gcalc_function::op_not |
Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::op_internals, 1);
shape_a= func.get_next_expression_pos();
if ((null_value= g1->store_shapes(&trn)))
break;
func.add_operation(Gcalc_function::op_internals, 1);
shape_b= func.get_next_expression_pos();
if ((null_value= g2->store_shapes(&trn)))
break;
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::op_border, 1);
func.repeat_expression(shape_a);
func.add_operation(Gcalc_function::op_border, 1);
func.repeat_expression(shape_b);
break; break;
default: default:
DBUG_ASSERT(FALSE); DBUG_ASSERT(FALSE);
break; break;
} }
if (null_value)
if ((null_value=
(args[0]->null_value || args[1]->null_value ||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
g1->store_shapes(&trn) || g2->store_shapes(&trn))))
goto exit; goto exit;
collector.prepare_operation(); collector.prepare_operation();
scan_it.init(&collector); scan_it.init(&collector);
#ifdef TMP_BLOCK
if (spatial_rel == SP_EQUALS_FUNC) if (spatial_rel == SP_EQUALS_FUNC)
{ {
result= (g1->get_class_info()->m_type_id == g1->get_class_info()->m_type_id) && result= (g1->get_class_info()->m_type_id == g1->get_class_info()->m_type_id) &&
func_equals(); func_equals();
goto exit; goto exit;
} }
#endif /*TMP_BLOCK*/
if (func.alloc_states()) if (func.alloc_states())
goto exit; goto exit;
result= func.find_function(scan_it) ^ mask; result= func.check_function(scan_it) ^ mask;
exit: exit:
collector.reset(); collector.reset();
...@@ -1307,7 +1225,7 @@ int Item_func_buffer::Transporter::start_line() ...@@ -1307,7 +1225,7 @@ int Item_func_buffer::Transporter::start_line()
if (m_fn->reserve_op_buffer(2)) if (m_fn->reserve_op_buffer(2))
return 1; return 1;
last_shape_pos= m_fn->get_next_operation_pos(); last_shape_pos= m_fn->get_next_expression_pos();
m_fn->add_operation(buffer_op, 0); m_fn->add_operation(buffer_op, 0);
m_npoints= 0; m_npoints= 0;
int_start_line(); int_start_line();
...@@ -1321,7 +1239,7 @@ int Item_func_buffer::Transporter::start_poly() ...@@ -1321,7 +1239,7 @@ int Item_func_buffer::Transporter::start_poly()
if (m_fn->reserve_op_buffer(2)) if (m_fn->reserve_op_buffer(2))
return 1; return 1;
last_shape_pos= m_fn->get_next_operation_pos(); last_shape_pos= m_fn->get_next_expression_pos();
m_fn->add_operation(buffer_op, 0); m_fn->add_operation(buffer_op, 0);
return Gcalc_operation_transporter::start_poly(); return Gcalc_operation_transporter::start_poly();
} }
...@@ -1827,19 +1745,20 @@ double Item_func_distance::val_real() ...@@ -1827,19 +1745,20 @@ double Item_func_distance::val_real()
of objects of objects
scev_thread | scev_two_threads | scev_single_point scev_thread | scev_two_threads | scev_single_point
*/ */
func.clear_state(); func.clear_i_states();
for (Gcalc_point_iterator pit(&scan_it); pit.point() != evpos; ++pit) for (Gcalc_point_iterator pit(&scan_it); pit.point() != evpos; ++pit)
{ {
gcalc_shape_info si= pit.point()->get_shape(); gcalc_shape_info si= pit.point()->get_shape();
if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon)) if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon))
func.invert_state(si); func.invert_i_state(si);
} }
func.clear_b_states();
for (; ev; ev= ev->get_next()) for (; ev; ev= ev->get_next())
{ {
if (ev->event != scev_intersection) if (ev->event != scev_intersection)
cur_point= ev->pi; cur_point= ev->pi;
func.set_on_state(ev->get_shape()); func.set_b_state(ev->get_shape());
if (func.count()) if (func.count())
{ {
/* Point of one object is inside the other - intersection found */ /* Point of one object is inside the other - intersection found */
......
...@@ -251,9 +251,6 @@ public: ...@@ -251,9 +251,6 @@ public:
void fix_length_and_dec() { maybe_null= 1; } void fix_length_and_dec() { maybe_null= 1; }
bool is_null() { (void) val_int(); return null_value; } bool is_null() { (void) val_int(); return null_value; }
protected:
int func_touches();
int func_equals();
}; };
......
...@@ -2519,6 +2519,12 @@ int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn) const ...@@ -2519,6 +2519,12 @@ int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn) const
n_objects= uint4korr(data); n_objects= uint4korr(data);
data+= 4; data+= 4;
if (!n_objects)
{
trn->empty_shape();
return 0;
}
if (trn->start_collection(n_objects)) if (trn->start_collection(n_objects))
return 1; return 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment