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

fixed bugs

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

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

per-file comments:
  mysql-test/r/gis-precise.result
        GIS bugs fixed.
        test result updated.
  mysql-test/t/gis-precise.test
        GIS bugs fixed.
        test cases added.
  sql/gcalc_slicescan.h
        GIS bugs fixed.
  sql/gcalc_tools.cc
        GIS bugs fixed.
  sql/gcalc_tools.h
        GIS bugs fixed.
  sql/item_create.cc
        GIS bugs fixed.
  sql/item_geofunc.cc
        GIS bugs fixed.
  sql/item_geofunc.h
        GIS bugs fixed.
  sql/spatial.cc
        GIS bugs fixed.
parent d0f2e1e5
This diff is collapsed.
...@@ -237,14 +237,6 @@ SELECT ST_NUMGEOMETRIES(ST_DIFFERENCE ( ...@@ -237,14 +237,6 @@ SELECT ST_NUMGEOMETRIES(ST_DIFFERENCE (
)); ));
#bug 841638 Assertion `!m_prev || m_prev->x != x || m_prev->y != y' failed in Gcalc_shape_transporter::int_add_point in maria-5.3-gis
SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER (
ST_UNION (
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 7 3 , 1 8 , 4 0 , 7 9 ) , ( 5 4 , 9 8 , 7 4 , 3 7 ) , ( 5 8 , 5 4 , 9 2 , 5 6 ) , ( 4 0 , 3 2 , 0 1 , 3 9 ) , ( 2 0 , 3 5 , 9 5 , 0 9 ) ) ' ) ,
MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 4 5 , 3 0 , 3 1 , 4 7 , 4 2 ) , ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' )
) , 1
)));
#bug 841745 ssertion `!sp0->is_bottom()' failed in Gcalc_scan_iterator::find_intersections in maria-5.3-gis #bug 841745 ssertion `!sp0->is_bottom()' failed in Gcalc_scan_iterator::find_intersections in maria-5.3-gis
SELECT ASTEXT(ST_DIFFERENCE ( SELECT ASTEXT(ST_DIFFERENCE (
POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) , POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) ,
...@@ -279,10 +271,30 @@ SELECT ST_BUFFER ( ...@@ -279,10 +271,30 @@ SELECT ST_BUFFER (
) ; ) ;
SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ; SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ;
#bug 848901 Assertion `fabs(cur_isc->x-m_cur_intersection->x) + fabs(cur_isc->y-m_cur_intersection->y) < 0.000000000001' failed in Gcalc_scan_iterator::intersection_scan() in maria-5.3-gis
SELECT ST_NUMGEOMETRIES( ST_SYMDIFFERENCE ( ST_SYMDIFFERENCE ( ST_INTERSECTION ( MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 6 4 , 3 7 , 9 4 , 3 8 ) , ( 2 2 , 2 9 , 1 2 , 9 8 ) ) ' ) , ST_SYMDIFFERENCE ( MULTIPOINTFROMTEXT( ' MULTIPOINT( 6 1 , 3 8 , 3 3 , 0 6 , 7 2 , 3 4 ) ' ) , ST_BUFFER ( ST_UNION ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 6 2 , 1 3 , 2 2 , 2 2 ) ) ) ' ) , GEOMETRYFROMTEXT( ' MULTILINESTRING( ( 1 4 , 9 9 , 3 0 , 6 6 ) , ( 3 5 , 1 0 , 5 8 , 6 1 ) , ( 8 9 , 6 1 , 5 1 , 6 2 ) , ( 2 2 , 7 5 , 5 8 , 6 9 , 3 0 ) , ( 8 0 , 8 4 , 6 7 , 5 5 ) ) ' ) ) , NUMPOINTS( EXTERIORRING( POLYGONFROMTEXT( ' POLYGON( ( 0 0 , 2 1 , 8 2 , 0 0 ) ) ' ) ) ) ) ) ) , ST_INTERSECTION ( POLYGONFROMTEXT( ' POLYGON( ( 2 3, 5 7 , 3 7 , 4 1 , 0 5, 2 3 ) ) ' ) , MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 3 , 1 4 , 6 4 , 9 1 , 3 4 , 1 8 ) , ( 9 9 , 0 3 , 1 7 , 9 9 ) ) ' ) ) ) , POLYGONFROMTEXT( ' POLYGON( ( 1 3, 7 2 , 1 5 , 3 8 , 5 0, 1 3) ) ' ) ) ) ;
#bug 848939 Wrong result with ST_INTERSECTION between linestrings and a polygon in 5.3-gis #bug 848939 Wrong result with ST_INTERSECTION between linestrings and a polygon in 5.3-gis
SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') )); SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') ));
#bug 855485 ST_CROSSES returns different result than PostGIS for overlapping polygons
SELECT ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) '));
#bug 855487 ST_WITHIN returns wrong result for partially overlapping polygons
SELECT ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') );
#bug 855492 ST_WITHIN returns TRUE on point on the edge of a polygon
SELECT ST_WITHIN( POINTFROMTEXT(' POINT(1 2 ) ') , MULTIPOLYGONFROMTEXT(' MULTIPOLYGON( ( (0 5, 3 5, 3 0, 0 0, 0 5), ( 1 1 , 2 1 , 2 4, 1 4, 1 1 ) ) ) '));
#bug 855497 ST_ENVELOPE of GEOMETRYCOLLECTION EMPTY returns NULL and not GEOMETRYCOLLECTION EMPTY
select ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY')));
#bug 855503 ST_EQUALS reports TRUE between a POLYGON and a MULTILINESTRING
SELECT ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') );
#bug 855505 ST_TOUCHES reports TRUE for intersecting polygon and linestring
SELECT ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') );
...@@ -307,6 +307,7 @@ public: ...@@ -307,6 +307,7 @@ public:
virtual int complete_ring()=0; virtual int complete_ring()=0;
virtual int add_point(double x, double y)=0; virtual int add_point(double x, double y)=0;
virtual int start_collection(int n_objects) { return 0; } virtual int start_collection(int n_objects) { return 0; }
virtual int empty_shape() { return 0; }
int start_simple_poly() int start_simple_poly()
{ {
return start_poly() || start_ring(); return start_poly() || start_ring();
......
This diff is collapsed.
...@@ -43,23 +43,35 @@ class Gcalc_function ...@@ -43,23 +43,35 @@ class Gcalc_function
private: private:
String shapes_buffer; String shapes_buffer;
String function_buffer; String function_buffer;
const char *cur_func;
int *i_states; int *i_states;
int *saved_i_states; int *b_states;
uint32 cur_object_id; uint32 cur_object_id;
uint n_shapes; uint n_shapes;
int count_internal(); int count_internal(const char *cur_func, uint set_type,
const char **end);
public: public:
enum value
{
v_empty= 0x0000000,
v_find_t= 0x1000000,
v_find_f= 0x2000000,
v_t_found= 0x3000000,
v_f_found= 0x4000000,
v_mask= 0x7000000
};
enum op_type enum op_type
{ {
op_shape= 0,
op_not= 0x80000000, op_not= 0x80000000,
op_shape= 0x00000000,
op_union= 0x10000000, op_union= 0x10000000,
op_intersection= 0x20000000, op_intersection= 0x20000000,
op_symdifference= 0x30000000, op_symdifference= 0x30000000,
op_difference= 0x40000000, op_difference= 0x40000000,
op_backdifference= 0x50000000, op_repeat= 0x50000000,
op_any= 0x70000000 op_border= 0x60000000,
op_internals= 0x70000000,
op_false= 0x08000000,
op_any= 0x78000000 /* The mask to get any of the operations */
}; };
enum shape_type enum shape_type
{ {
...@@ -75,10 +87,11 @@ public: ...@@ -75,10 +87,11 @@ public:
Also adds the shape to the list of operands. Also adds the shape to the list of operands.
*/ */
int single_shape_op(shape_type shape_kind, gcalc_shape_info *si); int single_shape_op(shape_type shape_kind, gcalc_shape_info *si);
void add_operation(op_type operation, uint32 n_operands); void add_operation(uint operation, uint32 n_operands);
void add_not_operation(op_type operation, uint32 n_operands); void add_not_operation(op_type operation, uint32 n_operands);
uint32 get_next_operation_pos() { return function_buffer.length(); } uint32 get_next_expression_pos() { return function_buffer.length(); }
void add_operands_to_op(uint32 operation_pos, uint32 n_operands); void add_operands_to_op(uint32 operation_pos, uint32 n_operands);
int repeat_expression(uint32 exp_pos);
void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; } void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; }
int reserve_shape_buffer(uint n_shapes); int reserve_shape_buffer(uint n_shapes);
int reserve_op_buffer(uint n_ops); int reserve_op_buffer(uint n_ops);
...@@ -90,20 +103,20 @@ public: ...@@ -90,20 +103,20 @@ public:
void set_states(int *shape_states) { i_states= shape_states; } void set_states(int *shape_states) { i_states= shape_states; }
int alloc_states(); int alloc_states();
void invert_state(gcalc_shape_info shape) { i_states[shape]^= 1; } void invert_i_state(gcalc_shape_info shape) { i_states[shape]^= 1; }
void set_on_state(gcalc_shape_info shape) { i_states[shape]= 1; } void set_b_state(gcalc_shape_info shape) { b_states[shape]= 1; }
int get_state(gcalc_shape_info shape) { return i_states[shape]; } void clear_b_state(gcalc_shape_info shape) { b_states[shape]= 0; }
void save_states(); int get_state(gcalc_shape_info shape)
void restore_states(); { return i_states[shape] | b_states[shape]; }
int get_i_state(gcalc_shape_info shape) { return i_states[shape]; }
int get_b_state(gcalc_shape_info shape) { return b_states[shape]; }
int count() int count()
{ { return count_internal(function_buffer.ptr(), 0, 0); }
cur_func= function_buffer.ptr(); void clear_i_states();
return count_internal(); void clear_b_states();
}
void clear_state() { bzero(i_states, n_shapes * sizeof(int)); }
void reset(); void reset();
int find_function(Gcalc_scan_iterator &scan_it); int check_function(Gcalc_scan_iterator &scan_it);
}; };
...@@ -132,6 +145,7 @@ public: ...@@ -132,6 +145,7 @@ public:
int complete_ring(); int complete_ring();
int add_point(double x, double y); int add_point(double x, double y);
int start_collection(int n_objects); int start_collection(int n_objects);
int empty_shape();
}; };
......
...@@ -5144,7 +5144,7 @@ static Native_func_registry func_array[] = ...@@ -5144,7 +5144,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("ENCRYPT") }, BUILDER(Create_func_encrypt)}, { { C_STRING_WITH_LEN("ENCRYPT") }, BUILDER(Create_func_encrypt)},
{ { C_STRING_WITH_LEN("ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)}, { { C_STRING_WITH_LEN("ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
{ { C_STRING_WITH_LEN("ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)}, { { C_STRING_WITH_LEN("ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)},
{ { C_STRING_WITH_LEN("EQUALS") }, GEOM_BUILDER(Create_func_mbr_equals)}, { { C_STRING_WITH_LEN("EQUALS") }, GEOM_BUILDER(Create_func_equals)},
{ { C_STRING_WITH_LEN("EXP") }, BUILDER(Create_func_exp)}, { { C_STRING_WITH_LEN("EXP") }, BUILDER(Create_func_exp)},
{ { C_STRING_WITH_LEN("EXPORT_SET") }, BUILDER(Create_func_export_set)}, { { C_STRING_WITH_LEN("EXPORT_SET") }, BUILDER(Create_func_export_set)},
{ { C_STRING_WITH_LEN("EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)}, { { C_STRING_WITH_LEN("EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
...@@ -5283,7 +5283,7 @@ static Native_func_registry func_array[] = ...@@ -5283,7 +5283,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("ST_DISTANCE") }, GEOM_BUILDER(Create_func_distance)}, { { C_STRING_WITH_LEN("ST_DISTANCE") }, GEOM_BUILDER(Create_func_distance)},
{ { C_STRING_WITH_LEN("ST_ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)}, { { C_STRING_WITH_LEN("ST_ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
{ { C_STRING_WITH_LEN("ST_ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)}, { { C_STRING_WITH_LEN("ST_ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)},
{ { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_mbr_equals)}, { { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_equals)},
{ { C_STRING_WITH_LEN("ST_EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)}, { { C_STRING_WITH_LEN("ST_EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
{ { C_STRING_WITH_LEN("ST_GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)}, { { C_STRING_WITH_LEN("ST_GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
{ { C_STRING_WITH_LEN("ST_GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)}, { { C_STRING_WITH_LEN("ST_GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
...@@ -5323,7 +5323,7 @@ static Native_func_registry func_array[] = ...@@ -5323,7 +5323,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("ST_SYMDIFFERENCE") }, GEOM_BUILDER(Create_func_symdifference)}, { { C_STRING_WITH_LEN("ST_SYMDIFFERENCE") }, GEOM_BUILDER(Create_func_symdifference)},
{ { C_STRING_WITH_LEN("ST_TOUCHES") }, GEOM_BUILDER(Create_func_touches)}, { { C_STRING_WITH_LEN("ST_TOUCHES") }, GEOM_BUILDER(Create_func_touches)},
{ { C_STRING_WITH_LEN("ST_UNION") }, GEOM_BUILDER(Create_func_union)}, { { C_STRING_WITH_LEN("ST_UNION") }, GEOM_BUILDER(Create_func_union)},
{ { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_mbr_within)}, { { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_within)},
{ { C_STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)}, { { C_STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)},
{ { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)}, { { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)},
{ { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)}, { { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)},
......
...@@ -660,6 +660,7 @@ static double distance_points(const Gcalc_heap::Info *a, ...@@ -660,6 +660,7 @@ static double distance_points(const Gcalc_heap::Info *a,
Calculates the distance between objects. Calculates the distance between objects.
*/ */
#ifdef TMP_BLOCK
static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si, static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si,
Gcalc_function *func, Gcalc_scan_iterator *scan_it) Gcalc_function *func, Gcalc_scan_iterator *scan_it)
{ {
...@@ -786,139 +787,11 @@ exit: ...@@ -786,139 +787,11 @@ exit:
mem_error: mem_error:
DBUG_RETURN(1); DBUG_RETURN(1);
} }
#endif /*TMP_BLOCK*/
#define GIS_ZERO 0.00000000001 #define GIS_ZERO 0.00000000001
int Item_func_spatial_rel::func_touches()
{
bool above_cur_point;
double x1, x2, y1, y2, ex, ey;
double distance, area;
int result= 0;
int cur_func= 0;
Gcalc_operation_transporter trn(&func, &collector);
String *res1= args[0]->val_str(&tmp_value1);
String *res2= args[1]->val_str(&tmp_value2);
Geometry_buffer buffer1, buffer2;
Geometry *g1, *g2;
int obj2_si;
DBUG_ENTER("Item_func_spatial_rel::func_touches");
DBUG_ASSERT(fixed == 1);
if ((null_value= (args[0]->null_value || args[1]->null_value ||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())))))
goto mem_error;
if ((g1->get_class_info()->m_type_id == Geometry::wkb_point) &&
(g2->get_class_info()->m_type_id == Geometry::wkb_point))
{
if (((Gis_point *) g1)->get_xy(&x1, &y1) ||
((Gis_point *) g2)->get_xy(&x2, &y2))
goto mem_error;
ex= x2 - x1;
ey= y2 - y1;
DBUG_RETURN((ex * ex + ey * ey) < GIS_ZERO);
}
if (func.reserve_op_buffer(1))
goto mem_error;
func.add_operation(Gcalc_function::op_intersection, 2);
if (g1->store_shapes(&trn))
goto mem_error;
obj2_si= func.get_nshapes();
if (g2->store_shapes(&trn) || func.alloc_states())
goto mem_error;
collector.prepare_operation();
scan_it.init(&collector);
if (calc_distance(&distance, &collector, obj2_si, &func, &scan_it))
goto mem_error;
if (distance > GIS_ZERO)
goto exit;
scan_it.reset();
scan_it.init(&collector);
above_cur_point= false;
distance= DBL_MAX;
while (scan_it.more_trapezoids())
{
if (scan_it.step())
goto mem_error;
func.clear_state();
for (Gcalc_trapezoid_iterator ti(&scan_it); ti.more(); ++ti)
{
gcalc_shape_info si= ti.lb()->get_shape();
if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon))
{
func.invert_state(si);
cur_func= func.count();
}
if (cur_func)
{
area= scan_it.get_h() *
((scan_it.get_sp_x(ti.rb()) - scan_it.get_sp_x(ti.lb())) +
(scan_it.get_sp_x(ti.rt()) - scan_it.get_sp_x(ti.lt())));
if (area > GIS_ZERO)
{
result= 0;
goto exit;
}
}
}
}
result= 1;
exit:
collector.reset();
func.reset();
scan_it.reset();
DBUG_RETURN(result);
mem_error:
null_value= 1;
DBUG_RETURN(0);
}
int Item_func_spatial_rel::func_equals()
{
Gcalc_heap::Info *pi_s1, *pi_s2;
Gcalc_heap::Info *cur_pi= collector.get_first();
double d;
if (!cur_pi)
return 1;
do {
pi_s1= cur_pi;
pi_s2= 0;
while ((cur_pi= cur_pi->get_next()))
{
d= fabs(pi_s1->x - cur_pi->x) + fabs(pi_s1->y - cur_pi->y);
if (d > GIS_ZERO)
break;
if (!pi_s2 && pi_s1->shape != cur_pi->shape)
pi_s2= cur_pi;
}
if (!pi_s2)
return 0;
} while (cur_pi);
return 1;
}
longlong Item_func_spatial_rel::val_int() longlong Item_func_spatial_rel::val_int()
{ {
DBUG_ENTER("Item_func_spatial_rel::val_int"); DBUG_ENTER("Item_func_spatial_rel::val_int");
...@@ -929,9 +802,7 @@ longlong Item_func_spatial_rel::val_int() ...@@ -929,9 +802,7 @@ longlong Item_func_spatial_rel::val_int()
Geometry *g1, *g2; Geometry *g1, *g2;
int result= 0; int result= 0;
int mask= 0; int mask= 0;
uint shape_a, shape_b;
if (spatial_rel == SP_TOUCHES_FUNC)
DBUG_RETURN(func_touches());
res1= args[0]->val_str(&tmp_value1); res1= args[0]->val_str(&tmp_value1);
res2= args[1]->val_str(&tmp_value2); res2= args[1]->val_str(&tmp_value2);
...@@ -940,56 +811,103 @@ longlong Item_func_spatial_rel::val_int() ...@@ -940,56 +811,103 @@ longlong Item_func_spatial_rel::val_int()
if (func.reserve_op_buffer(1)) if (func.reserve_op_buffer(1))
DBUG_RETURN(0); DBUG_RETURN(0);
if ((null_value=
(args[0]->null_value || args[1]->null_value ||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())))))
goto exit;
switch (spatial_rel) { switch (spatial_rel) {
case SP_CONTAINS_FUNC: case SP_CONTAINS_FUNC:
mask= 1; mask= 1;
func.add_operation(Gcalc_function::op_backdifference, 2); func.add_operation(Gcalc_function::op_difference, 2);
/* Mind the g2 goes first. */
null_value= g2->store_shapes(&trn) || g1->store_shapes(&trn);
break; break;
case SP_WITHIN_FUNC: case SP_WITHIN_FUNC:
mask= 1; mask= 1;
func.add_operation(Gcalc_function::op_difference, 2); func.add_operation(Gcalc_function::op_difference, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break; break;
case SP_EQUALS_FUNC: case SP_EQUALS_FUNC:
mask= 1;
func.add_operation(Gcalc_function::op_symdifference, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break; break;
case SP_DISJOINT_FUNC: case SP_DISJOINT_FUNC:
mask= 1; mask= 1;
func.add_operation(Gcalc_function::op_intersection, 2); func.add_operation(Gcalc_function::op_intersection, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break; break;
case SP_INTERSECTS_FUNC: case SP_INTERSECTS_FUNC:
func.add_operation(Gcalc_function::op_intersection, 2); func.add_operation(Gcalc_function::op_intersection, 2);
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
break; break;
case SP_OVERLAPS_FUNC: case SP_OVERLAPS_FUNC:
func.add_operation(Gcalc_function::op_backdifference, 2);
break;
case SP_CROSSES_FUNC: case SP_CROSSES_FUNC:
func.add_operation(Gcalc_function::op_intersection, 2); func.add_operation(Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_intersection, 2);
shape_a= func.get_next_expression_pos();
if ((null_value= g1->store_shapes(&trn)))
break;
shape_b= func.get_next_expression_pos();
if ((null_value= g2->store_shapes(&trn)))
break;
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_difference, 2);
func.repeat_expression(shape_a);
func.repeat_expression(shape_b);
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_difference, 2);
func.repeat_expression(shape_b);
func.repeat_expression(shape_a);
break;
case SP_TOUCHES_FUNC:
func.add_operation(Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::v_find_f |
Gcalc_function::op_not |
Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::op_internals, 1);
shape_a= func.get_next_expression_pos();
if ((null_value= g1->store_shapes(&trn)))
break;
func.add_operation(Gcalc_function::op_internals, 1);
shape_b= func.get_next_expression_pos();
if ((null_value= g2->store_shapes(&trn)))
break;
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::op_border, 1);
func.repeat_expression(shape_a);
func.add_operation(Gcalc_function::op_border, 1);
func.repeat_expression(shape_b);
break; break;
default: default:
DBUG_ASSERT(FALSE); DBUG_ASSERT(FALSE);
break; break;
} }
if (null_value)
if ((null_value=
(args[0]->null_value || args[1]->null_value ||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
g1->store_shapes(&trn) || g2->store_shapes(&trn))))
goto exit; goto exit;
collector.prepare_operation(); collector.prepare_operation();
scan_it.init(&collector); scan_it.init(&collector);
#ifdef TMP_BLOCK
if (spatial_rel == SP_EQUALS_FUNC) if (spatial_rel == SP_EQUALS_FUNC)
{ {
result= (g1->get_class_info()->m_type_id == g1->get_class_info()->m_type_id) && result= (g1->get_class_info()->m_type_id == g1->get_class_info()->m_type_id) &&
func_equals(); func_equals();
goto exit; goto exit;
} }
#endif /*TMP_BLOCK*/
if (func.alloc_states()) if (func.alloc_states())
goto exit; goto exit;
result= func.find_function(scan_it) ^ mask; result= func.check_function(scan_it) ^ mask;
exit: exit:
collector.reset(); collector.reset();
...@@ -1307,7 +1225,7 @@ int Item_func_buffer::Transporter::start_line() ...@@ -1307,7 +1225,7 @@ int Item_func_buffer::Transporter::start_line()
if (m_fn->reserve_op_buffer(2)) if (m_fn->reserve_op_buffer(2))
return 1; return 1;
last_shape_pos= m_fn->get_next_operation_pos(); last_shape_pos= m_fn->get_next_expression_pos();
m_fn->add_operation(buffer_op, 0); m_fn->add_operation(buffer_op, 0);
m_npoints= 0; m_npoints= 0;
int_start_line(); int_start_line();
...@@ -1321,7 +1239,7 @@ int Item_func_buffer::Transporter::start_poly() ...@@ -1321,7 +1239,7 @@ int Item_func_buffer::Transporter::start_poly()
if (m_fn->reserve_op_buffer(2)) if (m_fn->reserve_op_buffer(2))
return 1; return 1;
last_shape_pos= m_fn->get_next_operation_pos(); last_shape_pos= m_fn->get_next_expression_pos();
m_fn->add_operation(buffer_op, 0); m_fn->add_operation(buffer_op, 0);
return Gcalc_operation_transporter::start_poly(); return Gcalc_operation_transporter::start_poly();
} }
...@@ -1827,19 +1745,20 @@ double Item_func_distance::val_real() ...@@ -1827,19 +1745,20 @@ double Item_func_distance::val_real()
of objects of objects
scev_thread | scev_two_threads | scev_single_point scev_thread | scev_two_threads | scev_single_point
*/ */
func.clear_state(); func.clear_i_states();
for (Gcalc_point_iterator pit(&scan_it); pit.point() != evpos; ++pit) for (Gcalc_point_iterator pit(&scan_it); pit.point() != evpos; ++pit)
{ {
gcalc_shape_info si= pit.point()->get_shape(); gcalc_shape_info si= pit.point()->get_shape();
if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon)) if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon))
func.invert_state(si); func.invert_i_state(si);
} }
func.clear_b_states();
for (; ev; ev= ev->get_next()) for (; ev; ev= ev->get_next())
{ {
if (ev->event != scev_intersection) if (ev->event != scev_intersection)
cur_point= ev->pi; cur_point= ev->pi;
func.set_on_state(ev->get_shape()); func.set_b_state(ev->get_shape());
if (func.count()) if (func.count())
{ {
/* Point of one object is inside the other - intersection found */ /* Point of one object is inside the other - intersection found */
......
...@@ -251,9 +251,6 @@ public: ...@@ -251,9 +251,6 @@ public:
void fix_length_and_dec() { maybe_null= 1; } void fix_length_and_dec() { maybe_null= 1; }
bool is_null() { (void) val_int(); return null_value; } bool is_null() { (void) val_int(); return null_value; }
protected:
int func_touches();
int func_equals();
}; };
......
...@@ -2519,6 +2519,12 @@ int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn) const ...@@ -2519,6 +2519,12 @@ int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn) const
n_objects= uint4korr(data); n_objects= uint4korr(data);
data+= 4; data+= 4;
if (!n_objects)
{
trn->empty_shape();
return 0;
}
if (trn->start_collection(n_objects)) if (trn->start_collection(n_objects))
return 1; return 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment