summaryrefslogtreecommitdiff
path: root/sql/item_geofunc.cc
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2011-09-01 11:44:56 +0500
committerAlexey Botchkov <holyfoot@askmonty.org>2011-09-01 11:44:56 +0500
commit152f3c5e28fe2ae3fd950f15bb3de7064500ced5 (patch)
tree03282c50011a629819897543af9e245b213aaaa7 /sql/item_geofunc.cc
parent90c4df7a4af542707d884e53990827672bb8feea (diff)
downloadmariadb-git-152f3c5e28fe2ae3fd950f15bb3de7064500ced5.tar.gz
PostGIS-style 'same point' handling.
Diffstat (limited to 'sql/item_geofunc.cc')
-rw-r--r--sql/item_geofunc.cc112
1 files changed, 61 insertions, 51 deletions
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 4afc56eaf87..a8abcd26b42 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -665,10 +665,12 @@ static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si,
{
bool above_cur_point, cur_point_edge;
const Gcalc_scan_iterator::point *evpos;
- const Gcalc_heap::Info *cur_point, *dist_point;
- Gcalc_scan_events ev;
+ const Gcalc_heap::Info *cur_point= NULL;
+ const Gcalc_heap::Info *dist_point;
+ const Gcalc_scan_iterator::point *ev;
double t, distance, cur_distance;
double ex, ey, vx, vy, e_sqrlen;
+ int o1, o2;
DBUG_ENTER("calc_distance");
@@ -680,32 +682,39 @@ static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si,
if (scan_it->step())
goto mem_error;
evpos= scan_it->get_event_position();
- ev= scan_it->get_event();
- cur_point= evpos->pi;
+ ev= scan_it->get_events();
+ cur_point= NULL;
+
+ if (ev->simple_event())
+ {
+ cur_point= ev->pi;
+ goto calculate_distance;
+ }
/*
handling intersection we only need to check if it's the intersecion
of objects 1 and 2. In this case distance is 0
*/
- if (ev == scev_intersection)
+ o1= 0;
+ o2= 0;
+ for (; ev; ev= ev->get_next())
{
- if ((evpos->get_next()->pi->shape >= obj2_si) !=
- (cur_point->shape >= obj2_si))
+ if (ev->event != scev_intersection)
+ cur_point= ev->pi;
+ if (ev->pi->shape >= obj2_si)
+ o2= 1;
+ else
+ o1= 1;
+ if (o1 && o2)
{
distance= 0;
goto exit;
}
- continue;
}
+ if (!cur_point)
+ continue;
- /*
- if we get 'scev_point | scev_end | scev_two_ends' we don't need
- to check for intersection of objects.
- Though we need to calculate distances.
- */
- if (ev & (scev_point | scev_end | scev_two_ends))
- goto calculate_distance;
-
+#ifdef TO_REMOVE
goto calculate_distance;
/*
having these events we need to check for possible intersection
@@ -728,7 +737,7 @@ static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si,
distance= 0;
goto exit;
}
-
+#endif /*TO_REMOVE*/
calculate_distance:
if (cur_point->shape >= obj2_si)
@@ -1516,6 +1525,7 @@ longlong Item_func_issimple::val_int()
Gcalc_operation_transporter trn(&func, &collector);
Geometry *g;
int result= 1;
+ const Gcalc_scan_iterator::point *ev;
DBUG_ENTER("Item_func_issimple::val_int");
DBUG_ASSERT(fixed == 1);
@@ -1539,11 +1549,19 @@ longlong Item_func_issimple::val_int()
if (scan_it.step())
goto mem_error;
- if (scan_it.get_event() == scev_intersection)
- {
- result= 0;
- break;
- }
+ ev= scan_it.get_events();
+ if (ev->simple_event())
+ continue;
+
+ if ((ev->event == scev_thread || ev->event == scev_single_point) &&
+ !ev->get_next())
+ continue;
+
+ if (ev->event == scev_two_threads && !ev->get_next()->get_next())
+ continue;
+
+ result= 0;
+ break;
}
collector.reset();
@@ -1553,7 +1571,6 @@ longlong Item_func_issimple::val_int()
mem_error:
null_value= 1;
DBUG_RETURN(0);
- return 0;
}
@@ -1731,7 +1748,7 @@ double Item_func_distance::val_real()
bool above_cur_point, cur_point_edge;
const Gcalc_scan_iterator::point *evpos;
const Gcalc_heap::Info *cur_point, *dist_point;
- Gcalc_scan_events ev;
+ const Gcalc_scan_iterator::point *ev;
double t, distance, cur_distance;
double x1, x2, y1, y2;
double ex, ey, vx, vy, e_sqrlen;
@@ -1782,39 +1799,24 @@ double Item_func_distance::val_real()
if (scan_it.step())
goto mem_error;
evpos= scan_it.get_event_position();
- ev= scan_it.get_event();
- cur_point= evpos->pi;
+ ev= scan_it.get_events();
- /*
- handling intersection we only need to check if it's the intersecion
- of objects 1 and 2. In this case distance is 0
- */
- if (ev == scev_intersection)
+ if (ev->simple_event())
{
- if ((evpos->get_next()->pi->shape >= obj2_si) !=
- (cur_point->shape >= obj2_si))
- {
- distance= 0;
- goto exit;
- }
- continue;
+ cur_point= ev->pi;
+ goto count_distance;
}
-
/*
- if we get 'scev_point | scev_end | scev_two_ends' we don't need
- to check for intersection of objects.
- Though we need to calculate distances.
+ handling intersection we only need to check if it's the intersecion
+ of objects 1 and 2. In this case distance is 0
*/
- if (ev & (scev_point | scev_end | scev_two_ends))
- goto count_distance;
+ cur_point= NULL;
/*
having these events we need to check for possible intersection
of objects
scev_thread | scev_two_threads | scev_single_point
*/
- DBUG_ASSERT(ev & (scev_thread | scev_two_threads | scev_single_point));
-
func.clear_state();
for (Gcalc_point_iterator pit(&scan_it); pit.point() != evpos; ++pit)
{
@@ -1822,14 +1824,22 @@ double Item_func_distance::val_real()
if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon))
func.invert_state(si);
}
- func.invert_state(evpos->get_shape());
- if (func.count())
+
+ for (; ev; ev= ev->get_next())
{
- /* Point of one object is inside the other - intersection found */
- distance= 0;
- goto exit;
+ if (ev->event != scev_intersection)
+ cur_point= ev->pi;
+ func.set_on_state(evpos->get_shape());
+ if (func.count())
+ {
+ /* Point of one object is inside the other - intersection found */
+ distance= 0;
+ goto exit;
+ }
}
+ if (!cur_point)
+ continue;
count_distance:
if (cur_point->shape >= obj2_si)