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
0 0
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 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))'));
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
......@@ -25,48 +25,90 @@ insert into t1 values
(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))'));
astext(g)
POINT(2 2)
POINT(2 4)
POINT(2 6)
POINT(2 8)
POINT(4 2)
POINT(4 4)
POINT(4 6)
POINT(4 8)
POINT(6 2)
POINT(6 4)
POINT(6 6)
POINT(6 8)
POINT(8 2)
POINT(8 4)
POINT(8 6)
POINT(8 8)
select '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);
astext(g)
POINT(2 2)
POINT(2 4)
POINT(2 6)
POINT(2 8)
POINT(4 2)
POINT(4 4)
POINT(4 6)
POINT(4 8)
POINT(6 2)
POINT(6 4)
POINT(6 6)
POINT(6 8)
POINT(8 2)
POINT(8 4)
POINT(8 6)
POINT(8 8)
select '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);
astext(g)
POINT(4 4)
POINT(6 2)
POINT(6 4)
POINT(6 6)
select '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);
astext(g)
POINT(2 2)
POINT(2 4)
POINT(2 6)
POINT(2 8)
POINT(4 2)
POINT(4 4)
POINT(4 6)
POINT(4 8)
POINT(6 2)
POINT(6 4)
POINT(6 6)
POINT(6 8)
POINT(8 2)
POINT(8 4)
POINT(8 6)
POINT(8 8)
select '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);
astext(g)
POINT(2 2)
POINT(2 4)
POINT(2 6)
POINT(2 8)
POINT(4 2)
POINT(4 4)
POINT(4 6)
POINT(4 8)
POINT(6 2)
POINT(6 4)
POINT(6 6)
POINT(6 8)
POINT(8 2)
POINT(8 4)
POINT(8 6)
POINT(8 8)
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))'));
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
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)'));
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))'));
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
......@@ -177,10 +219,10 @@ st_touches(geomfromtext('point(0 0)'), geomfromtext('point(1 1)'))
0
select 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)'));
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)'));
st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)'))
0
......@@ -189,7 +231,7 @@ 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('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))'));
st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))'))
1
......@@ -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))
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)')))
GEOMETRYCOLLECTION()
GEOMETRYCOLLECTION EMPTY
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))')))
GEOMETRYCOLLECTION(POINT(8 1),LINESTRING(2 4,2 5,3 5,3 4,2 4))
......@@ -355,17 +397,6 @@ ST_NUMGEOMETRIES(ST_DIFFERENCE (
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 )
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 (
POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) ,
ST_UNION (
......@@ -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 ) ) ) ' ) ) ;
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
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 ) )') ));
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)
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 (
));
#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
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 ) ) ' ) ,
......@@ -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 ) ) ) ' ) ) ;
#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
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:
virtual int complete_ring()=0;
virtual int add_point(double x, double y)=0;
virtual int start_collection(int n_objects) { return 0; }
virtual int empty_shape() { return 0; }
int start_simple_poly()
{
return start_poly() || start_ring();
......
......@@ -43,7 +43,7 @@ gcalc_shape_info Gcalc_function::add_new_shape(uint32 shape_id,
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;
function_buffer.q_append(op_code);
......@@ -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.
*/
......@@ -109,42 +118,61 @@ int Gcalc_function::alloc_states()
if (function_buffer.reserve((n_shapes+1) * 2 * sizeof(int)))
return 1;
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;
}
void Gcalc_function::save_states()
{
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 Gcalc_function::count_internal(const char *cur_func, uint set_type,
const char **end)
{
int c_op= uint4korr(cur_func);
uint c_op= uint4korr(cur_func);
op_type next_func= (op_type) (c_op & op_any);
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;
const char *sav_cur_func= cur_func;
cur_func+= 4;
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)
return mask;
result= count_internal();
result= count_internal(cur_func, set_type, &cur_func);
while (--n_ops)
{
int next_res= count_internal();
int next_res= count_internal(cur_func, set_type, &cur_func);
switch (next_func)
{
case op_union:
......@@ -159,15 +187,59 @@ int Gcalc_function::count_internal()
case op_difference:
result= result & !next_res;
break;
case op_backdifference:
result= !result & next_res;
break;
default:
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()
}
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;
......@@ -194,31 +266,58 @@ int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it)
events= scan_it.get_events();
/* these kinds of events don't change the function */
if (events->simple_event())
continue;
Gcalc_point_iterator pit(&scan_it);
clear_state();
clear_b_states();
clear_i_states();
/* Walk to the event, marking polygons we met */
for (; pit.point() != scan_it.get_event_position(); ++pit)
{
gcalc_shape_info si= pit.point()->get_shape();
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 */
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())
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())
continue;
/* Check the status after the event */
restore_states();
eq_start= pit.point();
do
{
......@@ -226,18 +325,28 @@ int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it)
if (pit.point() != scan_it.get_event_end() &&
eq_start->cmp_dx_dy(pit.point()) == 0)
continue;
save_states();
for (cur_eq= eq_start; cur_eq != pit.point();
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())
return 1;
restore_states();
for (cur_eq= eq_start; cur_eq != pit.point(); cur_eq= cur_eq->get_next())
{
gcalc_shape_info si= cur_eq->get_shape();
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())
return 1;
......@@ -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)
{
if (buffer.reserve(4*2, 512))
......@@ -661,7 +779,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
if (ca_counter == 11522)
call_checkpoint(89);
#endif /*NO_TESTING*/
m_fn->clear_state();
m_fn->clear_i_states();
/* Walk to the event, remembering what is needed. */
#ifndef NO_TESTING
if (si->get_event_position() == pi.point())
......@@ -678,7 +796,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
prev_range= prev_state ? cur_t : 0;
}
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();
......@@ -800,6 +918,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
eq_start= pi.point();
eq_thread= point_thread= *starting_t_hook;
m_fn->clear_b_states();
while (eq_start != si->get_event_end())
{
const Gcalc_scan_iterator::point *cur_eq;
......@@ -812,17 +931,16 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
eq_start->cmp_dx_dy(pi.point()) == 0)
continue;
m_fn->save_states();
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();
m_fn->restore_states();
m_fn->clear_b_states();
for (cur_eq= eq_start; cur_eq != pi.point(); cur_eq= cur_eq->get_next())
{
gcalc_shape_info si= cur_eq->get_shape();
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();
if (prev_state != after_state)
......@@ -844,14 +962,15 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
if (!sav_prev_state && !m_poly_borders && !m_lines)
{
/* 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)
{
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())
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;
}
......
......@@ -43,23 +43,35 @@ class Gcalc_function
private:
String shapes_buffer;
String function_buffer;
const char *cur_func;
int *i_states;
int *saved_i_states;
int *b_states;
uint32 cur_object_id;
uint n_shapes;
int count_internal();
int count_internal(const char *cur_func, uint set_type,
const char **end);
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
{
op_shape= 0,
op_not= 0x80000000,
op_shape= 0x00000000,
op_union= 0x10000000,
op_intersection= 0x20000000,
op_symdifference= 0x30000000,
op_difference= 0x40000000,
op_backdifference= 0x50000000,
op_any= 0x70000000
op_repeat= 0x50000000,
op_border= 0x60000000,
op_internals= 0x70000000,
op_false= 0x08000000,
op_any= 0x78000000 /* The mask to get any of the operations */
};
enum shape_type
{
......@@ -75,10 +87,11 @@ public:
Also adds the shape to the list of operands.
*/
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);
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);
int repeat_expression(uint32 exp_pos);
void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; }
int reserve_shape_buffer(uint n_shapes);
int reserve_op_buffer(uint n_ops);
......@@ -90,20 +103,20 @@ public:
void set_states(int *shape_states) { i_states= shape_states; }
int alloc_states();
void invert_state(gcalc_shape_info shape) { i_states[shape]^= 1; }
void set_on_state(gcalc_shape_info shape) { i_states[shape]= 1; }
int get_state(gcalc_shape_info shape) { return i_states[shape]; }
void save_states();
void restore_states();
void invert_i_state(gcalc_shape_info shape) { i_states[shape]^= 1; }
void set_b_state(gcalc_shape_info shape) { b_states[shape]= 1; }
void clear_b_state(gcalc_shape_info shape) { b_states[shape]= 0; }
int get_state(gcalc_shape_info shape)
{ 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()
{
cur_func= function_buffer.ptr();
return count_internal();
}
void clear_state() { bzero(i_states, n_shapes * sizeof(int)); }
{ return count_internal(function_buffer.ptr(), 0, 0); }
void clear_i_states();
void clear_b_states();
void reset();
int find_function(Gcalc_scan_iterator &scan_it);
int check_function(Gcalc_scan_iterator &scan_it);
};
......@@ -132,6 +145,7 @@ public:
int complete_ring();
int add_point(double x, double y);
int start_collection(int n_objects);
int empty_shape();
};
......
......@@ -5144,7 +5144,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("ENCRYPT") }, BUILDER(Create_func_encrypt)},
{ { C_STRING_WITH_LEN("ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
{ { 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("EXPORT_SET") }, BUILDER(Create_func_export_set)},
{ { C_STRING_WITH_LEN("EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
......@@ -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_ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
{ { 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_GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
{ { C_STRING_WITH_LEN("ST_GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
......@@ -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_TOUCHES") }, GEOM_BUILDER(Create_func_touches)},
{ { 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_Y") }, GEOM_BUILDER(Create_func_y)},
{ { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)},
......
......@@ -660,6 +660,7 @@ static double distance_points(const Gcalc_heap::Info *a,
Calculates the distance between objects.
*/
#ifdef TMP_BLOCK
static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si,
Gcalc_function *func, Gcalc_scan_iterator *scan_it)
{
......@@ -786,139 +787,11 @@ exit:
mem_error:
DBUG_RETURN(1);
}
#endif /*TMP_BLOCK*/
#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()
{
DBUG_ENTER("Item_func_spatial_rel::val_int");
......@@ -929,9 +802,7 @@ longlong Item_func_spatial_rel::val_int()
Geometry *g1, *g2;
int result= 0;
int mask= 0;
if (spatial_rel == SP_TOUCHES_FUNC)
DBUG_RETURN(func_touches());
uint shape_a, shape_b;
res1= args[0]->val_str(&tmp_value1);
res2= args[1]->val_str(&tmp_value2);
......@@ -940,56 +811,103 @@ longlong Item_func_spatial_rel::val_int()
if (func.reserve_op_buffer(1))
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) {
case SP_CONTAINS_FUNC:
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;
case SP_WITHIN_FUNC:
mask= 1;
func.add_operation(Gcalc_function::op_difference, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break;
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;
case SP_DISJOINT_FUNC:
mask= 1;
func.add_operation(Gcalc_function::op_intersection, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break;
case SP_INTERSECTS_FUNC:
func.add_operation(Gcalc_function::op_intersection, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break;
case SP_OVERLAPS_FUNC:
func.add_operation(Gcalc_function::op_backdifference, 2);
break;
case SP_CROSSES_FUNC:
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;
default:
DBUG_ASSERT(FALSE);
break;
}
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))))
if (null_value)
goto exit;
collector.prepare_operation();
scan_it.init(&collector);
#ifdef TMP_BLOCK
if (spatial_rel == SP_EQUALS_FUNC)
{
result= (g1->get_class_info()->m_type_id == g1->get_class_info()->m_type_id) &&
func_equals();
goto exit;
}
#endif /*TMP_BLOCK*/
if (func.alloc_states())
goto exit;
result= func.find_function(scan_it) ^ mask;
result= func.check_function(scan_it) ^ mask;
exit:
collector.reset();
......@@ -1307,7 +1225,7 @@ int Item_func_buffer::Transporter::start_line()
if (m_fn->reserve_op_buffer(2))
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_npoints= 0;
int_start_line();
......@@ -1321,7 +1239,7 @@ int Item_func_buffer::Transporter::start_poly()
if (m_fn->reserve_op_buffer(2))
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);
return Gcalc_operation_transporter::start_poly();
}
......@@ -1827,19 +1745,20 @@ double Item_func_distance::val_real()
of objects
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)
{
gcalc_shape_info si= pit.point()->get_shape();
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())
{
if (ev->event != scev_intersection)
cur_point= ev->pi;
func.set_on_state(ev->get_shape());
func.set_b_state(ev->get_shape());
if (func.count())
{
/* Point of one object is inside the other - intersection found */
......
......@@ -251,9 +251,6 @@ public:
void fix_length_and_dec() { maybe_null= 1; }
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
n_objects= uint4korr(data);
data+= 4;
if (!n_objects)
{
trn->empty_shape();
return 0;
}
if (trn->start_collection(n_objects))
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