Commit 152f3c5e authored by Alexey Botchkov's avatar Alexey Botchkov

PostGIS-style 'same point' handling.

parent 90c4df7a
......@@ -392,10 +392,10 @@ Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
first second w c o e d t i r
120 120 0 0 0 1 0 1 1 0
120 120 1 1 0 1 0 1 1 1
120 121 0 0 1 0 0 0 1 0
121 120 0 0 1 0 0 0 1 0
121 121 0 0 0 1 0 1 1 0
121 121 1 1 0 1 0 1 1 1
explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
......@@ -494,12 +494,13 @@ mbroverlaps
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;
mbrtouches
down2,left2,right2,up2
big,center,down,down2,left,left2,right,right2,small,up,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;
mbrwithin
big,center
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS contains FROM t1 a1 JOIN t1 a2 ON Contains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
contains
center,small
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS disjoint FROM t1 a1 JOIN t1 a2 ON Disjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
disjoint
down3,left3,right3,up3
......@@ -514,9 +515,10 @@ overlaps
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;
touches
down2,left2,right2,up2
big,center,down,down2,left,left2,right,right2,small,up,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;
within
big,center
SET @vert1 = GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
SET @horiz1 = GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
SET @horiz2 = GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
......
This diff is collapsed.
......@@ -170,6 +170,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range g g 34 NULL 8 Using where
SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
fid AsText(g)
11 LINESTRING(140 140,160 160)
DROP TABLE t1;
CREATE TABLE t2 (
fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
......
......@@ -384,10 +384,10 @@ Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
first second w c o e d t i r
120 120 0 0 0 1 0 1 1 0
120 120 1 1 0 1 0 1 1 1
120 121 0 0 1 0 0 0 1 0
121 120 0 0 1 0 0 0 1 0
121 121 0 0 0 1 0 1 1 0
121 121 1 1 0 1 0 1 1 1
explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
......@@ -835,12 +835,13 @@ mbroverlaps
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;
mbrtouches
down2,left2,right2,up2
big,center,down,down2,left,left2,right,right2,small,up,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;
mbrwithin
big,center
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS contains FROM t1 a1 JOIN t1 a2 ON Contains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
contains
center,small
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS disjoint FROM t1 a1 JOIN t1 a2 ON Disjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
disjoint
down3,left3,right3,up3
......@@ -855,9 +856,10 @@ overlaps
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;
touches
down2,left2,right2,up2
big,center,down,down2,left,left2,right,right2,small,up,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;
within
big,center
SET @vert1 = GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
SET @horiz1 = GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
SET @horiz2 = GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
......@@ -1410,7 +1412,7 @@ FROM lakes, named_places
WHERE lakes.name = 'Blue Lake'
AND named_places.name = 'Ashton';
AsText(ST_SymDifference(shore, boundary))
MULTIPOLYGON(((48 6,52 18,66 23,73 9,48 6),(67 13,59 13,59 18,67 18,67 13)),((56 30,56 34,62 48,84 48,84 30,56 30)))
MULTIPOLYGON(((48 6,52 18,66 23,73 9,48 6),(59 13,59 18,67 18,67 13,59 13)),((56 30,56 34,62 48,84 48,84 30,56 30)))
# Conformance Item T51
SELECT count(*)
FROM buildings, bridges
......
......@@ -392,10 +392,10 @@ Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
first second w c o e d t i r
120 120 0 0 0 1 0 1 1 0
120 120 1 1 0 1 0 1 1 1
120 121 0 0 1 0 0 0 1 0
121 120 0 0 1 0 0 0 1 0
121 121 0 0 0 1 0 1 1 0
121 121 1 1 0 1 0 1 1 1
explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
......@@ -494,12 +494,13 @@ mbroverlaps
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;
mbrtouches
down2,left2,right2,up2
big,center,down,down2,left,left2,right,right2,small,up,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;
mbrwithin
big,center
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS contains FROM t1 a1 JOIN t1 a2 ON Contains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
contains
center,small
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS disjoint FROM t1 a1 JOIN t1 a2 ON Disjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
disjoint
down3,left3,right3,up3
......@@ -514,9 +515,10 @@ overlaps
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;
touches
down2,left2,right2,up2
big,center,down,down2,left,left2,right,right2,small,up,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;
within
big,center
SET @vert1 = GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
SET @horiz1 = GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
SET @horiz2 = GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
......
......@@ -392,10 +392,10 @@ Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
first second w c o e d t i r
120 120 0 0 0 1 0 1 1 0
120 120 1 1 0 1 0 1 1 1
120 121 0 0 1 0 0 0 1 0
121 120 0 0 1 0 0 0 1 0
121 121 0 0 0 1 0 1 1 0
121 121 1 1 0 1 0 1 1 1
explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
......@@ -494,12 +494,13 @@ mbroverlaps
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;
mbrtouches
down2,left2,right2,up2
big,center,down,down2,left,left2,right,right2,small,up,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;
mbrwithin
big,center
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS contains FROM t1 a1 JOIN t1 a2 ON Contains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
contains
center,small
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS disjoint FROM t1 a1 JOIN t1 a2 ON Disjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
disjoint
down3,left3,right3,up3
......@@ -514,9 +515,10 @@ overlaps
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;
touches
down2,left2,right2,up2
big,center,down,down2,left,left2,right,right2,small,up,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;
within
big,center
SET @vert1 = GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
SET @horiz1 = GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
SET @horiz2 = GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
......
This diff is collapsed.
......@@ -236,6 +236,7 @@ class Gcalc_shape_transporter
enum Gcalc_scan_events
{
scev_none= 0,
scev_point= 1, /* Just a new point in thread */
scev_thread= 2, /* Start of the new thread */
scev_two_threads= 4, /* A couple of new threads started */
......@@ -268,7 +269,13 @@ class Gcalc_scan_iterator : public Gcalc_dyn_list
Gcalc_heap::Info *pi;
Gcalc_heap::Info *next_pi;
sc_thread_id thread;
const point *precursor; /* used as a temporary field */
const point *intersection_link;
Gcalc_scan_events event;
#ifdef TO_REMOVE
const point *event_pair;
point *next_link;
#endif /*TO_REMOVE*/
inline const point *c_get_next() const
{ return (const point *)next; }
......@@ -276,15 +283,17 @@ class Gcalc_scan_iterator : public Gcalc_dyn_list
gcalc_shape_info get_shape() const { return pi->shape; }
inline point *get_next() { return (point *)next; }
inline const point *get_next() const { return (const point *)next; }
/* copies all but 'next' 'x' and 'precursor' */
void copy_core(const point *from)
void copy_core(point *from);
/* Compare the dx_dy parameters regarding the horiz_dir */
/* returns -1 if less, 0 if equal, 1 if bigger */
static int compare_dx_dy(int horiz_dir_a, double dx_dy_a,
int horiz_dir_b, double dx_dy_b);
int cmp_dx_dy(const point *p) const;
int simple_event() const
{
dx_dy= from->dx_dy;
horiz_dir= from->horiz_dir;
pi= from->pi;
next_pi= from->next_pi;
thread= from->thread;
return !next ? (event & (scev_point | scev_end)) :
(!next->next && event == scev_two_ends);
}
#ifndef DBUG_OFF
void dbug_print();
......@@ -301,6 +310,22 @@ class Gcalc_scan_iterator : public Gcalc_dyn_list
inline intersection *get_next() { return (intersection *)next; }
};
class slice_state
{
public:
point *slice;
point *event_position;
Gcalc_dyn_list::Item **event_position_hook;
Gcalc_dyn_list::Item **event_end_hook;
double y;
slice_state() : slice(NULL) {}
void clear_event_position()
{
event_position= NULL;
event_end_hook= (Gcalc_dyn_list::Item **) &event_position;
}
};
public:
Gcalc_scan_iterator(size_t blk_size= 8192);
......@@ -309,50 +334,46 @@ class Gcalc_scan_iterator : public Gcalc_dyn_list
int step()
{
DBUG_ASSERT(more_points());
return m_cur_intersection ? intersection_scan() : normal_scan();
return m_intersections ? intersection_scan() : normal_scan();
}
inline Gcalc_heap::Info *more_points() { return m_cur_pi; }
inline bool more_trapezoids()
{ return m_cur_pi && m_cur_pi->next; }
inline Gcalc_scan_events get_event() const { return m_event0; }
inline const point *get_events() const
{ return m_events; }
inline const point *get_event_position() const
{ return m_event_position0; }
inline const point *get_b_slice() const { return m_slice0; }
inline const point *get_t_slice() const { return m_slice1; }
inline double get_h() const { return m_h; }
inline double get_y() const { return m_y0; }
{ return current_state->event_position; }
inline const point *get_event_end() const
{ return (point *) *current_state->event_end_hook; }
inline const point *get_b_slice() const { return current_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; }
inline double get_y() const { return current_state->y; }
private:
Gcalc_heap::Info *m_cur_pi;
point *m_slice0;
point *m_slice1;
point *m_sav_slice;
slice_state state0, state1, state_s;
slice_state *current_state;
slice_state *next_state;
slice_state *saved_state;
intersection *m_intersections;
int m_n_intersections;
intersection *m_cur_intersection;
point **m_pre_intersection_hook;
double m_h;
double m_y0;
double m_y1;
double m_sav_y;
bool m_next_is_top_point;
unsigned int m_bottom_points_count;
sc_thread_id m_cur_thread;
Gcalc_scan_events m_event0, m_event1;
point *m_event_position0;
point *m_event_position1;
point *m_events;
int normal_scan();
int intersection_scan();
void sort_intersections();
int handle_intersections();
int insert_top_point();
int add_intersection(const point *a, const point *b,
int isc_kind, Gcalc_dyn_list::Item ***p_hook);
Gcalc_dyn_list::Item ***p_hook);
int find_intersections();
void pop_suitable_intersection();
intersection *new_intersection()
{
......@@ -363,6 +384,8 @@ class Gcalc_scan_iterator : public Gcalc_dyn_list
return (point *)new_item();
}
point *new_slice(point *example);
int arrange_event();
void mark_event_position1(point *ep, Gcalc_dyn_list::Item **ep_hook);
};
......@@ -427,6 +450,8 @@ class Gcalc_point_iterator
inline const Gcalc_heap::Info *get_pi() const { return sp->pi; }
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)
{ sp= scan_i->get_b_slice(); }
};
#endif /*GCALC_SLICESCAN_INCLUDED*/
......
This diff is collapsed.
......@@ -45,6 +45,7 @@ class Gcalc_function
String function_buffer;
const char *cur_func;
int *i_states;
int *saved_i_states;
uint32 cur_object_id;
uint n_shapes;
int count_internal();
......@@ -90,7 +91,10 @@ class Gcalc_function
void set_states(int *shape_states) { i_states= shape_states; }
int alloc_states();
void invert_state(gcalc_shape_info shape) { i_states[shape]^= 1; }
void set_on_state(gcalc_shape_info shape) { i_states[shape]= 1; }
int get_state(gcalc_shape_info shape) { return i_states[shape]; }
void save_states();
void restore_states();
int count()
{
cur_func= function_buffer.ptr();
......@@ -210,6 +214,7 @@ class Gcalc_operation_reducer : public Gcalc_dyn_list
res_point *up;
res_point *down;
res_point *glue;
Gcalc_function::shape_type type;
union
{
const Gcalc_heap::Info *pi;
......@@ -228,8 +233,10 @@ class Gcalc_operation_reducer : public Gcalc_dyn_list
{
public:
res_point *rp;
int result_range;
int horiz_dir;
double dx_dy;
res_point *thread_start;
res_point *enabled() { return rp; }
active_thread *get_next() { return (active_thread *)next; }
};
......@@ -240,6 +247,60 @@ class Gcalc_operation_reducer : public Gcalc_dyn_list
poly_instance *get_next() { return (poly_instance *)next; }
};
class line : public Gcalc_dyn_list::Item
{
public:
active_thread *t;
int incoming;
const Gcalc_scan_iterator::point *p;
line *get_next() { return (line *)next; }
};
class poly_border : public Gcalc_dyn_list::Item
{
public:
active_thread *t;
int incoming;
int prev_state;
const Gcalc_scan_iterator::point *p;
poly_border *get_next() { return (poly_border *)next; }
};
line *m_lines;
Gcalc_dyn_list::Item **m_lines_hook;
poly_border *m_poly_borders;
Gcalc_dyn_list::Item **m_poly_borders_hook;
line *new_line() { return (line *) new_item(); }
poly_border *new_poly_border() { return (poly_border *) new_item(); }
int 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 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;
}
protected:
Gcalc_function *m_fn;
Gcalc_dyn_list::Item **m_res_hook;
......@@ -249,12 +310,13 @@ class Gcalc_operation_reducer : public Gcalc_dyn_list
res_point *result_heap;
active_thread *m_first_active_thread;
res_point *add_res_point()
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;
}
......@@ -263,44 +325,27 @@ class Gcalc_operation_reducer : public Gcalc_dyn_list
poly_instance *new_poly() { return (poly_instance *) new_item(); }
private:
int continue_range(active_thread *t, const Gcalc_heap::Info *p);
int continue_i_range(active_thread *t, const Gcalc_heap::Info *p,
double x, double y);
int start_range(active_thread *t, const Gcalc_heap::Info *p);
int start_i_range(active_thread *t, const Gcalc_heap::Info *p,
double x, double y);
int end_range(active_thread *t, const Gcalc_heap::Info *p);
int end_i_range(active_thread *t, const Gcalc_heap::Info *p,
double x, double y);
int start_couple(active_thread *t0, active_thread *t1,const Gcalc_heap::Info *p,
const active_thread *prev_range);
int start_i_couple(active_thread *t0, active_thread *t1,
const Gcalc_heap::Info *p0,
const Gcalc_heap::Info *p1,
double x, double y,
const active_thread *prev_range);
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);
int connect_threads(int incoming_a, int incoming_b,
active_thread *ta, active_thread *tb,
const Gcalc_scan_iterator::point *pa,
const Gcalc_scan_iterator::point *pb,
active_thread *prev_range,
const Gcalc_heap::Info *ev_p,
const Gcalc_scan_iterator *si,
Gcalc_function::shape_type s_t);
int add_single_point(const Gcalc_heap::Info *p,
const Gcalc_scan_iterator *si);
poly_border *get_pair_border(poly_border *b1);
int continue_range(active_thread *t, const Gcalc_heap::Info *p,
int horiz_dir, double dx_dy);
int continue_i_range(active_thread *t, double x, double y,
int horiz_dir, double dx_dy);
int end_couple(active_thread *t0, active_thread *t1, const Gcalc_heap::Info *p);
int end_i_couple(active_thread *t0, active_thread *t1,
const Gcalc_heap::Info *p0,
const Gcalc_heap::Info *p1,
double x, double y);
int add_single_point(const Gcalc_heap::Info *p);
int add_i_single_point(const Gcalc_heap::Info *p, double x, double y);
int handle_lines_intersection(active_thread *t0, active_thread *t1,
const Gcalc_heap::Info *p0,
const Gcalc_heap::Info *p1,
double x, double y);
int handle_polygons_intersection(active_thread *t0, active_thread *t1,
Gcalc_dyn_list::Item **t_hook,
const Gcalc_heap::Info *p0,
const Gcalc_heap::Info *p1,
int prev_state, double x, double y,
const active_thread *prev_range);
int handle_line_polygon_intersection(active_thread *l,
const Gcalc_heap::Info *pl,
int line_state, int poly_state,
double x, double y);
int get_single_result(res_point *res, Gcalc_result_receiver *storage);
int get_result_thread(res_point *cur, Gcalc_result_receiver *storage,
......
......@@ -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)
......
......@@ -705,6 +705,8 @@ int Gis_line_string::store_shapes(Gcalc_shape_transporter *trn) const
{
uint32 n_points;
double x, y;
double prev_x, prev_y;
int first_point= 1;
const char *data= m_data;
if (no_data(m_data, 4))
......@@ -720,8 +722,13 @@ int Gis_line_string::store_shapes(Gcalc_shape_transporter *trn) const
{
get_point(&x, &y, data);
data+= POINT_DATA_SIZE;
if (!first_point && x == prev_x && y == prev_y)
continue;
if (trn->add_point(x, y))
return 1;
first_point= 0;
prev_x= x;
prev_y= y;
}
return trn->complete_line();
......@@ -1119,6 +1126,9 @@ int Gis_polygon::store_shapes(Gcalc_shape_transporter *trn) const
{
uint32 n_linear_rings;
const char *data= m_data;
double first_x, first_y;
double prev_x, prev_y;
int was_equal_first= 0;
if (trn->start_poly())
return 1;
......@@ -1140,11 +1150,33 @@ int Gis_polygon::store_shapes(Gcalc_shape_transporter *trn) const
return 1;
trn->start_ring();
get_point(&first_x, &first_y, data);
data+= POINT_DATA_SIZE;
n_points--;
prev_x= first_x;
prev_y= first_y;
if (trn->add_point(first_x, first_y))
return 1;
while (--n_points)
{
double x, y;
get_point(&x, &y, data);
data+= POINT_DATA_SIZE;
if (x == prev_x && y == prev_y)
continue;
prev_x= x;
prev_y= y;
if (was_equal_first)
{
if (trn->add_point(first_x, first_y))
return 1;
was_equal_first= 0;
}
if (x == first_x && y == first_y)
{
was_equal_first= 1;
continue;
}
if (trn->add_point(x, y))
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