Commit 3882c5d6 authored by Alexey Botchkov's avatar Alexey Botchkov

Fix for few similar bugs:

  #841622 Assertion `t->rp->type == Gcalc_function::shape_line' failed in Gcalc_operation_reducer::end_line in maria-5.3-gi
  #841625 Assertion `m_poly_borders->next' failed in Gcalc_operation_reducer::count_slice in maria-5.3-gis
  #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
  #841662 Third assertion `n > 0 && n < SINUSES_CALCULATED*2+1' in get_n_sincos
  #841745 Assertion `!sp0->is_bottom()' failed in Gcalc_scan_iterator::find_intersections in maria-5.3-gis

  They mostly was caused by inprecision of double arithmetic.
  Fixed by changes in how to handle multiple intersections to keep their order right.

  Also ST_DISTANCE(GEOM, EMPTY_GEOM) was defined as NULL.


per-file comments:
  mysql-test/r/gis-precise.result
   GIS bugfixes.
        test result updated.
  mysql-test/t/gis-precise.test
   GIS bugfixes.
        test cases added.
  sql/gcalc_slicescan.cc
   GIS bugfixes.
        If intersections are close, add order checks to cope with the
        double calcualtions imprecision.
  sql/gcalc_slicescan.h
   GIS bugfixes.
        n_row parameter added to intersection to check their order.
  sql/item_geofunc.cc
   GIS bugfixes.
        ST_DISTANCE(GEOM, EMPTY_GEOM) returns NULL.
parent a1315808
......@@ -214,7 +214,7 @@ astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0))
LINESTRING(0 0,1 1)
SELECT Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), 3)), 5);
Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), 3)), 5)
78.68303
78.68426
SELECT ST_INTERSECTION(NULL, NULL);
ST_INTERSECTION(NULL, NULL)
NULL
......@@ -257,7 +257,7 @@ ST_NUMGEOMETRIES((ST_UNION(ST_UNION(
MULTILINESTRINGFROMTEXT('MULTILINESTRING((2 0,4 2,0 2,1 5,0 3,7 0,8 5,5 8),
(6 2,4 0,3 5,3 6,4 3,6 4,3 9,0 7,3 7,8 4,2 9,5 0),
183
176
SELECT Round(ST_AREA(ST_BUFFER( ST_UNION(
POLYGONFROMTEXT('POLYGON((7 7, 7 7, 7 4, 7 7, 7 7))'),
POLYGONFROMTEXT('POLYGON((7 7, 4 7, 2 9, 7 6, 7 7))')), 1)), 6);
......@@ -331,3 +331,86 @@ ST_DISTANCE(POINTFROMTEXT('POINT(7 1)'),MULTILINESTRINGFROMTEXT('MULTILINESTRING
SELECT AsText(ST_UNION(POLYGONFROMTEXT('POLYGON((12 9, 3 6, 3 0, 12 9))'), POLYGONFROMTEXT('POLYGON((2 2, 7 2, 4 2, 2 0, 2 2))')));
AsText(ST_UNION(POLYGONFROMTEXT('POLYGON((12 9, 3 6, 3 0, 12 9))'), POLYGONFROMTEXT('POLYGON((2 2, 7 2, 4 2, 2 0, 2 2))')))
GEOMETRYCOLLECTION(POLYGON((2 0,2 2,3 2,3 6,12 9,3 0,3 1,2 0)),LINESTRING(5 2,7 2))
SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER(ST_UNION(
MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 2 5, 7 6, 1 8),(0 0 ,1 6 ,0 1, 8 9, 2 4, 6 1, 3 5, 4 8), (9 3, 5 4, 1 8, 4 2, 5 8, 3 0))' ) ,
MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 3 1, 2 7, 4 2, 6 2, 1 5))')
), 16)));
ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER(ST_UNION(
MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 2 5, 7 6, 1 8),(0 0 ,1 6 ,0 1, 8 9, 2 4, 6 1, 3 5, 4 8), (9 3, 5 4, 1 8, 4 2, 5 8, 3 0))' ) ,
MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 3 1, 2 7, 4 2, 6 2
280
SELECT 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 ) ) ' ),
ST_UNION (
MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 7 2 , 6 2 , 2 6 , 2 2 ) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) ,
ENVELOPE(
MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' )
)
)
),
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 9 , 1 3 , 7 3 , 8 5 ) , ( 5 0 , 8 1 , 2 0 , 7 4 , 1 0 ) , ( 9 2 , 5 2 , 6 5 , 8 8 , 0 2 ) , ( 0 8 , 3 9 , 4 0 , 1 0 ) , ( 0 0 , 7 6 , 8 3 , 0 0 ) ) ' )
));
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 )
126
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
659
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 (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ' ) ,
ST_SYMDIFFERENCE (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 3 8 , 0 8 , 6 6 , 6 1 , 0 5 , 6 7 , 3 7 ) , ( 5 8 , 7 7 , 9 0 , 8 7 ) , ( 1 5 , 1 8 , 2 3 , 3 9 ) , ( 1 3 , 9 7 , 5 5 , 0 8 , 6 9 ) , ( 3 6 , 6 9 , 8 7 , 0 2 , 4 6 , 9 5 ) ) ' ) ,
ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 9 4 , 2 0 , 2 2 , 7 2 , 6 2 ) , ( 5 2 , 8 2 , 4 8 , 3 4 ) , ( 1 0 , 1 4 , 2 7 , 7 0 , 1 5 ) , ( 2 8 , 4 4 , 5 0 , 7 0 , 4 0 ) ) ' ) ,
GEOMETRYFROMTEXT( ' MULTILINESTRING( ( 3 7 , 7 3 , 5 8 , 4 8 ) , ( 3 2 , 5 0 , 9 3 , 4 4 ) , ( 6 0 , 4 2 , 7 8 , 1 3 ) ) ' )
)
)
)
));
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 (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ' ) ,
ST_SYMDIFFERENCE (
MULTILINESTRINGFROMTEX
POLYGON((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4))
SELECT ST_NUMGEOMETRIES(ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 0 8 , 1 9 , 5 7 , 2 8 , 5 8 , 6 7 ) , ( 4 5 , 8 4 , 0 3 , 5 1 ) , ( 6 8 , 2 7 , 1 6 , 9 9 , 7 2 ) , ( 9 5 , 2 8 , 1 2 , 9 6 , 2 0 ) ) ' ) ,
MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 7 7 , 2 7, 6 8, 7 1 , 7 7 ) ) ) ' )
));
ST_NUMGEOMETRIES(ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 0 8 , 1 9 , 5 7 , 2 8 , 5 8 , 6 7 ) , ( 4 5 , 8 4 , 0 3 , 5 1 ) , ( 6 8 , 2 7 , 1 6 , 9 9 , 7 2 ) , ( 9 5 , 2 8 , 1 2 , 9 6 , 2 0 ) ) ' ) ,
MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (
50
SELECT ST_BUFFER (
LINESTRINGFROMTEXT( ' LINESTRING( 5 4 , 3 8 , 2 6 , 5 5 , 7 9 ) ' ) ,
ST_DISTANCE (
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_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 ) ) ) ' )
)
)
) ;
ST_BUFFER (
LINESTRINGFROMTEXT( ' LINESTRING( 5 4 , 3 8 , 2 6 , 5 5 , 7 9 ) ' ) ,
ST_DISTANCE (
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_DIFFERENCE (
MULTIPOL
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
......@@ -214,4 +214,69 @@ SELECT ST_DISTANCE(POINTFROMTEXT('POINT(7 1)'),MULTILINESTRINGFROMTEXT('MULTILIN
#bug 839327 Crash in Gcalc_operation_reducer::end_couple with ST_UNION and MULTIPOLYGONs in 5.3-gis
SELECT AsText(ST_UNION(POLYGONFROMTEXT('POLYGON((12 9, 3 6, 3 0, 12 9))'), POLYGONFROMTEXT('POLYGON((2 2, 7 2, 4 2, 2 0, 2 2))')));
#bug 841622 Assertion `t->rp->type == Gcalc_function::shape_line' failed in Gcalc_operation_reducer::end_line in maria-5.3-gis
SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER(ST_UNION(
MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 2 5, 7 6, 1 8),(0 0 ,1 6 ,0 1, 8 9, 2 4, 6 1, 3 5, 4 8), (9 3, 5 4, 1 8, 4 2, 5 8, 3 0))' ) ,
MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 3 1, 2 7, 4 2, 6 2, 1 5))')
), 16)));
#bug 841625 Assertion `m_poly_borders->next' failed in Gcalc_operation_reducer::count_slice in maria-5.3-gis
SELECT 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 ) ) ' ),
ST_UNION (
MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 7 2 , 6 2 , 2 6 , 2 2 ) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) ,
ENVELOPE(
MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' )
)
)
),
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 9 , 1 3 , 7 3 , 8 5 ) , ( 5 0 , 8 1 , 2 0 , 7 4 , 1 0 ) , ( 9 2 , 5 2 , 6 5 , 8 8 , 0 2 ) , ( 0 8 , 3 9 , 4 0 , 1 0 ) , ( 0 0 , 7 6 , 8 3 , 0 0 ) ) ' )
));
#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 ) ) ' ) ,
ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ' ) ,
ST_SYMDIFFERENCE (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 3 8 , 0 8 , 6 6 , 6 1 , 0 5 , 6 7 , 3 7 ) , ( 5 8 , 7 7 , 9 0 , 8 7 ) , ( 1 5 , 1 8 , 2 3 , 3 9 ) , ( 1 3 , 9 7 , 5 5 , 0 8 , 6 9 ) , ( 3 6 , 6 9 , 8 7 , 0 2 , 4 6 , 9 5 ) ) ' ) ,
ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 9 4 , 2 0 , 2 2 , 7 2 , 6 2 ) , ( 5 2 , 8 2 , 4 8 , 3 4 ) , ( 1 0 , 1 4 , 2 7 , 7 0 , 1 5 ) , ( 2 8 , 4 4 , 5 0 , 7 0 , 4 0 ) ) ' ) ,
GEOMETRYFROMTEXT( ' MULTILINESTRING( ( 3 7 , 7 3 , 5 8 , 4 8 ) , ( 3 2 , 5 0 , 9 3 , 4 4 ) , ( 6 0 , 4 2 , 7 8 , 1 3 ) ) ' )
)
)
)
));
#bug 841773 Assertion `t0->rp->type == t1->rp->type' failed in Gcalc_operation_reducer::end_couple in maria-5.3-gis
SELECT ST_NUMGEOMETRIES(ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 0 8 , 1 9 , 5 7 , 2 8 , 5 8 , 6 7 ) , ( 4 5 , 8 4 , 0 3 , 5 1 ) , ( 6 8 , 2 7 , 1 6 , 9 9 , 7 2 ) , ( 9 5 , 2 8 , 1 2 , 9 6 , 2 0 ) ) ' ) ,
MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 7 7 , 2 7, 6 8, 7 1 , 7 7 ) ) ) ' )
));
#bug 841662 Third assertion `n > 0 && n < SINUSES_CALCULATED*2+1' in get_n_sincos
SELECT ST_BUFFER (
LINESTRINGFROMTEXT( ' LINESTRING( 5 4 , 3 8 , 2 6 , 5 5 , 7 9 ) ' ) ,
ST_DISTANCE (
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_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 ) ) ) ' )
)
)
) ;
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 ) ) ) ' ) ) ;
......@@ -683,7 +683,8 @@ int Gcalc_scan_iterator::normal_scan()
#define INTERSECTION_ZERO 0.000000000001
int Gcalc_scan_iterator::add_intersection(const point *a, const point *b,
int Gcalc_scan_iterator::add_intersection(int n_row,
const point *a, const point *b,
Gcalc_dyn_list::Item ***p_hook)
{
intersection *isc= new_intersection();
......@@ -693,6 +694,7 @@ int Gcalc_scan_iterator::add_intersection(const point *a, const point *b,
m_n_intersections++;
**p_hook= isc;
*p_hook= &isc->next;
isc->n_row= n_row;
isc->thread_a= a->thread;
isc->thread_b= b->thread;
......@@ -703,13 +705,22 @@ int Gcalc_scan_iterator::add_intersection(const point *a, const point *b,
if (!a0->horiz_dir && !b0->horiz_dir)
{
double dk= a0->dx_dy - b0->dx_dy;
double dy= (b0->x - a0->x)/dk;
double b0_x= a0->next_pi->x - a0->pi->x;
double b0_y= a0->next_pi->y - a0->pi->y;
double b1_x= b0->next_pi->x - b0->pi->x;
double b1_y= b0->next_pi->y - b0->pi->y;
double b1xb0= b1_x * b0_y - b1_y * b0_x;
double t= (a0->pi->x - b0->pi->x) * b0_y - (a0->pi->y - b0->pi->y) * b0_x;
if (fabs(b1xb0) < INTERSECTION_ZERO)
{
isc->y= current_state->y;
isc->x= a0->x;
return 0;
}
if (fabs(dk) < INTERSECTION_ZERO)
dy= 0.0;
isc->y= current_state->y + dy;
isc->x= a0->x + dy*a0->dx_dy;
t/= b1xb0;
isc->x= b0->pi->x + b1_x*t;
isc->y= b0->pi->y + b1_y*t;
return 0;
}
isc->y= next_state->y;
......@@ -720,13 +731,13 @@ int Gcalc_scan_iterator::add_intersection(const point *a, const point *b,
int Gcalc_scan_iterator::find_intersections()
{
point *sp1= next_state->slice;
Gcalc_dyn_list::Item **hook;
m_n_intersections= 0;
{
/* Set links between slicepoints */
point *sp0= current_state->slice;
point *sp1= next_state->slice;
for (; sp1; sp0= sp0->get_next(),sp1= sp1->get_next())
{
DBUG_ASSERT(!sp0->is_bottom());
......@@ -737,30 +748,34 @@ int Gcalc_scan_iterator::find_intersections()
hook= (Gcalc_dyn_list::Item **)&m_intersections;
bool intersections_found;
int n_row= 0;
point *last_possible_isc= NULL;
do
{
point **pprev_s1= &next_state->slice;
intersections_found= false;
sp1= next_state->slice->get_next();
point *cur_possible_isc= NULL;
for (; sp1 != last_possible_isc;
pprev_s1= (point **)(&(*pprev_s1)->next), sp1= sp1->get_next())
n_row++;
for (;;)
{
point *prev_s1= *pprev_s1;
if (prev_s1->x <= sp1->x)
continue;
point *s1= prev_s1->get_next();
if (!s1)
break;
if (prev_s1->x <= s1->x)
{
pprev_s1= (point **) &prev_s1->next;
continue;
}
intersections_found= true;
if (add_intersection(prev_s1, sp1, &hook))
if (add_intersection(n_row, prev_s1, s1, &hook))
return 1;
*pprev_s1= sp1;
prev_s1->next= sp1->next;
sp1->next= prev_s1;
sp1= prev_s1;
cur_possible_isc= sp1;
}
last_possible_isc= cur_possible_isc;
*pprev_s1= s1;
prev_s1->next= s1->next;
s1->next= prev_s1;
pprev_s1= (point **) &prev_s1->next;
if (!*pprev_s1)
break;
};
} while (intersections_found);
*hook= NULL;
......@@ -772,7 +787,13 @@ static int compare_intersections(const void *e0, const void *e1)
{
Gcalc_scan_iterator::intersection *i0= (Gcalc_scan_iterator::intersection *)e0;
Gcalc_scan_iterator::intersection *i1= (Gcalc_scan_iterator::intersection *)e1;
if (i0->y != i1->y)
if (fabs(i0->y - i1->y) > 0.00000000000001)
return i0->y > i1->y;
if (i0->n_row != i1->n_row)
return i0->n_row > i1->n_row;
if (!coord_eq(i0->y, i1->y))
return i0->y > i1->y;
return i0->x > i1->x;
}
......@@ -810,7 +831,8 @@ int Gcalc_scan_iterator::intersection_scan()
{
point *sp0, *sp1;
Gcalc_dyn_list::Item **hook;
intersection *next_intersection;
intersection *next_intersection= NULL;
int met_equal= 0;
if (m_cur_intersection != m_intersections)
{
......@@ -860,7 +882,6 @@ int Gcalc_scan_iterator::intersection_scan()
next_state->y= m_cur_intersection->y;
found_equal_intersection:
sp0= current_state->slice;
hook= (Gcalc_dyn_list::Item **) &next_state->slice;
sp1= next_state->slice;
......@@ -872,6 +893,10 @@ found_equal_intersection:
if (sp0->thread == m_cur_intersection->thread_a ||
sp0->thread == m_cur_intersection->thread_b)
{
#ifdef REACTIVATE_THIS
DBUG_ASSERT(sp0->thread != m_cur_intersection->thread_a ||
sp0->get_next()->thread == m_cur_intersection->thread_b);
#endif /*REACTIVATE_THIS*/
sp1->copy_core(sp0);
sp1->x= m_cur_intersection->x;
sp1->event= scev_intersection;
......@@ -888,6 +913,7 @@ found_equal_intersection:
{
sp1->event= scev_intersection;
mark_event_position1(sp1, hook);
met_equal= 1;
}
else
sp1->event= scev_none;
......@@ -900,13 +926,64 @@ found_equal_intersection:
*hook= NULL;
}
next_intersection= m_cur_intersection->get_next();
if (next_intersection &&
coord_eq(next_intersection->x, m_cur_intersection->x) &&
coord_eq(next_intersection->y, m_cur_intersection->y))
if (met_equal)
{
m_cur_intersection= next_intersection;
goto found_equal_intersection;
/* Remove superfluous intersections. */
/* Double operations can produce unexact result, so it's needed. */
for (sp0= next_state->event_position;
sp0 != *next_state->event_end_hook;
sp0= sp0->get_next())
{
for (sp1= sp0->get_next();
sp1 != *next_state->event_end_hook;
sp1= sp1->get_next())
{
intersection *isc= m_cur_intersection;
while (isc->get_next())
{
intersection *cur_isc= isc->get_next();
if ((cur_isc->thread_a == sp0->thread &&
cur_isc->thread_b == sp1->thread) ||
(cur_isc->thread_a == sp1->thread &&
cur_isc->thread_b == sp0->thread))
{
/* The superfluous intersection should be close to the current. */
DBUG_ASSERT(fabs(cur_isc->x-m_cur_intersection->x) +
fabs(cur_isc->y-m_cur_intersection->y) <
INTERSECTION_ZERO);
isc->next= isc->next->next;
free_item(cur_isc);
}
else
isc= isc->get_next();
}
}
}
}
for (next_intersection= m_cur_intersection->get_next();
next_intersection &&
coord_eq(next_intersection->x, m_cur_intersection->x) &&
coord_eq(next_intersection->y, m_cur_intersection->y);
next_intersection= next_intersection->get_next())
{
/* Handle equal intersections. We only need to set proper events */
sp0= current_state->slice;
hook= (Gcalc_dyn_list::Item **) &next_state->slice;
sp1= next_state->slice;
next_state->clear_event_position();
for (; sp0;
hook= &sp1->next, sp1= sp1->get_next(), sp0= sp0->get_next())
{
if (sp0->thread == next_intersection->thread_a ||
sp0->thread == next_intersection->thread_b ||
sp1->event == scev_intersection)
{
sp1->event= scev_intersection;
mark_event_position1(sp1, hook);
}
}
}
m_cur_intersection= next_intersection;
......
......@@ -303,6 +303,7 @@ public:
class intersection : public Gcalc_dyn_list::Item
{
public:
int n_row;
sc_thread_id thread_a;
sc_thread_id thread_b;
double x;
......@@ -371,7 +372,7 @@ private:
void sort_intersections();
int handle_intersections();
int insert_top_point();
int add_intersection(const point *a, const point *b,
int add_intersection(int n_row, const point *a, const point *b,
Gcalc_dyn_list::Item ***p_hook);
int find_intersections();
......
......@@ -1789,6 +1789,14 @@ double Item_func_distance::val_real()
if (g2->store_shapes(&trn) || func.alloc_states())
goto mem_error;
if (obj2_si == 0 || func.get_nshapes() == obj2_si)
{
distance= 0.0;
null_value= 1;
goto exit;
}
collector.prepare_operation();
scan_it.init(&collector);
......
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