Commit 0249413a authored by Alexey Botchkov's avatar Alexey Botchkov

several bugs fixed here.

        849789  Second assertion `m_poly_borders->next' failed in Gcalc_operation_reducer::count_slice in maria-5.3-gis
        849791  Fourth assertion `n > 0 && n < SINUSES_CALCULATED*2+1' in get_n_sincos
        849789  Second assertion `m_poly_borders->next' failed in Gcalc_operation_reducer::count_slice in maria-5.3-gis
        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
        
per-file comments:
  mysql-test/r/gis-precise.result
        test result updated.
  mysql-test/r/gis.result
        test result updated.
  sql/gcalc_slicescan.cc
        bugfixes.
  sql/gcalc_slicescan.h
        bugfixes.
  sql/gcalc_tools.cc
        bugfixes.
  sql/gcalc_tools.h
        bugfixes.
  sql/item_geofunc.cc
        bugfixes.
  sql/spatial.cc
        bugfixes.
parent 5a04ac7b
...@@ -189,7 +189,7 @@ st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 ...@@ -189,7 +189,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))'))
1 0
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
...@@ -257,7 +257,7 @@ ST_NUMGEOMETRIES((ST_UNION(ST_UNION( ...@@ -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), 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), (6 2,4 0,3 5,3 6,4 3,6 4,3 9,0 7,3 7,8 4,2 9,5 0),
176 185
SELECT Round(ST_AREA(ST_BUFFER( ST_UNION( SELECT Round(ST_AREA(ST_BUFFER( ST_UNION(
POLYGONFROMTEXT('POLYGON((7 7, 7 7, 7 4, 7 7, 7 7))'), 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); POLYGONFROMTEXT('POLYGON((7 7, 4 7, 2 9, 7 6, 7 7))')), 1)), 6);
...@@ -338,7 +338,7 @@ MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 3 1, 2 7, 4 2, 6 2, 1 5))') ...@@ -338,7 +338,7 @@ MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 3 1, 2 7, 4 2, 6 2, 1 5))')
ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER(ST_UNION( 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, 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 MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 3 1, 2 7, 4 2, 6 2
280 275
SELECT ST_NUMGEOMETRIES(ST_DIFFERENCE ( SELECT 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 ) ) ' ),
...@@ -354,7 +354,7 @@ MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 9 , 1 3 , 7 3 , 8 5 ) , ( 5 0 , ...@@ -354,7 +354,7 @@ MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 9 , 1 3 , 7 3 , 8 5 ) , ( 5 0 ,
ST_NUMGEOMETRIES(ST_DIFFERENCE ( 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 )
126 123
SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER ( SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER (
ST_UNION ( 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( ( 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 ) ) ' ) ,
...@@ -365,7 +365,7 @@ ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER ( ...@@ -365,7 +365,7 @@ ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER (
ST_UNION ( 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( ( 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 MULTILINESTRI
659 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 (
...@@ -416,7 +416,7 @@ ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFR ...@@ -416,7 +416,7 @@ ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFR
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) ) ' ) ) ) ; 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 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
27 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)
...@@ -850,7 +850,7 @@ mbroverlaps ...@@ -850,7 +850,7 @@ mbroverlaps
down,left,right,up down,left,right,up
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrtouches FROM t1 a1 JOIN t1 a2 ON MBRTouches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrtouches FROM t1 a1 JOIN t1 a2 ON MBRTouches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
mbrtouches mbrtouches
big,center,down,down2,left,left2,right,right2,small,up,up2 down2,left2,right2,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1 a2 ON MBRWithin( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1 a2 ON MBRWithin( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
mbrwithin mbrwithin
big,center big,center
...@@ -871,7 +871,7 @@ overlaps ...@@ -871,7 +871,7 @@ overlaps
down,left,right,up down,left,right,up
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS touches FROM t1 a1 JOIN t1 a2 ON Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS touches FROM t1 a1 JOIN t1 a2 ON Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
touches touches
big,center,down,down2,left,left2,right,right2,small,up,up2 down2,left2,right2,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS within FROM t1 a1 JOIN t1 a2 ON Within( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS within FROM t1 a1 JOIN t1 a2 ON Within( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
within within
big,center big,center
......
...@@ -116,6 +116,450 @@ void Gcalc_dyn_list::reset() ...@@ -116,6 +116,450 @@ void Gcalc_dyn_list::reset()
} }
/* Internal coordinate operations implementations */
void Gcalc_internal_coord::set_zero()
{
int n_res= 0;
do
{
digits[n_res++]= 0;
} while (n_res < n_digits);
sign= 0;
}
int Gcalc_internal_coord::is_zero() const
{
int n_res= 0;
do
{
if (digits[n_res++] != 0)
return 0;
} while (n_res < n_digits);
return 1;
}
#ifdef GCALC_CHECK_WITH_FLOAT
long double Gcalc_internal_coord::get_double() const
{
int n= 0;
long double res= 0.0;
do
{
res*= (long double) DIG_BASE;
res+= digits[n];
} while(++n < n_digits);
n= 0;
do
{
if (n & 1)
res/= (long double) C_SCALE;
} while(++n < n_digits);
if (sign)
res*= -1.0;
return res;
}
#endif /*GCALC_CHECK_WITH_FLOAT*/
static void do_add(Gcalc_internal_coord *result,
const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b)
{
DBUG_ASSERT(a->n_digits == b->n_digits);
DBUG_ASSERT(a->n_digits == result->n_digits);
int n_digit= a->n_digits-1;
coord_digit_t carry= 0;
do
{
if ((result->digits[n_digit]=
a->digits[n_digit] + b->digits[n_digit] + carry) >= DIG_BASE)
{
carry= 1;
result->digits[n_digit]-= DIG_BASE;
}
else
carry= 0;
} while (n_digit--);
DBUG_ASSERT(carry == 0);
result->sign= a->sign;
}
static void do_sub(Gcalc_internal_coord *result,
const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b)
{
DBUG_ASSERT(a->n_digits == b->n_digits);
DBUG_ASSERT(a->n_digits == result->n_digits);
int n_digit= a->n_digits-1;
coord_digit_t carry= 0;
do
{
if ((result->digits[n_digit]=
a->digits[n_digit] - b->digits[n_digit] - carry) < 0)
{
carry= 1;
result->digits[n_digit]+= DIG_BASE;
}
else
carry= 0;
} while (n_digit--);
DBUG_ASSERT(carry == 0);
if (a->sign && result->is_zero())
result->sign= 0;
else
result->sign= a->sign;
}
static int do_cmp(const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b)
{
DBUG_ASSERT(a->n_digits == b->n_digits);
int n_digit= 0;
do
{
coord_digit_t d= a->digits[n_digit] - b->digits[n_digit];
if (d > 0)
return 1;
if (d < 0)
return -1;
n_digit++;
} while (n_digit < a->n_digits);
return 0;
}
#ifdef GCALC_CHECK_WITH_FLOAT
static int de_check(long double a, long double b)
{
long double d= a - b;
if (d < (long double) 1e-6 && d > (long double) -1e-6)
return 1;
printf("xxx\n");
return 0;
}
static int de_check1(long double a, long double b)
{
long double d= a - b;
if (d < (long double) 1e-6 && d > (long double) -1e-6)
return 1;
return 0;
}
static int de_weak(long double a, long double b)
{
long double d= a - b;
if (d < (long double) 1 && d > (long double) -1)
return 1;
return 0;
}
#endif /*GCALC_CHECK_WITH_FLOAT*/
void gcalc_mul_coord(Gcalc_internal_coord *result,
const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b)
{
DBUG_ASSERT(result->n_digits == a->n_digits + b->n_digits);
int n_a, n_b, n_res;
coord_digit_t carry= 0;
result->set_zero();
if (a->is_zero() || b->is_zero())
return;
n_a= a->n_digits - 1;
do
{
n_b= b->n_digits - 1;
do
{
coord2 mul= ((coord2) a->digits[n_a]) * b->digits[n_b] + carry +
result->digits[n_a + n_b + 1];
result->digits[n_a + n_b + 1]= mul % DIG_BASE;
carry= mul / DIG_BASE;
} while (n_b--);
if (carry)
{
for (n_res= n_a; (result->digits[n_res]+= carry) >= DIG_BASE; n_res--)
{
result->digits[n_res]-= DIG_BASE;
carry= 1;
}
carry= 0;
}
} while (n_a--);
result->sign= a->sign != b->sign;
#ifdef GCALC_CHECK_WITH_FLOAT
DBUG_ASSERT(de_check(a->get_double() * b->get_double(),
result->get_double()));
#endif /*GCALC_CHECK_WITH_FLOAT*/
}
void gcalc_add_coord(Gcalc_internal_coord *result,
const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b)
{
if (a->sign == b->sign)
do_add(result, a, b);
else
{
int cmp_res= do_cmp(a, b);
if (cmp_res == 0)
result->set_zero();
else if (cmp_res > 0)
do_sub(result, a, b);
else
do_sub(result, b, a);
}
#ifdef GCALC_CHECK_WITH_FLOAT
DBUG_ASSERT(de_check(a->get_double() + b->get_double(),
result->get_double()));
#endif /*GCALC_CHECK_WITH_FLOAT*/
}
void gcalc_sub_coord(Gcalc_internal_coord *result,
const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b)
{
if (a->sign != b->sign)
do_add(result, a, b);
else
{
int cmp_res= do_cmp(a, b);
if (cmp_res == 0)
result->set_zero();
else if (cmp_res > 0)
do_sub(result, a, b);
else
{
do_sub(result, b, a);
result->sign= 1 - result->sign;
}
}
#ifdef GCALC_CHECK_WITH_FLOAT
DBUG_ASSERT(de_check(a->get_double() - b->get_double(),
result->get_double()));
#endif /*GCALC_CHECK_WITH_FLOAT*/
}
int gcalc_cmp_coord(const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b)
{
int result;
if (a->sign != b->sign)
return a->sign ? -1 : 1;
result= a->sign ? do_cmp(b, a) : do_cmp(a, b);
#ifdef GCALC_CHECK_WITH_FLOAT
if (result == 0)
DBUG_ASSERT(de_check(a->get_double(), b->get_double()));
else if (result == 1)
DBUG_ASSERT(de_check1(a->get_double(), b->get_double()) ||
a->get_double() > b->get_double());
else
DBUG_ASSERT(de_check1(a->get_double(), b->get_double()) ||
a->get_double() < b->get_double());
#endif /*GCALC_CHECK_WITH_FLOAT*/
return result;
}
int Gcalc_coord1::set_double(double d)
{
double ds= d * C_SCALE;
init();
if ((sign= ds < 0))
ds= -ds;
c[0]= (coord_digit_t) (ds / (double) DIG_BASE);
c[1]= (coord_digit_t) (ds - ((double) c[0]) * DIG_BASE);
#ifdef GCALC_CHECK_WITH_FLOAT
DBUG_ASSERT(de_check(d, get_double()));
#endif /*GCALC_CHECK_WITH_FLOAT*/
return 0;
}
void Gcalc_coord1::copy(const Gcalc_coord1 *from)
{
c[0]= from->c[0];
c[1]= from->c[1];
sign= from->sign;
}
/* Internal coordinates implementation end */
Gcalc_heap::Info *Gcalc_heap::new_point_info(double x, double y,
gcalc_shape_info shape)
{
Info *result= (Info *)new_item();
if (!result)
return NULL;
*m_hook= result;
m_hook= &result->next;
m_n_points++;
result->x= x;
result->y= y;
result->shape= shape;
result->ix.set_double(x);
result->iy.set_double(y);
return result;
}
Gcalc_heap::Intersection_info *Gcalc_heap::new_intersection(
const Info *p1, const Info *p2,
const Info *p3, const Info *p4)
{
Intersection_info *isc= (Intersection_info *)new_item();
if (!isc)
return 0;
isc->p1= p1;
isc->p2= p2;
isc->p3= p3;
isc->p4= p4;
*m_intersection_hook= isc;
m_intersection_hook= &isc->next;
return isc;
}
class Gcalc_coord3 : public Gcalc_internal_coord
{
coord_digit_t c[COORD_BASE*3];
public:
void init()
{
n_digits= COORD_BASE*3;
digits= c;
}
};
static void calc_t(Gcalc_coord2 *t_a, Gcalc_coord2 *t_b,
Gcalc_coord1 *b1x,
Gcalc_coord1 *b1y,
const Gcalc_heap::Info *p1,
const Gcalc_heap::Info *p2,
const Gcalc_heap::Info *p3,
const Gcalc_heap::Info *p4)
{
Gcalc_coord1 a2_a1x, a2_a1y;
Gcalc_coord1 b2x, b2y;
Gcalc_coord2 x1y2, x2y1;
a2_a1x.init();
a2_a1y.init();
x1y2.init();
x2y1.init();
t_a->init();
t_b->init();
b1y->init();
b1x->init();
b2x.init();
b2y.init();
gcalc_sub_coord(&a2_a1x, &p3->ix, &p1->ix);
gcalc_sub_coord(&a2_a1y, &p3->iy, &p1->iy);
gcalc_sub_coord(b1x, &p2->ix, &p1->ix);
gcalc_sub_coord(b1y, &p2->iy, &p1->iy);
gcalc_sub_coord(&b2x, &p4->ix, &p3->ix);
gcalc_sub_coord(&b2y, &p4->iy, &p3->iy);
gcalc_mul_coord(&x1y2, b1x, &b2y);
gcalc_mul_coord(&x2y1, &b2x, b1y);
gcalc_sub_coord(t_b, &x1y2, &x2y1);
gcalc_mul_coord(&x1y2, &a2_a1x, &b2y);
gcalc_mul_coord(&x2y1, &a2_a1y, &b2x);
gcalc_sub_coord(t_a, &x1y2, &x2y1);
}
inline void calc_t(Gcalc_coord2 *t_a, Gcalc_coord2 *t_b,
Gcalc_coord1 *b1x,
Gcalc_coord1 *b1y,
const Gcalc_heap::Intersection_info *isc)
{
calc_t(t_a, t_b, b1x, b1y, isc->p1, isc->p2, isc->p3, isc->p4);
}
void Gcalc_heap::Intersection_info::calc_xy(double *x, double *y) const
{
double b0_x= p2->x - p1->x;
double b0_y= p2->y - p1->y;
double b1_x= p4->x - p3->x;
double b1_y= p4->y - p3->y;
double b0xb1= b0_x * b1_y - b0_y * b1_x;
double t= (p3->x - p1->x) * b1_y - (p3->y - p1->y) * b1_x;
t/= b0xb1;
*x= p1->x + b0_x * t;
*y= p1->y + b0_y * t;
}
#ifdef GCALC_CHECK_WITH_FLOAT
void Gcalc_heap::Intersection_info::calc_xy_ld(long double *x,
long double *y) const
{
long double b0_x= p2->x - p1->x;
long double b0_y= p2->y - p1->y;
long double b1_x= p4->x - p3->x;
long double b1_y= p4->y - p3->y;
long double b0xb1= b0_x * b1_y - b0_y * b1_x;
long double t= (p3->x - p1->x) * b1_y - (p3->y - p1->y) * b1_x;
long double cx, cy;
t/= b0xb1;
cx= (long double) p1->x + b0_x * t;
cy= (long double) p1->y + b0_y * t;
Gcalc_coord2 t_a, t_b;
Gcalc_coord1 yb, xb;
Gcalc_coord3 m1, m2, sum;
calc_t(&t_a, &t_b, &xb, &yb, this);
if (t_b.is_zero())
{
*x= p1->x;
*y= p1->y;
return;
}
m1.init();
m2.init();
sum.init();
gcalc_mul_coord(&m1, &p1->ix, &t_b);
gcalc_mul_coord(&m2, &xb, &t_a);
gcalc_add_coord(&sum, &m1, &m2);
*x= sum.get_double() / t_b.get_double();
gcalc_mul_coord(&m1, &p1->iy, &t_b);
gcalc_mul_coord(&m2, &yb, &t_a);
gcalc_add_coord(&sum, &m1, &m2);
*y= sum.get_double() / t_b.get_double();
}
#endif /*GCALC_CHECK_WITH_FLOAT*/
static inline void trim_node(Gcalc_heap::Info *node, Gcalc_heap::Info *prev_node) static inline void trim_node(Gcalc_heap::Info *node, Gcalc_heap::Info *prev_node)
{ {
if (!node) if (!node)
...@@ -127,13 +571,21 @@ static inline void trim_node(Gcalc_heap::Info *node, Gcalc_heap::Info *prev_node ...@@ -127,13 +571,21 @@ static inline void trim_node(Gcalc_heap::Info *node, Gcalc_heap::Info *prev_node
} }
static int cmp_point_info(const Gcalc_heap::Info *i0,
const Gcalc_heap::Info *i1)
{
int cmp_y= gcalc_cmp_coord(&i0->iy, &i1->iy);
if (cmp_y)
return cmp_y;
return gcalc_cmp_coord(&i0->ix, &i1->ix);
}
static int compare_point_info(const void *e0, const void *e1) static int compare_point_info(const void *e0, const void *e1)
{ {
const Gcalc_heap::Info *i0= (const Gcalc_heap::Info *)e0; const Gcalc_heap::Info *i0= (const Gcalc_heap::Info *)e0;
const Gcalc_heap::Info *i1= (const Gcalc_heap::Info *)e1; const Gcalc_heap::Info *i1= (const Gcalc_heap::Info *)e1;
if (!coord_eq(i0->y, i1->y)) return cmp_point_info(i0, i1) > 0;
return i0->y > i1->y;
return i0->x > i1->x;
} }
...@@ -155,6 +607,7 @@ void Gcalc_heap::prepare_operation() ...@@ -155,6 +607,7 @@ void Gcalc_heap::prepare_operation()
void Gcalc_heap::reset() void Gcalc_heap::reset()
{ {
#ifdef TMP_BLOCK
if (!m_hook) if (!m_hook)
{ {
m_hook= &m_first; m_hook= &m_first;
...@@ -164,10 +617,18 @@ void Gcalc_heap::reset() ...@@ -164,10 +617,18 @@ void Gcalc_heap::reset()
*m_hook= m_free; *m_hook= m_free;
m_free= m_first; m_free= m_first;
m_hook= &m_first; #endif /*TMP_BLOCK*/
if (m_n_points)
{
free_list(m_first);
free_list(m_first_intersection, m_intersection_hook);
m_intersection_hook= (Gcalc_dyn_list::Item **) &m_first_intersection;
m_n_points= 0; m_n_points= 0;
}
m_hook= &m_first;
} }
int Gcalc_shape_transporter::int_single_point(gcalc_shape_info Info, int Gcalc_shape_transporter::int_single_point(gcalc_shape_info Info,
double x, double y) double x, double y)
{ {
...@@ -229,6 +690,7 @@ void Gcalc_shape_transporter::int_complete() ...@@ -229,6 +690,7 @@ void Gcalc_shape_transporter::int_complete()
} }
#ifdef TMP_BLOCK
inline int GET_DX_DY(double *dxdy, inline int GET_DX_DY(double *dxdy,
const Gcalc_heap::Info *p0, const Gcalc_heap::Info *p1) const Gcalc_heap::Info *p0, const Gcalc_heap::Info *p1)
{ {
...@@ -238,6 +700,13 @@ inline int GET_DX_DY(double *dxdy, ...@@ -238,6 +700,13 @@ inline int GET_DX_DY(double *dxdy,
(*dxdy/= dy)>DBL_MAX || (*dxdy/= dy)>DBL_MAX ||
(*dxdy)<-DBL_MAX; (*dxdy)<-DBL_MAX;
} }
#endif /*TMP_BLOCK*/
inline void calc_dx_dy(Gcalc_scan_iterator::point *p)
{
gcalc_sub_coord(&p->dx, &p->next_pi->ix, &p->pi->ix);
gcalc_sub_coord(&p->dy, &p->next_pi->iy, &p->pi->iy);
}
Gcalc_scan_iterator::Gcalc_scan_iterator(size_t blk_size) : Gcalc_scan_iterator::Gcalc_scan_iterator(size_t blk_size) :
Gcalc_dyn_list(blk_size, Gcalc_dyn_list(blk_size,
...@@ -268,14 +737,20 @@ void Gcalc_scan_iterator::init(Gcalc_heap *points) ...@@ -268,14 +737,20 @@ void Gcalc_scan_iterator::init(Gcalc_heap *points)
if (!(m_cur_pi= points->get_first())) if (!(m_cur_pi= points->get_first()))
return; return;
m_heap= points;
m_cur_thread= 0; m_cur_thread= 0;
m_intersections= NULL; m_intersections= NULL;
m_cur_intersection= NULL;
m_next_is_top_point= true; m_next_is_top_point= true;
m_events= NULL; m_events= NULL;
current_state= &state0; current_state= &state0;
next_state= &state1; next_state= &state1;
saved_state= &state_s; saved_state= &state_s;
#ifdef TMP_BLOCK
next_state->y= m_cur_pi->y; next_state->y= m_cur_pi->y;
#endif /*TMP_BLOCK*/
next_state->intersection_scan= 0;
next_state->pi= m_cur_pi;
} }
void Gcalc_scan_iterator::reset() void Gcalc_scan_iterator::reset()
...@@ -286,20 +761,35 @@ void Gcalc_scan_iterator::reset() ...@@ -286,20 +761,35 @@ void Gcalc_scan_iterator::reset()
} }
void Gcalc_scan_iterator::point::copy_core(point *from) void Gcalc_scan_iterator::point::copy_core(const point *from)
{ {
#ifdef TMP_BLOCK
dx_dy= from->dx_dy; dx_dy= from->dx_dy;
horiz_dir= from->horiz_dir; horiz_dir= from->horiz_dir;
#endif /*TMP_BLOCK*/
pi= from->pi; pi= from->pi;
next_pi= from->next_pi; next_pi= from->next_pi;
thread= from->thread; thread= from->thread;
dx.copy(&from->dx);
dy.copy(&from->dy);
#ifdef TO_REMOVE #ifdef TO_REMOVE
from->next_link= this; from->next_link= this;
#endif /*TO_REMOVE*/ #endif /*TO_REMOVE*/
} }
int Gcalc_scan_iterator::point::compare_dx_dy(int horiz_dir_a, double dx_dy_a, void Gcalc_scan_iterator::point::copy_all(const point *from)
{
pi= from->pi;
next_pi= from->next_pi;
thread= from->thread;
dx.copy(&from->dx);
dy.copy(&from->dy);
intersection_link= from->intersection_link;
event= from->event;
}
#ifdef TMP_BLOCK
int Gcalc_scan_iterator::point::cmp_dx_dy(int horiz_dir_a, double dx_dy_a,
int horiz_dir_b, double dx_dy_b) int horiz_dir_b, double dx_dy_b)
{ {
if (!horiz_dir_a && !horiz_dir_b) if (!horiz_dir_a && !horiz_dir_b)
...@@ -323,7 +813,169 @@ int Gcalc_scan_iterator::point::cmp_dx_dy(const point *p) const ...@@ -323,7 +813,169 @@ int Gcalc_scan_iterator::point::cmp_dx_dy(const point *p) const
return p->is_bottom() ? 0 : -1; return p->is_bottom() ? 0 : -1;
if (p->is_bottom()) if (p->is_bottom())
return 1; return 1;
return compare_dx_dy(horiz_dir, dx_dy, p->horiz_dir, p->dx_dy); return cmp_dx_dy(horiz_dir, dx_dy, p->horiz_dir, p->dx_dy);
}
#endif /*TMP_BLOCK*/
int Gcalc_scan_iterator::point::cmp_dx_dy(const Gcalc_coord1 *dx_a,
const Gcalc_coord1 *dy_a,
const Gcalc_coord1 *dx_b,
const Gcalc_coord1 *dy_b)
{
Gcalc_coord2 dx_a_dy_b;
Gcalc_coord2 dy_a_dx_b;
dx_a_dy_b.init();
dy_a_dx_b.init();
gcalc_mul_coord(&dx_a_dy_b, dx_a, dy_b);
gcalc_mul_coord(&dy_a_dx_b, dy_a, dx_b);
return gcalc_cmp_coord(&dx_a_dy_b, &dy_a_dx_b);
}
int Gcalc_scan_iterator::point::cmp_dx_dy(const Gcalc_heap::Info *p1,
const Gcalc_heap::Info *p2,
const Gcalc_heap::Info *p3,
const Gcalc_heap::Info *p4)
{
Gcalc_coord1 dx_a, dy_a, dx_b, dy_b;
dx_a.init();
dx_b.init();
dy_a.init();
dy_b.init();
gcalc_sub_coord(&dx_a, &p2->ix, &p1->ix);
gcalc_sub_coord(&dy_a, &p2->iy, &p1->iy);
gcalc_sub_coord(&dx_b, &p4->ix, &p3->ix);
gcalc_sub_coord(&dy_b, &p4->iy, &p3->iy);
return cmp_dx_dy(&dx_a, &dy_a, &dx_b, &dy_b);
}
int Gcalc_scan_iterator::point::cmp_dx_dy(const point *p) const
{
if (is_bottom())
return p->is_bottom() ? 0 : -1;
if (p->is_bottom())
return 1;
return cmp_dx_dy(&dx, &dy, &p->dx, &p->dy);
}
#ifdef GCALC_CHECK_WITH_FLOAT
void Gcalc_scan_iterator::point::calc_x(long double *x, long double y,
long double ix) const
{
if (fabsl(dy.get_double()) < (long double) 1e-15)
{
*x= ix;
}
else
*x= (long double) pi->x + dx.get_double()/dy.get_double() * (y - pi->y);
}
#endif /*GCALC_CHECK_WITH_FLOAT*/
static int cmp_sp_pi(const Gcalc_scan_iterator::point *sp,
const Gcalc_heap::Info *pi)
{
Gcalc_coord1 dx_pi, dy_pi;
Gcalc_coord2 dx_sp_dy_pi, dy_sp_dx_pi;
if (!sp->next_pi)
return cmp_point_info(sp->pi, pi);
dx_pi.init();
dy_pi.init();
dx_sp_dy_pi.init();
dy_sp_dx_pi.init();
gcalc_sub_coord(&dx_pi, &pi->ix, &sp->pi->ix);
gcalc_sub_coord(&dy_pi, &pi->iy, &sp->pi->iy);
gcalc_mul_coord(&dx_sp_dy_pi, &sp->dx, &dy_pi);
gcalc_mul_coord(&dy_sp_dx_pi, &sp->dy, &dx_pi);
int result= gcalc_cmp_coord(&dx_sp_dy_pi, &dy_sp_dx_pi);
#ifdef GCALC_CHECK_WITH_FLOAT
long double sp_x;
sp->calc_x(&sp_x, pi->y, pi->x);
if (result == 0)
DBUG_ASSERT(de_check1(sp->dy.get_double(), 0.0) ||
de_check(sp_x, pi->x));
if (result < 0)
DBUG_ASSERT(de_check1(sp->dy.get_double(), 0.0) ||
de_check1(sp_x, pi->x) ||
sp_x < pi->x);
if (result > 0)
DBUG_ASSERT(de_check1(sp->dy.get_double(), 0.0) ||
de_check1(sp_x, pi->x) ||
sp_x > pi->x);
#endif /*GCALC_CHECK_WITH_FLOAT*/
return result;
}
static void calc_cmp_sp_sp_exp(Gcalc_coord3 *result,
const Gcalc_scan_iterator::point *a,
const Gcalc_scan_iterator::point *b,
const Gcalc_coord1 *ly)
{
Gcalc_coord2 x_dy, dx_ly, sum;
x_dy.init();
dx_ly.init();
sum.init();
result->init();
gcalc_mul_coord(&x_dy, &a->pi->ix, &a->dy);
gcalc_mul_coord(&dx_ly, &a->dx, ly);
gcalc_add_coord(&sum, &x_dy, &dx_ly);
gcalc_mul_coord(result, &sum, &b->dy);
}
static int cmp_sp_sp_cnt(const Gcalc_scan_iterator::point *a,
const Gcalc_scan_iterator::point *b,
const Gcalc_coord1 *y)
{
Gcalc_coord1 lya, lyb;
Gcalc_coord3 a_exp, b_exp;
lya.init();
lyb.init();
gcalc_sub_coord(&lya, y, &a->pi->iy);
gcalc_sub_coord(&lyb, y, &b->pi->iy);
calc_cmp_sp_sp_exp(&a_exp, a, b, &lya);
calc_cmp_sp_sp_exp(&b_exp, b, a, &lyb);
int result= gcalc_cmp_coord(&a_exp, &b_exp);
#ifdef GCALC_CHECK_WITH_FLOAT
long double a_x, b_x;
a->calc_x(&a_x, y->get_double(), 0);
b->calc_x(&b_x, y->get_double(), 0);
if (result == 0)
DBUG_ASSERT(de_check(a_x, b_x));
if (result < 0)
DBUG_ASSERT(de_check1(a_x, b_x) || a_x < b_x);
if (result > 0)
DBUG_ASSERT(de_check1(a_x, b_x) || a_x > b_x);
#endif /*GCALC_CHECK_WITH_FLOAT*/
return result;
}
static int cmp_sp_sp(const Gcalc_scan_iterator::point *a,
const Gcalc_scan_iterator::point *b,
const Gcalc_heap::Info *pi)
{
if (a->event == scev_none && b->event == scev_none)
return cmp_sp_sp_cnt(a, b, &pi->iy);
if (a->event == scev_none)
return cmp_sp_pi(a, pi);
if (b->event == scev_none)
return -1 * cmp_sp_pi(b, pi);
return 0;
} }
...@@ -366,7 +1018,7 @@ int Gcalc_scan_iterator::arrange_event() ...@@ -366,7 +1018,7 @@ int Gcalc_scan_iterator::arrange_event()
continue; continue;
if (!(new_sp= new_slice_point())) if (!(new_sp= new_slice_point()))
return 1; return 1;
*new_sp= *sp; new_sp->copy_all(sp);
*ae_hook= new_sp; *ae_hook= new_sp;
ae_hook= &new_sp->next; ae_hook= &new_sp->next;
#ifdef TO_REMOVE #ifdef TO_REMOVE
...@@ -420,10 +1072,12 @@ int Gcalc_scan_iterator::insert_top_point() ...@@ -420,10 +1072,12 @@ int Gcalc_scan_iterator::insert_top_point()
sp0->pi= m_cur_pi; sp0->pi= m_cur_pi;
sp0->next_pi= m_cur_pi->left; sp0->next_pi= m_cur_pi->left;
sp0->thread= m_cur_thread++; sp0->thread= m_cur_thread++;
#ifdef TMP_BLOCK
sp0->x= coord_to_float(m_cur_pi->x); sp0->x= coord_to_float(m_cur_pi->x);
#endif /*TMP_BLOCK*/
if (m_cur_pi->left) if (m_cur_pi->left)
{ {
sp0->horiz_dir= GET_DX_DY(&sp0->dx_dy, m_cur_pi, m_cur_pi->left); calc_dx_dy(sp0);
sp0->event= scev_thread; sp0->event= scev_thread;
/*Now just to increase the size of m_slice0 to be same*/ /*Now just to increase the size of m_slice0 to be same*/
...@@ -436,15 +1090,13 @@ int Gcalc_scan_iterator::insert_top_point() ...@@ -436,15 +1090,13 @@ int Gcalc_scan_iterator::insert_top_point()
if (!(sp1= new_slice_point())) if (!(sp1= new_slice_point()))
return 1; return 1;
sp1->event= sp0->event= scev_two_threads; sp1->event= sp0->event= scev_two_threads;
#ifdef TO_REMOVE
sp1->event_pair= sp0;
sp0->event_pair= sp1;
#endif /*TO_REMOVE*/
sp1->pi= m_cur_pi; sp1->pi= m_cur_pi;
sp1->next_pi= m_cur_pi->right; sp1->next_pi= m_cur_pi->right;
sp1->thread= m_cur_thread++; sp1->thread= m_cur_thread++;
#ifdef TMP_BLOCK
sp1->x= sp0->x; sp1->x= sp0->x;
sp1->horiz_dir= GET_DX_DY(&sp1->dx_dy, m_cur_pi, m_cur_pi->right); #endif /*TMP_BLOCK*/
calc_dx_dy(sp1);
/* We have two threads so should decide which one will be first */ /* We have two threads so should decide which one will be first */
if (sp0->cmp_dx_dy(sp1)>0) if (sp0->cmp_dx_dy(sp1)>0)
{ {
...@@ -463,17 +1115,20 @@ int Gcalc_scan_iterator::insert_top_point() ...@@ -463,17 +1115,20 @@ int Gcalc_scan_iterator::insert_top_point()
else else
{ {
sp0->event= scev_single_point; sp0->event= scev_single_point;
#ifdef TMP_BLOCK
sp0->horiz_dir= 0; sp0->horiz_dir= 0;
sp0->dx_dy= 0.0; sp0->dx_dy= 0.0;
#endif /*TMP_BLOCK*/
} }
/* We need to find the place to insert. */ /* We need to find the place to insert. */
for (; sp && (sp->x < sp0->x); prev_hook= &sp->next, sp=sp->get_next()) for (; sp && cmp_sp_pi(sp, m_cur_pi) < 0;
prev_hook= &sp->next, sp=sp->get_next())
{} {}
next_state->event_position_hook= prev_hook; next_state->event_position_hook= prev_hook;
if (sp && coord_eq(sp->x, sp0->x)) if (sp && cmp_sp_pi(sp, m_cur_pi) == 0)
{ {
next_state->event_position= sp; next_state->event_position= sp;
do do
...@@ -482,7 +1137,7 @@ int Gcalc_scan_iterator::insert_top_point() ...@@ -482,7 +1137,7 @@ int Gcalc_scan_iterator::insert_top_point()
sp->event= scev_intersection; sp->event= scev_intersection;
prev_hook= &sp->next; prev_hook= &sp->next;
sp= sp->get_next(); sp= sp->get_next();
} while (sp && coord_eq(sp->x, sp0->x)); } while (sp && cmp_sp_pi(sp, m_cur_pi) == 0);
} }
else else
next_state->event_position= sp0; next_state->event_position= sp0;
...@@ -503,44 +1158,88 @@ int Gcalc_scan_iterator::insert_top_point() ...@@ -503,44 +1158,88 @@ int Gcalc_scan_iterator::insert_top_point()
} }
#ifndef NO_TESTING
const char *pev(int ev)
{
switch (ev)
{
case scev_none:
return "n";
case scev_thread:
return "t";
case scev_two_threads:
return "tt";
case scev_end:
return "e";
case scev_two_ends:
return "ee";
case scev_intersection:
return "i";
case scev_point:
return "p";
case scev_single_point:
return "sp";
};
return "fck";
}
extern int ca_counter;
#endif /*NO_TESTING*/
int Gcalc_scan_iterator::normal_scan() int Gcalc_scan_iterator::normal_scan()
{ {
point *sp; point *sp;
Gcalc_dyn_list::Item **sp_hook; Gcalc_dyn_list::Item **sp_hook;
Gcalc_heap::Info *next_pi; Gcalc_heap::Info *next_pi;
point *first_bottom_point= NULL; point *first_bottom_point;
if (m_next_is_top_point && insert_top_point()) if (m_next_is_top_point && insert_top_point())
return 1; return 1;
for (next_pi= m_cur_pi->get_next(); for (next_pi= m_cur_pi->get_next();
next_pi && next_pi && cmp_point_info(m_cur_pi, next_pi) == 0;
coord_eq(m_cur_pi->x, next_pi->x) &&
coord_eq(m_cur_pi->y, next_pi->y);
next_pi= next_pi->get_next()) next_pi= next_pi->get_next())
{ {
DBUG_ASSERT(coord_eq(next_state->event_position->x, next_pi->x));
next_state->clear_event_position(); next_state->clear_event_position();
m_next_is_top_point= true; m_next_is_top_point= true;
first_bottom_point= NULL;
for (sp= next_state->slice, for (sp= next_state->slice,
sp_hook= (Gcalc_dyn_list::Item **) &next_state->slice; sp; sp_hook= (Gcalc_dyn_list::Item **) &next_state->slice; sp;
sp_hook= &sp->next, sp= sp->get_next()) sp_hook= &sp->next, sp= sp->get_next())
{ {
#ifndef NO_TESTING
// if (ca_counter == 21)
printf("%s%d\t", pev(sp->event), sp->thread);
#endif /*NO_TESTING*/
if (sp->next_pi == next_pi) /* End of the segment */ if (sp->next_pi == next_pi) /* End of the segment */
{ {
#ifdef TMP_BLOCK
sp->x= coord_to_float(next_pi->x); sp->x= coord_to_float(next_pi->x);
sp->pi= next_pi; sp->pi= next_pi;
#endif /*TMP_BLOCK*/
if (cmp_point_info(sp->pi, next_pi))
sp->pi= next_pi;
sp->next_pi= next_pi->left; sp->next_pi= next_pi->left;
m_next_is_top_point= false; m_next_is_top_point= false;
if (next_pi->is_bottom()) if (next_pi->is_bottom())
{ {
if (first_bottom_point) if (sp->event == scev_thread)
sp->event= scev_single_point;
else if (sp->event == scev_two_threads)
{
if (sp->get_next() && sp->get_next()->pi == sp->pi)
sp->get_next()->event= scev_thread;
else if (sp != next_state->slice)
{
point *fnd_sp;
for (fnd_sp= next_state->slice; fnd_sp->get_next() != sp;
fnd_sp= fnd_sp->get_next());
DBUG_ASSERT(fnd_sp->pi == sp->pi);
fnd_sp->event= scev_thread;
}
sp->event= scev_single_point;
}
else if (first_bottom_point)
{ {
first_bottom_point->event= sp->event= scev_two_ends; first_bottom_point->event= sp->event= scev_two_ends;
#ifdef TO_REMOVE
first_bottom_point->event_pair= sp;
sp->event_pair= first_bottom_point;
#endif /*TO_REMOVE*/
} }
else else
{ {
...@@ -550,21 +1249,52 @@ int Gcalc_scan_iterator::normal_scan() ...@@ -550,21 +1249,52 @@ int Gcalc_scan_iterator::normal_scan()
} }
else else
{ {
if ((sp->event & (scev_point | scev_thread | scev_two_threads)) == 0)
sp->event= scev_point; sp->event= scev_point;
sp->horiz_dir= GET_DX_DY(&sp->dx_dy, next_pi, next_pi->left); calc_dx_dy(sp);
} }
mark_event_position1(sp, sp_hook); mark_event_position1(sp, sp_hook);
} }
else if (coord_eq(sp->x, next_pi->x)) else if (sp->event || (cmp_sp_pi(sp, next_pi) == 0))
{ {
if (!sp->event) if (!sp->event)
sp->event= scev_intersection; sp->event= scev_intersection;
mark_event_position1(sp, sp_hook); mark_event_position1(sp, sp_hook);
} }
} }
#ifndef NO_TESTING
//if (ca_counter == 21)
printf("\n");
#endif /*NO_TESTING*/
m_cur_pi= next_pi; m_cur_pi= next_pi;
if (m_next_is_top_point && insert_top_point()) if (m_next_is_top_point)
{
if (insert_top_point())
return 1; return 1;
/* Set proper values to the event position */
/* TODO: can be done faster */
next_state->clear_event_position();
if (next_state->slice->event)
mark_event_position1(next_state->slice,
(Gcalc_dyn_list::Item **) &next_state->slice);
#ifndef NO_TESTING
//if (ca_counter == 21)
printf("*%s%d\t", pev(next_state->slice->event), next_state->slice->thread);
#endif /*NO_TESTING*/
for (sp= next_state->slice; sp->get_next(); sp= sp->get_next())
{
#ifndef NO_TESTING
//if (ca_counter == 21)
printf("%s%d\t", pev(sp->get_next()->event), sp->get_next()->thread);
#endif /*NO_TESTING*/
if (sp->get_next()->event)
mark_event_position1(sp->get_next(), &sp->next);
}
#ifndef NO_TESTING
//if (ca_counter == 21)
printf("\n");
#endif /*NO_TESTING*/
}
} }
/* Swap current <-> next */ /* Swap current <-> next */
...@@ -580,6 +1310,19 @@ int Gcalc_scan_iterator::normal_scan() ...@@ -580,6 +1310,19 @@ int Gcalc_scan_iterator::normal_scan()
point *sp0= current_state->slice; point *sp0= current_state->slice;
point *sp1= next_state->slice; point *sp1= next_state->slice;
point *prev_sp1= NULL; point *prev_sp1= NULL;
#ifndef NO_TESTING
//if (ca_counter == 21)
{
point *sp= current_state->slice;
printf("After arrange\n");
for (; sp; sp= sp->get_next())
printf("%s%d\t", pev(sp->event), sp->thread);
printf("\nEvent\n");
for (sp= m_events; sp; sp= sp->get_next())
printf("%s%d\t", pev(sp->event), sp->thread);
printf("\n");
}
#endif /*NO_TESTING*/
if (!(m_cur_pi= next_pi)) if (!(m_cur_pi= next_pi))
{ {
...@@ -592,8 +1335,12 @@ int Gcalc_scan_iterator::normal_scan() ...@@ -592,8 +1335,12 @@ int Gcalc_scan_iterator::normal_scan()
return 0; return 0;
} }
next_state->intersection_scan= 0;
next_state->pi= m_cur_pi;
Gcalc_heap::Info *cur_pi= m_cur_pi; Gcalc_heap::Info *cur_pi= m_cur_pi;
#ifdef TMP_BLOCK
next_state->y= coord_to_float(cur_pi->y); next_state->y= coord_to_float(cur_pi->y);
#endif /*TMP_BLOCK*/
first_bottom_point= NULL; first_bottom_point= NULL;
...@@ -603,9 +1350,12 @@ int Gcalc_scan_iterator::normal_scan() ...@@ -603,9 +1350,12 @@ int Gcalc_scan_iterator::normal_scan()
for (; sp0; sp0= sp0->get_next()) for (; sp0; sp0= sp0->get_next())
{ {
DBUG_ASSERT(!sp0->is_bottom());
if (sp0->next_pi == cur_pi) /* End of the segment */ if (sp0->next_pi == cur_pi) /* End of the segment */
{ {
#ifdef TMP_BLOCK
sp1->x= coord_to_float(cur_pi->x); sp1->x= coord_to_float(cur_pi->x);
#endif /*TMP_BLOCK*/
sp1->pi= cur_pi; sp1->pi= cur_pi;
sp1->thread= sp0->thread; sp1->thread= sp0->thread;
sp1->next_pi= cur_pi->left; sp1->next_pi= cur_pi->left;
...@@ -625,16 +1375,12 @@ int Gcalc_scan_iterator::normal_scan() ...@@ -625,16 +1375,12 @@ int Gcalc_scan_iterator::normal_scan()
else else
{ {
first_bottom_point->event= sp1->event= scev_two_ends; first_bottom_point->event= sp1->event= scev_two_ends;
#ifdef TO_REMOVE
sp1->event_pair= first_bottom_point;
first_bottom_point->event_pair= sp1;
#endif /*TO_REMOVE*/
} }
} }
else else
{ {
sp1->event= scev_point; sp1->event= scev_point;
sp1->horiz_dir= GET_DX_DY(&sp1->dx_dy, m_cur_pi, m_cur_pi->left); calc_dx_dy(sp1);
} }
mark_event_position1(sp1, mark_event_position1(sp1,
prev_sp1 ? &prev_sp1->next : prev_sp1 ? &prev_sp1->next :
...@@ -644,10 +1390,12 @@ int Gcalc_scan_iterator::normal_scan() ...@@ -644,10 +1390,12 @@ int Gcalc_scan_iterator::normal_scan()
{ {
/* Cut current string with the height of the new point*/ /* Cut current string with the height of the new point*/
sp1->copy_core(sp0); sp1->copy_core(sp0);
#ifdef TMP_BLOCK
sp1->x= sp1->horiz_dir ? coord_to_float(cur_pi->x) : sp1->x= sp1->horiz_dir ? coord_to_float(cur_pi->x) :
(coord_to_float(sp1->pi->x) + (coord_to_float(sp1->pi->x) +
(next_state->y-coord_to_float(sp1->pi->y)) * sp1->dx_dy); (next_state->y-coord_to_float(sp1->pi->y)) * sp1->dx_dy);
if (coord_eq(sp1->x, cur_pi->x)) #endif /*TMP_BLOCK*/
if (cmp_sp_pi(sp1, cur_pi) == 0)
{ {
mark_event_position1(sp1, mark_event_position1(sp1,
prev_sp1 ? &prev_sp1->next : prev_sp1 ? &prev_sp1->next :
...@@ -659,7 +1407,7 @@ int Gcalc_scan_iterator::normal_scan() ...@@ -659,7 +1407,7 @@ int Gcalc_scan_iterator::normal_scan()
} }
intersections_found= intersections_found || intersections_found= intersections_found ||
(prev_sp1 && prev_sp1->x > sp1->x); (prev_sp1 && cmp_sp_sp(prev_sp1, sp1, cur_pi) > 0);
prev_sp1= sp1; prev_sp1= sp1;
sp1= sp1->get_next(); sp1= sp1->get_next();
...@@ -674,6 +1422,16 @@ int Gcalc_scan_iterator::normal_scan() ...@@ -674,6 +1422,16 @@ int Gcalc_scan_iterator::normal_scan()
free_list(sp1); free_list(sp1);
} }
#ifndef NO_TESTING
//if (ca_counter == 21)
{
point *sp= next_state->slice;
printf("After slice\n");
for (; sp; sp= sp->get_next())
printf("%s%d\t", pev(sp->event), sp->thread);
printf("\n");
}
#endif /*NO_TESTING*/
if (intersections_found) if (intersections_found)
return handle_intersections(); return handle_intersections();
...@@ -681,16 +1439,20 @@ int Gcalc_scan_iterator::normal_scan() ...@@ -681,16 +1439,20 @@ int Gcalc_scan_iterator::normal_scan()
} }
#define INTERSECTION_ZERO 0.000000000001 #ifndef NO_TESTING
int isc_counter= 0;
#endif /*NO_TESTING*/
int Gcalc_scan_iterator::add_intersection(int n_row, int Gcalc_scan_iterator::add_intersection(int n_row,
const point *a, const point *b, const point *a, const point *b,
Gcalc_dyn_list::Item ***p_hook) Gcalc_dyn_list::Item ***p_hook)
{ {
const point *a0= a->intersection_link;
const point *b0= b->intersection_link;
intersection *isc= new_intersection(); intersection *isc= new_intersection();
if (!isc) if (!isc)
return 1; return 1;
m_n_intersections++; m_n_intersections++;
**p_hook= isc; **p_hook= isc;
*p_hook= &isc->next; *p_hook= &isc->next;
...@@ -698,34 +1460,17 @@ int Gcalc_scan_iterator::add_intersection(int n_row, ...@@ -698,34 +1460,17 @@ int Gcalc_scan_iterator::add_intersection(int n_row,
isc->thread_a= a->thread; isc->thread_a= a->thread;
isc->thread_b= b->thread; isc->thread_b= b->thread;
/* intersection_normal */ isc->ii= m_heap->new_intersection(a0->pi, a0->next_pi,
const point *a0= a->intersection_link; b0->pi, b0->next_pi);
const point *b0= b->intersection_link; #ifndef NO_TESTING
DBUG_ASSERT(!a0->horiz_dir || !b0->horiz_dir); //if (isc_counter == 40)
if (!a0->horiz_dir && !b0->horiz_dir)
{ {
double b0_x= a0->next_pi->x - a0->pi->x; long double ix, iy;
double b0_y= a0->next_pi->y - a0->pi->y; isc->ii->calc_xy_ld(&ix, &iy);
double b1_x= b0->next_pi->x - b0->pi->x; printf("%d\t%d\t%.20LG\t%.20LG\t%d\n", isc->thread_a, isc->thread_b, ix, iy, isc->n_row);
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;
}
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; #endif /*NO_TESTING*/
isc->x= a0->horiz_dir ? b->x : a->x; return isc->ii == NULL;
return 0;
} }
...@@ -733,6 +1478,10 @@ int Gcalc_scan_iterator::find_intersections() ...@@ -733,6 +1478,10 @@ int Gcalc_scan_iterator::find_intersections()
{ {
Gcalc_dyn_list::Item **hook; Gcalc_dyn_list::Item **hook;
#ifndef NO_TESTING
++isc_counter;
printf("Looking for intersections\n");
#endif /*NO_TESTING*/
m_n_intersections= 0; m_n_intersections= 0;
{ {
/* Set links between slicepoints */ /* Set links between slicepoints */
...@@ -743,6 +1492,15 @@ int Gcalc_scan_iterator::find_intersections() ...@@ -743,6 +1492,15 @@ int Gcalc_scan_iterator::find_intersections()
DBUG_ASSERT(!sp0->is_bottom()); DBUG_ASSERT(!sp0->is_bottom());
DBUG_ASSERT(sp0->thread == sp1->thread); DBUG_ASSERT(sp0->thread == sp1->thread);
sp1->intersection_link= sp0; sp1->intersection_link= sp0;
#ifndef NO_TESTING
//if (isc_counter == 40)
{
long double spx, spx1;
sp0->calc_x(&spx, current_state->pi->y, current_state->pi->x);
sp1->calc_x(&spx1, m_cur_pi->y, m_cur_pi->x);
printf("%d\t%.20LG\t%.20LG\n", sp0->thread, spx, spx1);
}
#endif /*NO_TESTING*/
} }
} }
...@@ -761,7 +1519,7 @@ int Gcalc_scan_iterator::find_intersections() ...@@ -761,7 +1519,7 @@ int Gcalc_scan_iterator::find_intersections()
point *s1= prev_s1->get_next(); point *s1= prev_s1->get_next();
if (!s1) if (!s1)
break; break;
if (prev_s1->x <= s1->x) if (cmp_sp_sp(prev_s1, s1, m_cur_pi) <= 0)
{ {
pprev_s1= (point **) &prev_s1->next; pprev_s1= (point **) &prev_s1->next;
continue; continue;
...@@ -783,19 +1541,250 @@ int Gcalc_scan_iterator::find_intersections() ...@@ -783,19 +1541,250 @@ int Gcalc_scan_iterator::find_intersections()
} }
static int compare_intersections(const void *e0, const void *e1) class Gcalc_coord4 : public Gcalc_internal_coord
{
coord_digit_t c[COORD_BASE*4];
public:
void init()
{
n_digits= COORD_BASE*4;
digits= c;
}
};
class Gcalc_coord5 : public Gcalc_internal_coord
{
coord_digit_t c[COORD_BASE*5];
public:
void init()
{
n_digits= COORD_BASE*5;
digits= c;
}
};
static void calc_isc_exp(Gcalc_coord5 *exp,
const Gcalc_coord2 *bb2,
const Gcalc_coord1 *ya1,
const Gcalc_coord2 *bb1,
const Gcalc_coord1 *yb1,
const Gcalc_coord2 *a21_b1)
{
Gcalc_coord3 p1, p2, sum;
p1.init();
p2.init();
sum.init();
exp->init();
gcalc_mul_coord(&p1, ya1, bb1);
gcalc_mul_coord(&p2, yb1, a21_b1);
gcalc_add_coord(&sum, &p1, &p2);
gcalc_mul_coord(exp, bb2, &sum);
}
#ifdef TMP_BLOCK
static void calc_aa1_b(Gcalc_coord2 *res,
const Gcalc_heap::Info *a0,
const Gcalc_heap::Info *a1,
const Gcalc_coord1 *xb,
const Gcalc_coord1 *yb)
{
Gcalc_coord1 aa1_x, aa1_y;
Gcalc_coord2 p1, p2;
res->init();
aa1_x.init();
aa1_y.init();
p1.init();
p2.init();
gcalc_sub_coord(&aa1_x, &a1->ix, &a0->ix);
gcalc_sub_coord(&aa1_y, &a1->iy, &a0->iy);
gcalc_mul_coord(&p1, &aa1_x, yb);
gcalc_mul_coord(&p2, &aa1_y, xb);
gcalc_sub_coord(res, &p1, &p2);
}
static int cmp_intersections_y(const Gcalc_heap::Intersection_info *i1,
const Gcalc_heap::Intersection_info *i2)
{
Gcalc_coord2 t_a1, t_b1;
Gcalc_coord2 t_a2, t_b2;
Gcalc_coord1 yb1, yb2;
Gcalc_coord1 xb1, xb2;
Gcalc_coord5 exp_a, exp_b;
calc_t(&t_a1, &t_b1, &xb1, &yb1, i1);
calc_t(&t_a2, &t_b2, &xb2, &yb2, i2);
calc_isc_exp(&exp_a, &t_b2, &i1->p1->iy, &t_b1, &yb1, &t_a1);
calc_isc_exp(&exp_b, &t_b1, &i2->p1->iy, &t_b2, &yb2, &t_a2);
int result= gcalc_cmp_coord(&exp_a, &exp_b);
#ifdef GCALC_CHECK_WITH_FLOAT
long double x1, y1, x2,y2;
i1->calc_xy_ld(&x1, &y1);
i2->calc_xy_ld(&x2, &y2);
if (result == 0)
DBUG_ASSERT(de_check(y1, y2));
if (result < 0)
DBUG_ASSERT(de_check1(y1, y2) || y1 < y2);
if (result > 0)
DBUG_ASSERT(de_check1(y1, y2) || y1 > y2);
#endif /*GCALC_CHECK_WITH_FLOAT*/
return result;
}
static int compare_intersections(const void *e1, const void *e2)
{ {
Gcalc_scan_iterator::intersection *i0= (Gcalc_scan_iterator::intersection *)e0;
Gcalc_scan_iterator::intersection *i1= (Gcalc_scan_iterator::intersection *)e1; Gcalc_scan_iterator::intersection *i1= (Gcalc_scan_iterator::intersection *)e1;
Gcalc_scan_iterator::intersection *i2= (Gcalc_scan_iterator::intersection *)e2;
int result= cmp_intersections_y(i1->ii, i2->ii);
if (result != 0)
return result > 0;
return (i1->n_row > i2->n_row);
}
if (fabs(i0->y - i1->y) > 0.00000000000001) #endif /*TMP_BLOCK*/
return i0->y > i1->y;
if (i0->n_row != i1->n_row) #ifndef NO_TESTING
return i0->n_row > i1->n_row; extern int ca_counter;
if (!coord_eq(i0->y, i1->y)) #endif /*NO_TESTING*/
return i0->y > i1->y; static int cmp_intersections(const Gcalc_heap::Intersection_info *i1,
return i0->x > i1->x; const Gcalc_heap::Intersection_info *i2)
{
Gcalc_coord2 t_a1, t_b1;
Gcalc_coord2 t_a2, t_b2;
Gcalc_coord1 yb1, yb2;
Gcalc_coord1 xb1, xb2;
Gcalc_coord5 exp_a, exp_b;
int result;
calc_t(&t_a1, &t_b1, &xb1, &yb1, i1);
calc_t(&t_a2, &t_b2, &xb2, &yb2, i2);
calc_isc_exp(&exp_a, &t_b2, &i1->p1->iy, &t_b1, &yb1, &t_a1);
calc_isc_exp(&exp_b, &t_b1, &i2->p1->iy, &t_b2, &yb2, &t_a2);
result= gcalc_cmp_coord(&exp_a, &exp_b);
#ifdef GCALC_CHECK_WITH_FLOAT
long double x1, y1, x2, y2;
i1->calc_xy_ld(&x1, &y1);
i2->calc_xy_ld(&x2, &y2);
if (result == 0)
DBUG_ASSERT(de_weak(y1, y2));
#ifndef NO_TESTING
if (ca_counter == 7)
printf("77");
#endif /*NO_TESTING*/
if (result < 0)
DBUG_ASSERT(de_weak(y1, y2) || y1 < y2);
if (result > 0)
DBUG_ASSERT(de_weak(y1, y2) || y1 > y2);
#endif /*GCALC_CHECK_WITH_FLOAT*/
if (result != 0)
return result;
calc_isc_exp(&exp_a, &t_b2, &i1->p1->ix, &t_b1, &xb1, &t_a1);
calc_isc_exp(&exp_b, &t_b1, &i2->p1->ix, &t_b2, &xb2, &t_a2);
result= gcalc_cmp_coord(&exp_a, &exp_b);
#ifdef GCALC_CHECK_WITH_FLOAT
if (result == 0)
DBUG_ASSERT(de_weak(x1, x2));
if (result < 0)
DBUG_ASSERT(de_weak(x1, x2) || x1 < x2);
if (result > 0)
DBUG_ASSERT(de_weak(x1, x2) || x1 > x2);
#endif /*GCALC_CHECK_WITH_FLOAT*/
return result;
}
static int compare_intersections(const void *e1, const void *e2)
{
Gcalc_scan_iterator::intersection *i1= (Gcalc_scan_iterator::intersection *)e1;
Gcalc_scan_iterator::intersection *i2= (Gcalc_scan_iterator::intersection *)e2;
int result= cmp_intersections(i1->ii, i2->ii);
if (result != 0)
return result > 0;
return (i1->n_row > i2->n_row);
}
inline int intersections_eq(const Gcalc_heap::Intersection_info *i1,
const Gcalc_heap::Intersection_info *i2)
{
return cmp_intersections(i1, i2) == 0;
}
#ifdef TMP_BLOCK
static void calc_isc_sp_exp(Gcalc_coord4 *exp,
const Gcalc_coord2 *bb,
const Gcalc_coord1 *x1,
const Gcalc_coord1 *y1,
const Gcalc_coord1 *x2,
const Gcalc_coord1 *y2)
{
Gcalc_coord2 p1, p2, sum;
p1.init();
p2.init();
sum.init();
exp->init();
gcalc_mul_coord(&p1, x1, y1);
gcalc_mul_coord(&p2, x2, y2);
gcalc_add_coord(&sum, &p1, &p2);
gcalc_mul_coord(exp, bb, &sum);
}
#endif /*TMP_BLOCK*/
static int sp_isc_eq(const Gcalc_scan_iterator::point *sp,
const Gcalc_heap::Intersection_info *isc)
{
Gcalc_coord4 exp_a, exp_b;
Gcalc_coord1 xb1, yb1;
Gcalc_coord2 t_a, t_b;
Gcalc_coord2 t_sp_a, t_sp_b;
#ifdef TMP_BLOCK
xa1a0.init();
ya1a0.init();
gcalc_sub_coord(&xa1a0, &isc->p1->ix, &sp->pi->ix);
gcalc_sub_coord(&ya1a0, &isc->p1->iy, &sp->pi->iy);
calc_isc_sp_exp(&exp_a, &t_b, &sp->pi->ix, &ya1a0, &sp->pi->iy, &xa1a0);
calc_isc_sp_exp(&exp_b, &t_a, &sp->pi->iy, &isc->p1->ix,
&sp->pi->ix, &isc->p1->iy);
return gcalc_cmp_coord(&exp_a, &exp_b);
#endif /*TMP_BLOCK*/
exp_a.init();
exp_b.init();
calc_t(&t_a, &t_b, &xb1, &yb1, isc);
calc_t(&t_sp_a, &t_sp_b, &xb1, &yb1, isc->p1, isc->p2, sp->pi, sp->next_pi);
gcalc_mul_coord(&exp_a, &t_a, &t_sp_b);
gcalc_mul_coord(&exp_b, &t_b, &t_sp_a);
int result= gcalc_cmp_coord(&exp_a, &exp_b);
#ifdef GCALC_CHECK_WITH_FLOAT
long double int_x, int_y, sp_x;
isc->calc_xy_ld(&int_x, &int_y);
sp->calc_x(&sp_x, int_y, int_x);
if (result == 0)
DBUG_ASSERT(de_check1(sp->dy.get_double(), 0.0) ||
de_check(sp_x, int_x));
#ifdef TMP_BLOCK
else
DBUG_ASSERT(!de_check1(sp_x, int_x));
#endif /*TMP_BLOCK*/
#endif /*GCALC_CHECK_WITH_FLOAT*/
return result == 0;
} }
...@@ -823,6 +1812,18 @@ int Gcalc_scan_iterator::handle_intersections() ...@@ -823,6 +1812,18 @@ int Gcalc_scan_iterator::handle_intersections()
/* We need the next slice to be just equal */ /* We need the next slice to be just equal */
next_state->slice= new_slice(saved_state->slice); next_state->slice= new_slice(saved_state->slice);
m_cur_intersection= m_intersections; m_cur_intersection= m_intersections;
#ifndef NO_TESTING
//if (isc_counter == 40)
{
printf("Sorted\n");
for (intersection *isc= m_intersections; isc; isc= isc->get_next())
{
long double ix, iy;
isc->ii->calc_xy_ld(&ix, &iy);
printf("%d\t%d\t%.20LG\t%.20LG\t%d\n", isc->thread_a, isc->thread_b, ix, iy, isc->n_row);
}
}
#endif /*NO_TESTING*/
return intersection_scan(); return intersection_scan();
} }
...@@ -832,7 +1833,6 @@ int Gcalc_scan_iterator::intersection_scan() ...@@ -832,7 +1833,6 @@ int Gcalc_scan_iterator::intersection_scan()
point *sp0, *sp1; point *sp0, *sp1;
Gcalc_dyn_list::Item **hook; Gcalc_dyn_list::Item **hook;
intersection *next_intersection= NULL; intersection *next_intersection= NULL;
int met_equal= 0;
if (m_cur_intersection != m_intersections) if (m_cur_intersection != m_intersections)
{ {
...@@ -846,20 +1846,12 @@ int Gcalc_scan_iterator::intersection_scan() ...@@ -846,20 +1846,12 @@ int Gcalc_scan_iterator::intersection_scan()
if (arrange_event()) if (arrange_event())
return 1; return 1;
#ifdef TMP_BLOCK
if (!m_cur_intersection) if (!m_cur_intersection)
{ {
saved_state->event_position_hook= saved_state->event_position_hook=
(Gcalc_dyn_list::Item **) &saved_state->slice; (Gcalc_dyn_list::Item **) &saved_state->slice;
#ifdef TO_REMOVE
for (sp0= current_state->slice, sp1= saved_state->slice;
sp0;
sp0= sp0->get_next(), sp1= sp1->get_next())
{
sp0->next_link= sp1;
if (sp1->get_next() == saved_state->event_position)
saved_state->event_position_hook= &sp1->next;
}
#endif /*TO_REMOVE*/
for (sp1= saved_state->slice; sp1; sp1= sp1->get_next()) for (sp1= saved_state->slice; sp1; sp1= sp1->get_next())
{ {
if (sp1->get_next() == saved_state->event_position) if (sp1->get_next() == saved_state->event_position)
...@@ -878,14 +1870,63 @@ int Gcalc_scan_iterator::intersection_scan() ...@@ -878,14 +1870,63 @@ int Gcalc_scan_iterator::intersection_scan()
m_intersections= NULL; m_intersections= NULL;
return 0; return 0;
} }
#endif /*TMP_BLOCK*/
if (!m_cur_intersection)
{
/* Swap saved <-> next */
{
slice_state *tmp= next_state;
next_state= saved_state;
saved_state= tmp;
} }
Gcalc_dyn_list::Item **n_hook=
(Gcalc_dyn_list::Item **) &next_state->slice;
next_state->y= m_cur_intersection->y; next_state->clear_event_position();
sp0= current_state->slice;
sp1= next_state->slice;
for (; sp0;
sp0= sp0->get_next(), n_hook= &sp1->next, sp1= sp1->get_next())
{
if (sp0->thread != sp1->thread)
{
point *fnd_s= sp1->get_next();
Gcalc_dyn_list::Item **fnd_hook= &sp1->next;
for (; fnd_s && fnd_s->thread != sp0->thread;
fnd_hook= &fnd_s->next, fnd_s= fnd_s->get_next());
DBUG_ASSERT(fnd_s && fnd_s == *fnd_hook);
/* Now swap items of the next_state->slice */
*n_hook= fnd_s;
*fnd_hook= fnd_s->next;
fnd_s->next= sp1;
sp1= fnd_s;
}
if (sp1->event)
mark_event_position1(sp1, n_hook);
}
#ifndef DBUG_OFF
sp0= current_state->slice;
sp1= next_state->slice;
for (; sp0; sp0= sp0->get_next(), sp1= sp1->get_next())
DBUG_ASSERT(sp0->thread == sp1->thread);
DBUG_ASSERT(!sp1);
#endif /*DBUG_OFF*/
free_list(saved_state->slice);
saved_state->slice= NULL;
free_list(m_intersections);
m_intersections= NULL;
return 0;
}
}
sp0= current_state->slice; sp0= current_state->slice;
hook= (Gcalc_dyn_list::Item **) &next_state->slice; hook= (Gcalc_dyn_list::Item **) &next_state->slice;
sp1= next_state->slice; sp1= next_state->slice;
next_state->clear_event_position(); next_state->clear_event_position();
next_state->intersection_scan= 1;
next_state->isc= m_cur_intersection->ii;
for (; sp0; for (; sp0;
hook= &sp1->next, sp1= sp1->get_next(), sp0= sp0->get_next()) hook= &sp1->next, sp1= sp1->get_next(), sp0= sp0->get_next())
...@@ -893,27 +1934,20 @@ int Gcalc_scan_iterator::intersection_scan() ...@@ -893,27 +1934,20 @@ int Gcalc_scan_iterator::intersection_scan()
if (sp0->thread == m_cur_intersection->thread_a || if (sp0->thread == m_cur_intersection->thread_a ||
sp0->thread == m_cur_intersection->thread_b) sp0->thread == m_cur_intersection->thread_b)
{ {
#ifdef REACTIVATE_THIS
DBUG_ASSERT(sp0->thread != m_cur_intersection->thread_a || DBUG_ASSERT(sp0->thread != m_cur_intersection->thread_a ||
sp0->get_next()->thread == m_cur_intersection->thread_b); sp0->get_next()->thread == m_cur_intersection->thread_b ||
#endif /*REACTIVATE_THIS*/ sp_isc_eq(sp0->get_next(), m_cur_intersection->ii));
sp1->copy_core(sp0); sp1->copy_core(sp0);
sp1->x= m_cur_intersection->x;
sp1->event= scev_intersection; sp1->event= scev_intersection;
mark_event_position1(sp1, hook); mark_event_position1(sp1, hook);
} }
else else
{ {
sp1->copy_core(sp0); sp1->copy_core(sp0);
sp1->x= sp1->horiz_dir ? if (sp_isc_eq(sp1, m_cur_intersection->ii))
m_cur_intersection->x :
coord_to_float(sp1->pi->x) +
(next_state->y-coord_to_float(sp1->pi->y)) * sp1->dx_dy;
if (coord_eq(sp1->x, m_cur_intersection->x))
{ {
sp1->event= scev_intersection; sp1->event= scev_intersection;
mark_event_position1(sp1, hook); mark_event_position1(sp1, hook);
met_equal= 1;
} }
else else
sp1->event= scev_none; sp1->event= scev_none;
...@@ -926,45 +1960,10 @@ int Gcalc_scan_iterator::intersection_scan() ...@@ -926,45 +1960,10 @@ int Gcalc_scan_iterator::intersection_scan()
*hook= NULL; *hook= NULL;
} }
if (met_equal) /* Now check equal intersections */
{
/* 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) <
0.00000000001);
isc->next= isc->next->next;
free_item(cur_isc);
}
else
isc= isc->get_next();
}
}
}
}
for (next_intersection= m_cur_intersection->get_next(); for (next_intersection= m_cur_intersection->get_next();
next_intersection && next_intersection &&
coord_eq(next_intersection->x, m_cur_intersection->x) && intersections_eq(next_intersection->ii, m_cur_intersection->ii);
coord_eq(next_intersection->y, m_cur_intersection->y);
next_intersection= next_intersection->get_next()) next_intersection= next_intersection->get_next())
{ {
/* Handle equal intersections. We only need to set proper events */ /* Handle equal intersections. We only need to set proper events */
...@@ -990,5 +1989,58 @@ int Gcalc_scan_iterator::intersection_scan() ...@@ -990,5 +1989,58 @@ int Gcalc_scan_iterator::intersection_scan()
return 0; return 0;
} }
double Gcalc_scan_iterator::get_y() const
{
if (current_state->intersection_scan)
{
double x, y;
current_state->isc->calc_xy(&x, &y);
return y;
}
else
return current_state->pi->y;
}
double Gcalc_scan_iterator::get_event_x() const
{
if (current_state->intersection_scan)
{
double x, y;
current_state->isc->calc_xy(&x, &y);
return x;
}
else
return current_state->pi->x;
}
double Gcalc_scan_iterator::get_h() const
{
double cur_y= get_y();
double next_y;
if (next_state->intersection_scan)
{
double x;
next_state->isc->calc_xy(&x, &next_y);
}
else
next_y= next_state->pi->y;
return next_y - cur_y;
}
double Gcalc_scan_iterator::get_sp_x(const point *sp) const
{
double dy;
if (sp->event == scev_end | scev_two_ends | scev_point)
return sp->pi->x;
dy= sp->next_pi->y - sp->pi->y;
if (fabs(dy) < 1e-12)
return sp->pi->x;
return (sp->next_pi->x - sp->pi->x) * dy;
}
#endif /* HAVE_SPATIAL */ #endif /* HAVE_SPATIAL */
...@@ -58,10 +58,13 @@ public: ...@@ -58,10 +58,13 @@ public:
m_free= item; m_free= item;
} }
inline void free_list(Item *list, Item **hook) inline void free_list(Item *list, Item **hook)
{
if (*hook != list)
{ {
*hook= m_free; *hook= m_free;
m_free= list; m_free= list;
} }
}
void free_list(Item *list) void free_list(Item *list)
{ {
...@@ -91,6 +94,79 @@ protected: ...@@ -91,6 +94,79 @@ protected:
} }
}; };
/* Internal Gcalc coordinates to provide the precise calculations */
#define DIG_BASE 1000000000
typedef int32 coord_digit_t;
typedef long long coord2;
#define C_SCALE 1e13
#define COORD_BASE 2
#ifndef DBUG_OFF
//#define GCALC_CHECK_WITH_FLOAT
#define NO_TESTING
#else
#define NO_TESTING
#endif /*DBUG_OFF*/
class Gcalc_internal_coord
{
public:
coord_digit_t *digits;
int sign;
int n_digits;
void set_zero();
int is_zero() const;
#ifdef GCALC_CHECK_WITH_FLOAT
long double get_double() const;
#endif /*GCALC_CHECK_WITH_FLOAT*/
};
class Gcalc_coord1 : public Gcalc_internal_coord
{
coord_digit_t c[COORD_BASE];
public:
void init()
{
n_digits= COORD_BASE;
digits= c;
}
int set_double(double d);
void copy(const Gcalc_coord1 *from);
};
class Gcalc_coord2 : public Gcalc_internal_coord
{
coord_digit_t c[COORD_BASE*2];
public:
void init()
{
n_digits= COORD_BASE*2;
digits= c;
}
};
void gcalc_mul_coord(Gcalc_internal_coord *result,
const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b);
void gcalc_add_coord(Gcalc_internal_coord *result,
const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b);
void gcalc_sub_coord(Gcalc_internal_coord *result,
const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b);
int gcalc_cmp_coord(const Gcalc_internal_coord *a,
const Gcalc_internal_coord *b);
/* Internal coordinates declarations end. */
typedef uint gcalc_shape_info; typedef uint gcalc_shape_info;
/* /*
...@@ -114,27 +190,34 @@ public: ...@@ -114,27 +190,34 @@ public:
Info *left; Info *left;
Info *right; Info *right;
double x,y; double x,y;
Gcalc_coord1 ix, iy;
inline bool is_bottom() const { return !left; } inline bool is_bottom() const { return !left; }
inline Info *get_next() { return (Info *)next; } inline Info *get_next() { return (Info *)next; }
inline const Info *get_next() const { return (const Info *)next; } inline const Info *get_next() const { return (const Info *)next; }
}; };
class Intersection_info : public Gcalc_dyn_list::Item
{
public:
/* Line p1-p2 supposed to intersect line p3-p4 */
const Info *p1;
const Info *p2;
const Info *p3;
const Info *p4;
void calc_xy(double *x, double *y) const;
#ifdef GCALC_CHECK_WITH_FLOAT
void calc_xy_ld(long double *x, long double *y) const;
#endif /*GCALC_CHECK_WITH_FLOAT*/
};
Gcalc_heap(size_t blk_size=8192) : Gcalc_heap(size_t blk_size=8192) :
Gcalc_dyn_list(blk_size, sizeof(Info)), m_hook(&m_first), m_n_points(0) {} Gcalc_dyn_list(blk_size, sizeof(Info)),
Info *new_point_info(double x, double y, gcalc_shape_info shape) m_hook(&m_first), m_n_points(0),
{ m_intersection_hook((Gcalc_dyn_list::Item **) &m_first_intersection)
Info *result= (Info *)new_item(); {}
if (!result) Info *new_point_info(double x, double y, gcalc_shape_info shape);
return NULL; Intersection_info *new_intersection(const Info *p1, const Info *p2,
*m_hook= result; const Info *p3, const Info *p4);
m_hook= &result->next;
m_n_points++;
result->x= x;
result->y= y;
result->shape= shape;
return result;
}
void prepare_operation(); void prepare_operation();
inline bool ready() const { return m_hook == NULL; } inline bool ready() const { return m_hook == NULL; }
Info *get_first() { return (Info *)m_first; } Info *get_first() { return (Info *)m_first; }
...@@ -145,6 +228,8 @@ private: ...@@ -145,6 +228,8 @@ private:
Gcalc_dyn_list::Item *m_first; Gcalc_dyn_list::Item *m_first;
Gcalc_dyn_list::Item **m_hook; Gcalc_dyn_list::Item **m_hook;
int m_n_points; int m_n_points;
Intersection_info *m_first_intersection;
Gcalc_dyn_list::Item **m_intersection_hook;
}; };
...@@ -263,9 +348,13 @@ public: ...@@ -263,9 +348,13 @@ public:
class point : public Gcalc_dyn_list::Item class point : public Gcalc_dyn_list::Item
{ {
public: public:
#ifdef TMP_BLOCK
double x; double x;
double dx_dy; double dx_dy;
int horiz_dir; int horiz_dir;
#endif /*TMP_BLOCK*/
Gcalc_coord1 dx;
Gcalc_coord1 dy;
Gcalc_heap::Info *pi; Gcalc_heap::Info *pi;
Gcalc_heap::Info *next_pi; Gcalc_heap::Info *next_pi;
sc_thread_id thread; sc_thread_id thread;
...@@ -273,22 +362,32 @@ public: ...@@ -273,22 +362,32 @@ public:
const point *intersection_link; const point *intersection_link;
Gcalc_scan_events event; Gcalc_scan_events event;
#ifdef TO_REMOVE #ifdef TO_REMOVE
const point *event_pair;
point *next_link; point *next_link;
#endif /*TO_REMOVE*/ #endif /*TO_REMOVE*/
inline const point *c_get_next() const inline const point *c_get_next() const
{ return (const point *)next; } { return (const point *)next; }
inline bool is_bottom() const { return pi->is_bottom(); } inline bool is_bottom() const { return !next_pi; }
gcalc_shape_info get_shape() const { return pi->shape; } gcalc_shape_info get_shape() const { return pi->shape; }
inline point *get_next() { return (point *)next; } inline point *get_next() { return (point *)next; }
inline const point *get_next() const { return (const point *)next; } inline const point *get_next() const { return (const point *)next; }
/* copies all but 'next' 'x' and 'precursor' */ /* copies all but 'next' 'x' and 'precursor' */
void copy_core(point *from); void copy_core(const point *from);
void copy_all(const point *from);
/* Compare the dx_dy parameters regarding the horiz_dir */ /* Compare the dx_dy parameters regarding the horiz_dir */
/* returns -1 if less, 0 if equal, 1 if bigger */ /* returns -1 if less, 0 if equal, 1 if bigger */
static int compare_dx_dy(int horiz_dir_a, double dx_dy_a, #ifdef TMP_BLOCK
static int cmp_dx_dy(int horiz_dir_a, double dx_dy_a,
int horiz_dir_b, double dx_dy_b); int horiz_dir_b, double dx_dy_b);
#endif /*TMP_BLOCK*/
static int cmp_dx_dy(const Gcalc_coord1 *dx_a,
const Gcalc_coord1 *dy_a,
const Gcalc_coord1 *dx_b,
const Gcalc_coord1 *dy_b);
static int cmp_dx_dy(const Gcalc_heap::Info *p1,
const Gcalc_heap::Info *p2,
const Gcalc_heap::Info *p3,
const Gcalc_heap::Info *p4);
int cmp_dx_dy(const point *p) const; int cmp_dx_dy(const point *p) const;
int simple_event() const int simple_event() const
{ {
...@@ -298,6 +397,9 @@ public: ...@@ -298,6 +397,9 @@ public:
#ifndef DBUG_OFF #ifndef DBUG_OFF
void dbug_print(); void dbug_print();
#endif /*DBUG_OFF*/ #endif /*DBUG_OFF*/
#ifdef GCALC_CHECK_WITH_FLOAT
void calc_x(long double *x, long double y, long double ix) const;
#endif /*GCALC_CHECK_WITH_FLOAT*/
}; };
class intersection : public Gcalc_dyn_list::Item class intersection : public Gcalc_dyn_list::Item
...@@ -306,8 +408,11 @@ public: ...@@ -306,8 +408,11 @@ public:
int n_row; int n_row;
sc_thread_id thread_a; sc_thread_id thread_a;
sc_thread_id thread_b; sc_thread_id thread_b;
#ifdef TMP_BLOCK
double x; double x;
double y; double y;
#endif /*TMP_BLOCK*/
const Gcalc_heap::Intersection_info *ii;
inline intersection *get_next() { return (intersection *)next; } inline intersection *get_next() { return (intersection *)next; }
}; };
...@@ -318,7 +423,15 @@ public: ...@@ -318,7 +423,15 @@ public:
point *event_position; point *event_position;
Gcalc_dyn_list::Item **event_position_hook; Gcalc_dyn_list::Item **event_position_hook;
Gcalc_dyn_list::Item **event_end_hook; Gcalc_dyn_list::Item **event_end_hook;
int intersection_scan;
union
{
const Gcalc_heap::Info *pi;
const Gcalc_heap::Intersection_info *isc;
};
#ifdef TMP_BLOCK
double y; double y;
#endif /*TMP_BLOCK*/
slice_state() : slice(NULL) {} slice_state() : slice(NULL) {}
void clear_event_position() void clear_event_position()
{ {
...@@ -350,10 +463,24 @@ public: ...@@ -350,10 +463,24 @@ public:
{ return (point *) *current_state->event_end_hook; } { return (point *) *current_state->event_end_hook; }
inline const point *get_b_slice() const { return current_state->slice; } inline const point *get_b_slice() const { return current_state->slice; }
inline const point *get_t_slice() const { return next_state->slice; } inline const point *get_t_slice() const { return next_state->slice; }
inline double get_h() const { return current_state->y - next_state->y; } double get_h() const;
inline double get_y() const { return current_state->y; } double get_y() const;
double get_event_x() const;
double get_sp_x(const point *sp) const;
int intersection_step() const { return current_state->intersection_scan; }
const Gcalc_heap::Info *get_cur_pi() const
{
DBUG_ASSERT(!intersection_step());
return current_state->pi;
}
const Gcalc_heap::Intersection_info *get_cur_ii() const
{
DBUG_ASSERT(intersection_step());
return current_state->isc;
}
private: private:
Gcalc_heap *m_heap;
Gcalc_heap::Info *m_cur_pi; Gcalc_heap::Info *m_cur_pi;
slice_state state0, state1, state_s; slice_state state0, state1, state_s;
slice_state *current_state; slice_state *current_state;
...@@ -382,7 +509,10 @@ private: ...@@ -382,7 +509,10 @@ private:
} }
point *new_slice_point() point *new_slice_point()
{ {
return (point *)new_item(); point *new_point= (point *)new_item();
new_point->dx.init();
new_point->dy.init();
return new_point;
} }
point *new_slice(point *example); point *new_slice(point *example);
int arrange_event(); int arrange_event();
...@@ -450,7 +580,6 @@ public: ...@@ -450,7 +580,6 @@ public:
inline const Gcalc_scan_iterator::point *point() const { return sp; } inline const Gcalc_scan_iterator::point *point() const { return sp; }
inline const Gcalc_heap::Info *get_pi() const { return sp->pi; } inline const Gcalc_heap::Info *get_pi() const { return sp->pi; }
inline gcalc_shape_info get_shape() const { return sp->get_shape(); } inline gcalc_shape_info get_shape() const { return sp->get_shape(); }
inline double get_x() const { return sp->x; }
inline void restart(const Gcalc_scan_iterator *scan_i) inline void restart(const Gcalc_scan_iterator *scan_i)
{ sp= scan_i->get_b_slice(); } { sp= scan_i->get_b_slice(); }
}; };
......
...@@ -347,6 +347,10 @@ int Gcalc_result_receiver::add_point(double x, double y) ...@@ -347,6 +347,10 @@ int Gcalc_result_receiver::add_point(double x, double y)
buffer.q_append(prev_y); buffer.q_append(prev_y);
prev_x= x; prev_x= x;
prev_y= y; prev_y= y;
#ifndef NO_TESTING
if (n_points == 53)
printf("xxx\n");
#endif /*NO_TESTING*/
return 0; return 0;
} }
...@@ -488,6 +492,9 @@ int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_positio ...@@ -488,6 +492,9 @@ int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_positio
Gcalc_operation_reducer::Gcalc_operation_reducer(size_t blk_size) : Gcalc_operation_reducer::Gcalc_operation_reducer(size_t blk_size) :
Gcalc_dyn_list(blk_size, sizeof(res_point)), Gcalc_dyn_list(blk_size, sizeof(res_point)),
#ifndef DBUG_OFF
n_res_points(0),
#endif /*DBUG_OFF*/
m_res_hook((Gcalc_dyn_list::Item **)&m_result), m_res_hook((Gcalc_dyn_list::Item **)&m_result),
m_first_active_thread(NULL) m_first_active_thread(NULL)
{} {}
...@@ -514,9 +521,73 @@ Gcalc_operation_reducer(Gcalc_function *fn, modes mode, size_t blk_size) : ...@@ -514,9 +521,73 @@ Gcalc_operation_reducer(Gcalc_function *fn, modes mode, size_t blk_size) :
} }
inline int Gcalc_operation_reducer::continue_range(active_thread *t, void Gcalc_operation_reducer::res_point::set(const Gcalc_scan_iterator *si)
{
if ((intersection_point= si->intersection_step()))
ii= si->get_cur_ii();
else
pi= si->get_cur_pi();
}
#ifndef NO_TESTING
void call_checkpoint(int d)
{
printf("%d\n", d);
}
#endif /*NO_TESTING*/
Gcalc_operation_reducer::res_point *
Gcalc_operation_reducer::add_res_point(Gcalc_function::shape_type type)
{
res_point *result= (res_point *)new_item();
*m_res_hook= result;
result->prev_hook= m_res_hook;
m_res_hook= &result->next;
result->type= type;
#ifndef DBUG_OFF
result->point_n= n_res_points++;
#endif /*DBUG_OFF*/
#ifndef NO_TESTING
if (result->point_n == 74)
call_checkpoint(74);
#endif /*NO_TESTING*/
return result;
}
int Gcalc_operation_reducer::add_line(int incoming, active_thread *t,
const Gcalc_scan_iterator::point *p)
{
line *l= new_line();
if (!l)
return 1;
l->incoming= incoming;
l->t= t;
l->p= p;
*m_lines_hook= l;
m_lines_hook= &l->next;
return 0;
}
int Gcalc_operation_reducer::add_poly_border(int incoming,
active_thread *t, int prev_state, const Gcalc_scan_iterator::point *p)
{
poly_border *b= new_poly_border();
if (!b)
return 1;
b->incoming= incoming;
b->t= t;
b->prev_state= prev_state;
b->p= p;
*m_poly_borders_hook= b;
m_poly_borders_hook= &b->next;
return 0;
}
int Gcalc_operation_reducer::continue_range(active_thread *t,
const Gcalc_heap::Info *p, const Gcalc_heap::Info *p,
int horiz_dir, double dx_dy) const Gcalc_heap::Info *p_next)
{ {
res_point *rp= add_res_point(t->rp->type); res_point *rp= add_res_point(t->rp->type);
if (!rp) if (!rp)
...@@ -527,15 +598,14 @@ inline int Gcalc_operation_reducer::continue_range(active_thread *t, ...@@ -527,15 +598,14 @@ inline int Gcalc_operation_reducer::continue_range(active_thread *t,
rp->intersection_point= false; rp->intersection_point= false;
rp->pi= p; rp->pi= p;
t->rp= rp; t->rp= rp;
t->horiz_dir= horiz_dir; t->p1= p;
t->dx_dy= dx_dy; t->p2= p_next;
return 0; return 0;
} }
inline int Gcalc_operation_reducer::continue_i_range(active_thread *t, inline int Gcalc_operation_reducer::continue_i_range(active_thread *t,
double x, double y, const Gcalc_heap::Intersection_info *ii)
int horiz_dir, double dx_dy)
{ {
res_point *rp= add_res_point(t->rp->type); res_point *rp= add_res_point(t->rp->type);
if (!rp) if (!rp)
...@@ -544,11 +614,8 @@ inline int Gcalc_operation_reducer::continue_i_range(active_thread *t, ...@@ -544,11 +614,8 @@ inline int Gcalc_operation_reducer::continue_i_range(active_thread *t,
rp->down= t->rp; rp->down= t->rp;
t->rp->up= rp; t->rp->up= rp;
rp->intersection_point= true; rp->intersection_point= true;
rp->x= x; rp->ii= ii;
rp->y= y;
t->rp= rp; t->rp= rp;
t->horiz_dir= horiz_dir;
t->dx_dy= dx_dy;
return 0; return 0;
} }
...@@ -573,6 +640,9 @@ int Gcalc_operation_reducer::end_couple(active_thread *t0, active_thread *t1, ...@@ -573,6 +640,9 @@ int Gcalc_operation_reducer::end_couple(active_thread *t0, active_thread *t1,
} }
#ifndef NO_TESTING
int ca_counter= 0;
#endif /*NO_TESTING*/
int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
{ {
Gcalc_point_iterator pi(si); Gcalc_point_iterator pi(si);
...@@ -587,8 +657,16 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -587,8 +657,16 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
active_thread *bottom_threads= NULL; active_thread *bottom_threads= NULL;
active_thread *eq_thread, *point_thread;; active_thread *eq_thread, *point_thread;;
#ifndef NO_TESTING
if (ca_counter == 11522)
call_checkpoint(89);
#endif /*NO_TESTING*/
m_fn->clear_state(); m_fn->clear_state();
/* Walk to the event, remembering what is needed. */ /* Walk to the event, remembering what is needed. */
#ifndef NO_TESTING
if (si->get_event_position() == pi.point())
printf("yyy\n");
#endif /*NO_TESTING*/
for (; pi.point() != si->get_event_position(); for (; pi.point() != si->get_event_position();
++pi, cur_t_hook= (active_thread **) &(*cur_t_hook)->next) ++pi, cur_t_hook= (active_thread **) &(*cur_t_hook)->next)
{ {
...@@ -612,13 +690,13 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -612,13 +690,13 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
case scev_point: case scev_point:
{ {
if (cur_t->enabled() && if (cur_t->enabled() &&
continue_range(cur_t, events->pi, events->horiz_dir, events->dx_dy)) continue_range(cur_t, events->pi, events->next_pi))
return 1; return 1;
break; break;
} }
case scev_end: case scev_end:
{ {
if (cur_t->enabled() && end_line(cur_t, events->pi, si)) if (cur_t->enabled() && end_line(cur_t, si))
return 1; return 1;
*cur_t_hook= cur_t->get_next(); *cur_t_hook= cur_t->get_next();
free_item(cur_t); free_item(cur_t);
...@@ -635,8 +713,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -635,8 +713,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
else if (cur_t->enabled() || cur_t->get_next()->enabled()) else if (cur_t->enabled() || cur_t->get_next()->enabled())
{ {
/* Rare case when edges of a polygon coincide */ /* Rare case when edges of a polygon coincide */
if (end_line(cur_t->enabled() ? cur_t : cur_t->get_next(), if (end_line(cur_t->enabled() ? cur_t : cur_t->get_next(), si))
events->pi, si))
return 1; return 1;
} }
*cur_t_hook= cur_t->get_next()->get_next(); *cur_t_hook= cur_t->get_next()->get_next();
...@@ -647,6 +724,9 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -647,6 +724,9 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
#ifndef NO_TESTING
goto testing;
#endif /*NO_TESTING*/
return 0; return 0;
} }
...@@ -773,7 +853,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -773,7 +853,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
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_on_state(events->get_shape());
return m_fn->count() ? add_single_point(event_point, si) : 0; return m_fn->count() ? add_single_point(si) : 0;
} }
if (m_poly_borders) if (m_poly_borders)
...@@ -783,6 +863,10 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -783,6 +863,10 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
{ {
poly_border *pb1, *pb2; poly_border *pb1, *pb2;
pb1= m_poly_borders; pb1= m_poly_borders;
#ifndef NO_TESTING
if (!m_poly_borders->next)
call_checkpoint(3);
#endif /*NO_TESTING*/
DBUG_ASSERT(m_poly_borders->next); DBUG_ASSERT(m_poly_borders->next);
pb2= get_pair_border(pb1); pb2= get_pair_border(pb1);
...@@ -790,8 +874,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -790,8 +874,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
m_poly_borders= pb1->get_next(); m_poly_borders= pb1->get_next();
if (connect_threads(pb1->incoming, pb2->incoming, if (connect_threads(pb1->incoming, pb2->incoming,
pb1->t, pb2->t, pb1->p, pb2->p, pb1->t, pb2->t, pb1->p, pb2->p,
prev_range, event_point, si, prev_range, si, Gcalc_function::shape_polygon))
Gcalc_function::shape_polygon))
return 1; return 1;
free_item(pb1); free_item(pb1);
...@@ -809,8 +892,8 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -809,8 +892,8 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
{ {
if (connect_threads(m_lines->incoming, m_lines->get_next()->incoming, if (connect_threads(m_lines->incoming, m_lines->get_next()->incoming,
m_lines->t, m_lines->get_next()->t, m_lines->t, m_lines->get_next()->t,
m_lines->p, m_lines->get_next()->p, NULL, m_lines->p, m_lines->get_next()->p,
event_point, si, Gcalc_function::shape_line)) NULL, si, Gcalc_function::shape_line))
return 1; return 1;
} }
else else
...@@ -819,11 +902,11 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -819,11 +902,11 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
{ {
if (cur_line->incoming) if (cur_line->incoming)
{ {
if (end_line(cur_line->t, event_point, si)) if (end_line(cur_line->t, si))
return 1; return 1;
} }
else else
start_line(cur_line->t, cur_line->p, event_point, si); start_line(cur_line->t, cur_line->p, si);
} }
} }
free_list(m_lines); free_list(m_lines);
...@@ -834,28 +917,56 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) ...@@ -834,28 +917,56 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
if (bottom_threads) if (bottom_threads)
free_list(bottom_threads); free_list(bottom_threads);
#ifndef NO_TESTING
testing:
{
Gcalc_point_iterator x_pi(si);
active_thread **x_cur_t_hook= &m_first_active_thread;
int x_prev_state= 0;
m_fn->save_states();
m_fn->clear_state();
if (ca_counter == /*11552*/90)
call_checkpoint(10);
for (; x_pi.point(); ++x_pi)
{
active_thread *cur_t= *x_cur_t_hook;
if (cur_t->enabled() &&
cur_t->rp->type == Gcalc_function::shape_polygon)
x_prev_state^= 1;
int ppb= m_fn->count();
if (m_fn->get_shape_kind(x_pi.get_shape()) == Gcalc_function::shape_polygon)
m_fn->invert_state(x_pi.get_shape());
int ppa= m_fn->count();
if (ppa != x_prev_state)
{
if (x_pi.point()->cmp_dx_dy(x_pi.point()->get_next()) != 0)
call_checkpoint(21);
}
if (cur_t->enabled())
{
if (m_fn->get_shape_kind(x_pi.get_shape()) == Gcalc_function::shape_polygon)
if (ppa == ppb)
call_checkpoint(22);
else
if (ppa != 0 && ppb != 0)
call_checkpoint(23);
}
x_cur_t_hook= (active_thread **) &(*x_cur_t_hook)->next;
}
m_fn->restore_states();
}
#endif /*NO_TESTING*/
return 0; return 0;
} }
int Gcalc_operation_reducer::add_single_point(const Gcalc_heap::Info *p, int Gcalc_operation_reducer::add_single_point(const Gcalc_scan_iterator *si)
const Gcalc_scan_iterator *si)
{ {
res_point *rp= add_res_point(Gcalc_function::shape_point); res_point *rp= add_res_point(Gcalc_function::shape_point);
if (!rp) if (!rp)
return 1; return 1;
rp->glue= rp->up= rp->down= NULL; rp->glue= rp->up= rp->down= NULL;
if (p) rp->set(si);
{
rp->intersection_point= false;
rp->pi= p;
}
else
{
rp->intersection_point= true;
rp->y= si->get_y();
rp->x= si->get_events()->x;
}
return 0; return 0;
} }
...@@ -912,7 +1023,7 @@ int Gcalc_operation_reducer::connect_threads( ...@@ -912,7 +1023,7 @@ int Gcalc_operation_reducer::connect_threads(
int incoming_a, int incoming_b, int incoming_a, int incoming_b,
active_thread *ta, active_thread *tb, active_thread *ta, active_thread *tb,
const Gcalc_scan_iterator::point *pa, const Gcalc_scan_iterator::point *pb, const Gcalc_scan_iterator::point *pa, const Gcalc_scan_iterator::point *pb,
active_thread *prev_range, const Gcalc_heap::Info *ev_p, active_thread *prev_range,
const Gcalc_scan_iterator *si, Gcalc_function::shape_type s_t) const Gcalc_scan_iterator *si, Gcalc_function::shape_type s_t)
{ {
if (incoming_a && incoming_b) if (incoming_a && incoming_b)
...@@ -929,18 +1040,8 @@ int Gcalc_operation_reducer::connect_threads( ...@@ -929,18 +1040,8 @@ int Gcalc_operation_reducer::connect_threads(
rpa->up= rpb->up= NULL; rpa->up= rpb->up= NULL;
ta->rp->up= rpa; ta->rp->up= rpa;
tb->rp->up= rpb; tb->rp->up= rpb;
if (ev_p) rpa->set(si);
{ rpb->set(si);
rpa->intersection_point= rpb->intersection_point= false;
rpa->pi= rpb->pi= ev_p;
}
else
{
rpa->intersection_point= rpb->intersection_point= true;
rpa->x= rpb->x= si->get_events()->x;
rpa->y= rpb->y= si->get_y();
}
ta->rp= tb->rp= NULL; ta->rp= tb->rp= NULL;
return 0; return 0;
} }
...@@ -953,35 +1054,30 @@ int Gcalc_operation_reducer::connect_threads( ...@@ -953,35 +1054,30 @@ int Gcalc_operation_reducer::connect_threads(
return 1; return 1;
rp0->glue= rp1; rp0->glue= rp1;
rp1->glue= rp0; rp1->glue= rp0;
if (ev_p) rp0->set(si);
{ rp1->set(si);
rp0->intersection_point= rp1->intersection_point= false;
rp0->pi= rp1->pi= ev_p;
}
else
{
rp0->intersection_point= rp1->intersection_point= true;
rp0->x= rp1->x= si->get_events()->x;
rp0->y= rp1->y= si->get_y();
}
rp0->down= rp1->down= NULL; rp0->down= rp1->down= NULL;
ta->rp= rp0; ta->rp= rp0;
tb->rp= rp1; tb->rp= rp1;
ta->horiz_dir= pa->horiz_dir; ta->p1= pa->pi;
ta->dx_dy= pa->dx_dy; ta->p2= pa->next_pi;
tb->horiz_dir= pb->horiz_dir; tb->p1= pb->pi;
tb->dx_dy= pb->dx_dy; tb->p2= pb->next_pi;
if (prev_range) if (prev_range)
{ {
rp0->outer_poly= prev_range->thread_start; rp0->outer_poly= prev_range->thread_start;
tb->thread_start= prev_range->thread_start; tb->thread_start= prev_range->thread_start;
/* Chack if needed */
ta->thread_start= prev_range->thread_start;
} }
else else
{ {
rp0->outer_poly= 0; rp0->outer_poly= 0;
ta->thread_start= rp0; ta->thread_start= rp0;
/* Chack if needed */
tb->thread_start= rp0;
} }
return 0; return 0;
} }
...@@ -991,20 +1087,18 @@ int Gcalc_operation_reducer::connect_threads( ...@@ -991,20 +1087,18 @@ int Gcalc_operation_reducer::connect_threads(
tb->rp= ta->rp; tb->rp= ta->rp;
tb->thread_start= ta->thread_start; tb->thread_start= ta->thread_start;
if (Gcalc_scan_iterator::point:: if (Gcalc_scan_iterator::point::
compare_dx_dy(ta->horiz_dir, ta->dx_dy, cmp_dx_dy(ta->p1, ta->p2, pb->pi, pb->next_pi) != 0)
pb->horiz_dir, pb->dx_dy) != 0) {
{ if (si->intersection_step() ?
if (ev_p ? continue_range(tb, ev_p, pb->horiz_dir, pb->dx_dy): continue_i_range(tb, si->get_cur_ii()) :
continue_i_range(tb, continue_range(tb, si->get_cur_pi(), pb->next_pi))
si->get_events()->x, si->get_y(), #ifdef TMP_BLOCK
pb->horiz_dir, pb->dx_dy)) continue_range(tb, si->get_cur_pi())
#endif /*TMP_BLOCK*/
return 1; return 1;
} }
else tb->p1= pb->pi;
{ tb->p2= pb->next_pi;
tb->horiz_dir= pb->horiz_dir;
tb->dx_dy= pb->dx_dy;
}
return 0; return 0;
} }
...@@ -1012,33 +1106,21 @@ int Gcalc_operation_reducer::connect_threads( ...@@ -1012,33 +1106,21 @@ int Gcalc_operation_reducer::connect_threads(
int Gcalc_operation_reducer::start_line(active_thread *t, int Gcalc_operation_reducer::start_line(active_thread *t,
const Gcalc_scan_iterator::point *p, const Gcalc_scan_iterator::point *p,
const Gcalc_heap::Info *ev_p,
const Gcalc_scan_iterator *si) const Gcalc_scan_iterator *si)
{ {
res_point *rp= add_res_point(Gcalc_function::shape_line); res_point *rp= add_res_point(Gcalc_function::shape_line);
if (!rp) if (!rp)
return 1; return 1;
rp->glue= rp->down= NULL; rp->glue= rp->down= NULL;
if (ev_p) rp->set(si);
{
rp->intersection_point= false;
rp->pi= ev_p;
}
else
{
rp->intersection_point= true;
rp->x= si->get_events()->x;
rp->y= si->get_y();
}
t->rp= rp; t->rp= rp;
t->horiz_dir= p->horiz_dir; t->p1= p->pi;
t->dx_dy= p->dx_dy; t->p2= p->next_pi;
return 0; return 0;
} }
int Gcalc_operation_reducer::end_line(active_thread *t, int Gcalc_operation_reducer::end_line(active_thread *t,
const Gcalc_heap::Info *ev_p,
const Gcalc_scan_iterator *si) const Gcalc_scan_iterator *si)
{ {
DBUG_ASSERT(t->rp->type == Gcalc_function::shape_line); DBUG_ASSERT(t->rp->type == Gcalc_function::shape_line);
...@@ -1047,17 +1129,7 @@ int Gcalc_operation_reducer::end_line(active_thread *t, ...@@ -1047,17 +1129,7 @@ int Gcalc_operation_reducer::end_line(active_thread *t,
return 1; return 1;
rp->glue= rp->up= NULL; rp->glue= rp->up= NULL;
rp->down= t->rp; rp->down= t->rp;
if (ev_p) rp->set(si);
{
rp->intersection_point= false;
rp->pi= ev_p;
}
else
{
rp->intersection_point= true;
rp->x= si->get_events()->x;
rp->y= si->get_y();
}
t->rp->up= rp; t->rp->up= rp;
t->rp= NULL; t->rp= NULL;
...@@ -1071,6 +1143,11 @@ int Gcalc_operation_reducer::count_all(Gcalc_heap *hp) ...@@ -1071,6 +1143,11 @@ int Gcalc_operation_reducer::count_all(Gcalc_heap *hp)
si.init(hp); si.init(hp);
while (si.more_points()) while (si.more_points())
{ {
#ifndef NO_TESTING
printf("Point %d\n", ++ca_counter);
if (ca_counter == 12)
call_checkpoint(10);
#endif /*NO_TESTING*/
if (si.step()) if (si.step())
return 1; return 1;
if (count_slice(&si)) if (count_slice(&si))
...@@ -1094,8 +1171,9 @@ inline int Gcalc_operation_reducer::get_single_result(res_point *res, ...@@ -1094,8 +1171,9 @@ inline int Gcalc_operation_reducer::get_single_result(res_point *res,
{ {
if (res->intersection_point) if (res->intersection_point)
{ {
if (storage->single_point(float_to_coord(res->x), double x, y;
float_to_coord(res->y))) res->ii->calc_xy(&x, &y);
if (storage->single_point(x,y))
return 1; return 1;
} }
else else
...@@ -1105,6 +1183,9 @@ inline int Gcalc_operation_reducer::get_single_result(res_point *res, ...@@ -1105,6 +1183,9 @@ inline int Gcalc_operation_reducer::get_single_result(res_point *res,
return 0; return 0;
} }
#ifndef NO_TESTING
int pc_counter= 0;
#endif /*NO_TESTING*/
int Gcalc_operation_reducer::get_result_thread(res_point *cur, int Gcalc_operation_reducer::get_result_thread(res_point *cur,
Gcalc_result_receiver *storage, Gcalc_result_receiver *storage,
...@@ -1116,12 +1197,16 @@ int Gcalc_operation_reducer::get_result_thread(res_point *cur, ...@@ -1116,12 +1197,16 @@ int Gcalc_operation_reducer::get_result_thread(res_point *cur,
double x, y; double x, y;
while (cur) while (cur)
{ {
#ifndef NO_TESTING
++pc_counter;
if (pc_counter == 79)
call_checkpoint(79);
#endif /*NO_TESTING*/
if (!glue_step) if (!glue_step)
{ {
if (cur->intersection_point) if (cur->intersection_point)
{ {
x= float_to_coord(cur->x); cur->ii->calc_xy(&x, &y);
y= float_to_coord(cur->y);
} }
else else
{ {
......
...@@ -206,26 +206,37 @@ public: ...@@ -206,26 +206,37 @@ public:
int get_result(Gcalc_result_receiver *storage); int get_result(Gcalc_result_receiver *storage);
void reset(); void reset();
#ifndef DBUG_OFF
int n_res_points;
#endif /*DBUG_OFF*/
class res_point : public Gcalc_dyn_list::Item class res_point : public Gcalc_dyn_list::Item
{ {
public: public:
bool intersection_point; int intersection_point;
double x,y;
res_point *up;
res_point *down;
res_point *glue;
Gcalc_function::shape_type type;
union union
{ {
const Gcalc_heap::Info *pi; const Gcalc_heap::Info *pi;
const Gcalc_heap::Intersection_info *ii;
res_point *first_poly_node; res_point *first_poly_node;
}; };
#ifdef TMP_BLOCK
union union
{ {
#endif /*TMP_BLOCK*/
res_point *outer_poly; res_point *outer_poly;
uint32 poly_position; uint32 poly_position;
#ifdef TMP_BLOCK
}; };
#endif /*TMP_BLOCK*/
res_point *up;
res_point *down;
res_point *glue;
Gcalc_function::shape_type type;
Gcalc_dyn_list::Item **prev_hook; Gcalc_dyn_list::Item **prev_hook;
#ifndef DBUG_OFF
int point_n;
#endif /*DBUG_OFF*/
void set(const Gcalc_scan_iterator *si);
res_point *get_next() { return (res_point *)next; } res_point *get_next() { return (res_point *)next; }
}; };
...@@ -233,9 +244,9 @@ public: ...@@ -233,9 +244,9 @@ public:
{ {
public: public:
res_point *rp; res_point *rp;
int horiz_dir;
double dx_dy;
res_point *thread_start; res_point *thread_start;
const Gcalc_heap::Info *p1, *p2;
res_point *enabled() { return rp; } res_point *enabled() { return rp; }
active_thread *get_next() { return (active_thread *)next; } active_thread *get_next() { return (active_thread *)next; }
}; };
...@@ -273,33 +284,9 @@ public: ...@@ -273,33 +284,9 @@ public:
line *new_line() { return (line *) new_item(); } line *new_line() { return (line *) new_item(); }
poly_border *new_poly_border() { return (poly_border *) new_item(); } poly_border *new_poly_border() { return (poly_border *) new_item(); }
int add_line(int incoming, active_thread *t, int add_line(int incoming, active_thread *t,
const Gcalc_scan_iterator::point *p) const Gcalc_scan_iterator::point *p);
{
line *l= new_line();
if (!l)
return 1;
l->incoming= incoming;
l->t= t;
l->p= p;
*m_lines_hook= l;
m_lines_hook= &l->next;
return 0;
}
int add_poly_border(int incoming, active_thread *t, int prev_state, int add_poly_border(int incoming, active_thread *t, int prev_state,
const Gcalc_scan_iterator::point *p) const Gcalc_scan_iterator::point *p);
{
poly_border *b= new_poly_border();
if (!b)
return 1;
b->incoming= incoming;
b->t= t;
b->prev_state= prev_state;
b->p= p;
*m_poly_borders_hook= b;
m_poly_borders_hook= &b->next;
return 0;
}
protected: protected:
Gcalc_function *m_fn; Gcalc_function *m_fn;
...@@ -310,43 +297,29 @@ protected: ...@@ -310,43 +297,29 @@ protected:
res_point *result_heap; res_point *result_heap;
active_thread *m_first_active_thread; active_thread *m_first_active_thread;
res_point *add_res_point(Gcalc_function::shape_type type) res_point *add_res_point(Gcalc_function::shape_type type);
{
res_point *result= (res_point *)new_item();
*m_res_hook= result;
result->prev_hook= m_res_hook;
m_res_hook= &result->next;
result->type= type;
return result;
}
active_thread *new_active_thread() { return (active_thread *)new_item(); } active_thread *new_active_thread() { return (active_thread *)new_item(); }
poly_instance *new_poly() { return (poly_instance *) new_item(); } poly_instance *new_poly() { return (poly_instance *) new_item(); }
private: private:
int start_line(active_thread *t, const Gcalc_scan_iterator::point *p, int start_line(active_thread *t, const Gcalc_scan_iterator::point *p,
const Gcalc_heap::Info *ev_p, const Gcalc_scan_iterator *si);
int end_line(active_thread *t, const Gcalc_heap::Info *ev_p,
const Gcalc_scan_iterator *si); const Gcalc_scan_iterator *si);
int end_line(active_thread *t, const Gcalc_scan_iterator *si);
int connect_threads(int incoming_a, int incoming_b, int connect_threads(int incoming_a, int incoming_b,
active_thread *ta, active_thread *tb, active_thread *ta, active_thread *tb,
const Gcalc_scan_iterator::point *pa, const Gcalc_scan_iterator::point *pa,
const Gcalc_scan_iterator::point *pb, const Gcalc_scan_iterator::point *pb,
active_thread *prev_range, active_thread *prev_range,
const Gcalc_heap::Info *ev_p,
const Gcalc_scan_iterator *si, const Gcalc_scan_iterator *si,
Gcalc_function::shape_type s_t); Gcalc_function::shape_type s_t);
int add_single_point(const Gcalc_heap::Info *p, int add_single_point(const Gcalc_scan_iterator *si);
const Gcalc_scan_iterator *si);
poly_border *get_pair_border(poly_border *b1); poly_border *get_pair_border(poly_border *b1);
int continue_range(active_thread *t, const Gcalc_heap::Info *p, int continue_range(active_thread *t, const Gcalc_heap::Info *p,
int horiz_dir, double dx_dy); const Gcalc_heap::Info *p_next);
int continue_i_range(active_thread *t, double x, double y, int continue_i_range(active_thread *t,
int horiz_dir, double dx_dy); const Gcalc_heap::Intersection_info *ii);
int end_couple(active_thread *t0, active_thread *t1, const Gcalc_heap::Info *p); int end_couple(active_thread *t0, active_thread *t1, const Gcalc_heap::Info *p);
int add_single_point(const Gcalc_heap::Info *p);
int get_single_result(res_point *res, Gcalc_result_receiver *storage); int get_single_result(res_point *res, Gcalc_result_receiver *storage);
int get_result_thread(res_point *cur, Gcalc_result_receiver *storage, int get_result_thread(res_point *cur, Gcalc_result_receiver *storage,
int move_upward, res_point *first_poly_node); int move_upward, res_point *first_poly_node);
......
...@@ -867,7 +867,8 @@ int Item_func_spatial_rel::func_touches() ...@@ -867,7 +867,8 @@ int Item_func_spatial_rel::func_touches()
if (cur_func) if (cur_func)
{ {
area= scan_it.get_h() * area= scan_it.get_h() *
((ti.rb()->x - ti.lb()->x) + (ti.rt()->x - ti.lt()->x)); ((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) if (area > GIS_ZERO)
{ {
result= 0; result= 0;
......
...@@ -2230,6 +2230,8 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const ...@@ -2230,6 +2230,8 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
return 1; return 1;
n_objects= uint4korr(data); n_objects= uint4korr(data);
data+= 4; data+= 4;
if (n_objects == 0)
return 1;
while (n_objects--) while (n_objects--)
{ {
......
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