MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gcalc_tools.h
1 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 
17 #ifndef GCALC_TOOLS_INCLUDED
18 #define GCALC_TOOLS_INCLUDED
19 
20 #include "gcalc_slicescan.h"
21 
22 
23 /*
24  The Gcalc_function class objects are used to check for a binary relation.
25  The relation can be constructed with the prefix notation using predicates as
26  op_not (as !A)
27  op_union ( A || B || C... )
28  op_intersection ( A && B && C ... )
29  op_symdifference ( A+B+C+... == 1 )
30  op_difference ( A && !(B||C||..))
31  with the calls of the add_operation(operation, n_operands) method.
32  The relation is calculated over a set of shapes, that in turn have
33  to be added with the add_new_shape() method. All the 'shapes' can
34  be set to 0 with clear_shapes() method and single value
35  can be changed with the invert_state() method.
36  Then the value of the relation can be calculated with the count() method.
37  Frequently used method is find_function(Gcalc_scan_iterator it) that
38  iterates through the 'it' until the relation becomes TRUE.
39 */
40 
42 {
43 private:
44  static const uint32 function_buffer_item_size= 4;
45  static const uint32 shape_buffer_item_size= 4;
46  String shapes_buffer;
47  String function_buffer;
48  const char *cur_func;
49  int *i_states;
50  uint32 cur_object_id;
51  uint n_shapes;
52  int count_internal();
53 public:
54 #ifndef DBUG_OFF
55 
58  static const char *op_name(int code);
62  static const char *shape_name(int code);
63 #endif
64  enum op_type
65  {
66  op_shape= 0,
67  op_not= 0x80000000,
68  op_union= 0x10000000,
69  op_intersection= 0x20000000,
70  op_symdifference= 0x30000000,
71  op_difference= 0x40000000,
72  op_backdifference= 0x50000000,
73  op_any= 0x70000000
74  };
75  enum shape_type
76  {
77  shape_point= 0,
78  shape_line= 1,
79  shape_polygon= 2,
80  shape_hole= 3
81  };
82  Gcalc_function() : n_shapes(0) {}
83  gcalc_shape_info add_new_shape(uint32 shape_id, shape_type shape_kind);
84  /*
85  Adds the leaf operation that returns the shape value.
86  Also adds the shape to the list of operands.
87  */
88  int single_shape_op(shape_type shape_kind, gcalc_shape_info *si);
89  void add_operation(op_type operation, uint32 n_operands);
90  void add_not_operation(op_type operation, uint32 n_operands);
91  uint32 get_next_operation_pos() { return function_buffer.length(); }
95  void add_operands_to_op(uint32 operation_pos, uint32 n_operands);
99  void set_operands_to_op(uint32 operation_pos, uint32 n_operands);
100  void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; }
101  int reserve_shape_buffer(uint n_shapes);
102  int reserve_op_buffer(uint n_ops);
103  uint get_nshapes() const { return n_shapes; }
104  shape_type get_shape_kind(gcalc_shape_info si) const
105  {
106  return (shape_type) uint4korr(shapes_buffer.ptr() + (si*4));
107  }
108 
109  void set_states(int *shape_states) { i_states= shape_states; }
110  int alloc_states();
111  void invert_state(gcalc_shape_info shape) { i_states[shape]^= 1; }
112  int get_state(gcalc_shape_info shape) { return i_states[shape]; }
113  int count()
114  {
115  cur_func= function_buffer.ptr();
116  return count_internal();
117  }
118  void clear_state() { memset(i_states, 0, n_shapes * sizeof(int)); }
119  void reset();
120 
121  int find_function(Gcalc_scan_iterator &scan_it);
122 
123 #ifndef DBUG_OFF
124 
131 #endif
132 };
133 
134 
135 /*
136  Gcalc_operation_transporter class extends the Gcalc_shape_transporter.
137  In addition to the parent's functionality, it fills the Gcalc_function
138  object so it has the function that determines the proper shape.
139  For example Multipolyline will be represented as an union of polylines.
140 */
141 
143 {
144 protected:
145  Gcalc_function *m_fn;
146  gcalc_shape_info m_si;
147 public:
149  Gcalc_shape_transporter(heap), m_fn(fn) {}
150 
151  int single_point(Gcalc_shape_status *st, double x, double y);
152  int start_line(Gcalc_shape_status *st);
153  int complete_line(Gcalc_shape_status *st);
154  int start_poly(Gcalc_shape_status *st);
155  int complete_poly(Gcalc_shape_status *st);
156  int start_ring(Gcalc_shape_status *st);
157  int complete_ring(Gcalc_shape_status *st);
158  int add_point(Gcalc_shape_status *st, double x, double y);
159  int start_collection(Gcalc_shape_status *st, int nshapes);
160  int complete_collection(Gcalc_shape_status *st);
161  int collection_add_item(Gcalc_shape_status *st_collection,
162  Gcalc_shape_status *st_item);
163 };
164 
165 
166 /*
167  When we calculate the result of an spatial operation like
168  Union or Intersection, we receive vertexes of the result
169  one-by-one, and probably need to treat them in variative ways.
170  So, the Gcalc_result_receiver class designed to get these
171  vertexes and construct shapes/objects out of them.
172  and to store the result in an appropriate format
173 */
174 
176 {
177  String buffer;
178  uint32 n_points;
179  Gcalc_function::shape_type common_shapetype;
180  bool collection_result;
181  uint32 n_shapes;
182  uint32 n_holes;
183 
184  Gcalc_function::shape_type cur_shape;
185  uint32 shape_pos;
186  double first_x, first_y, prev_x, prev_y;
187  double shape_area;
188 public:
189 
191  {
192  public:
193  void *first_point;
194  uint32 order;
195  uint32 position;
196  uint32 length;
197  bool is_poly_hole;
198 #ifndef DBUG_OFF
199  inline void dbug_print() const;
200 #endif
201  };
202 
203  Gcalc_result_receiver() : collection_result(FALSE), n_shapes(0), n_holes(0)
204  {}
205  int start_shape(Gcalc_function::shape_type shape);
206  int add_point(double x, double y);
207  int complete_shape();
208  int single_point(double x, double y);
209  int done();
210  void reset();
211 
212  const char *result() { return buffer.ptr(); }
213  uint length() { return buffer.length(); }
214  int get_nshapes() { return n_shapes; }
215  int get_nholes() { return n_holes; }
216  int get_result_typeid();
217  uint32 position() { return buffer.length(); }
218  int reorder_chunks(chunk_info *chunks, int nchunks);
219 };
220 
221 
222 /*
223  Gcalc_operation_reducer class incapsulates the spatial
224  operation functionality. It analyses the slices generated by
225  the slicescan and calculates the shape of the result defined
226  by some Gcalc_function.
227 */
228 
230 {
231 public:
232  enum modes
233  {
234  /* Numeric values important here - careful with changing */
235  default_mode= 0,
236  prefer_big_with_holes= 1,
237  polygon_selfintersections_allowed= 2, /* allowed in the result */
238  line_selfintersections_allowed= 4 /* allowed in the result */
239  };
240 
241  Gcalc_operation_reducer(size_t blk_size=8192);
242  void init(Gcalc_function *fn, modes mode= default_mode);
243  Gcalc_operation_reducer(Gcalc_function *fn, modes mode= default_mode,
244  size_t blk_size=8192);
245  int count_slice(Gcalc_scan_iterator *si);
246  int count_all(Gcalc_heap *hp);
247  int get_result(Gcalc_result_receiver *storage);
248  void reset();
249 
251  {
252  res_point *m_outer_poly;
253  public:
254  bool intersection_point;
255  double x,y;
256  res_point *up;
257  res_point *down;
258  res_point *glue;
259  union
260  {
261  const Gcalc_heap::Info *pi; // is valid before get_result_thread()
262  res_point *first_poly_node; // is valid after get_result_thread()
263  };
264  Gcalc_dyn_list::Item **prev_hook;
265  res_point *get_next() { return (res_point *)next; }
266  void set_outer_poly(res_point *p)
267  {
268  m_outer_poly= p;
269  DBUG_PRINT("info", ("setting outer_poly of #%u to #%u",
270  item_id(),
271  m_outer_poly ? m_outer_poly->item_id() : 0));
272  }
273  res_point *get_outer_poly() { return m_outer_poly; }
274  };
275 
277  {
278  res_point *m_thread_start;
279  public:
280  res_point *rp;
281  int result_range;
282  void init()
283  {
284  rp= m_thread_start= NULL;
285  result_range= 0;
286  DBUG_PRINT("info", ("setting m_thread_start of #%u to NULL (reset)",
287  item_id()));
288  }
289  active_thread *get_next() { return (active_thread *)next; }
290  void set_thread_start(res_point *p)
291  {
292  DBUG_PRINT("info", ("setting m_thread_start of #%u to #%u",
293  item_id(), p ? p->item_id() : 0));
294  m_thread_start= p;
295  }
296  res_point *thread_start() const { return m_thread_start; }
297  };
298 
299 protected:
300  Gcalc_function *m_fn;
301  Gcalc_dyn_list::Item **m_res_hook;
302  res_point *m_result;
303  int m_mode;
304 
305  res_point *result_heap;
306  active_thread *m_first_active_thread;
307 
308  res_point *add_res_point(const Gcalc_heap::Info *pi)
309  {
310  res_point *rp= new_res_point(pi, false);
311  if (!rp)
312  return NULL;
313  DBUG_PRINT("info", ("add_res_point #%u: pi=(%g,%g,#%u)",
314  rp->item_id(), pi->x, pi->y, pi->shape));
315  return rp;
316  }
317 
318  res_point *add_res_i_point(const Gcalc_heap::Info *pi, double x, double y)
319  {
320  res_point *rp= new_res_point(pi, true);
321  if (!rp)
322  return NULL;
323  DBUG_PRINT("info", ("add_res_i_point #%u: pi=(%g,%g,#%u) xy=(%g,%g)",
324  rp->item_id(), pi->x, pi->y, pi->shape, x, y));
325  rp->x= x;
326  rp->y= y;
327  return rp;
328  }
329 
330  res_point *add_res_single_point(const Gcalc_heap::Info *pi)
331  {
332  res_point *rp= new_res_point(pi, false);
333  if (!rp)
334  return NULL;
335  DBUG_PRINT("info", ("add_res_single_point #%u: pi=(%g,%g,#%u)",
336  rp->item_id(), pi->x, pi->y, pi->shape));
337  rp->x= pi->x;
338  rp->y= pi->y;
339  return rp;
340  }
341 
342  active_thread *new_active_thread()
343  {
344  active_thread *tmp= (active_thread *) new_item();
345  if (tmp)
346  tmp->init();
347  return tmp;
348  }
349 
350 private:
351 
352  res_point *new_res_point(const Gcalc_heap::Info *pi,
353  bool intersection_point)
354  {
355  res_point *result= (res_point *) new_item();
356  *m_res_hook= result;
357  result->prev_hook= m_res_hook;
358  m_res_hook= &result->next;
359  result->pi= pi;
360  result->intersection_point= intersection_point;
361  return result;
362  }
363 
364  int continue_range(active_thread *t, const Gcalc_heap::Info *p);
365  int continue_i_range(active_thread *t, const Gcalc_heap::Info *p,
366  double x, double y);
367  int start_range(active_thread *t, const Gcalc_heap::Info *p);
368  int start_i_range(active_thread *t, const Gcalc_heap::Info *p,
369  double x, double y);
370  int end_range(active_thread *t, const Gcalc_heap::Info *p);
371  int end_i_range(active_thread *t, const Gcalc_heap::Info *p,
372  double x, double y);
373  int start_couple(active_thread *t0, active_thread *t1,const Gcalc_heap::Info *p,
374  const active_thread *prev_range);
375  int start_i_couple(active_thread *t0, active_thread *t1,
376  const Gcalc_heap::Info *p0,
377  const Gcalc_heap::Info *p1,
378  double x, double y,
379  const active_thread *prev_range);
380  int end_couple(active_thread *t0, active_thread *t1, const Gcalc_heap::Info *p);
381  int end_i_couple(active_thread *t0, active_thread *t1,
382  const Gcalc_heap::Info *p0,
383  const Gcalc_heap::Info *p1,
384  double x, double y);
385  int add_single_point(const Gcalc_heap::Info *p);
386  int add_i_single_point(const Gcalc_heap::Info *p, double x, double y);
387 
388  int handle_lines_intersection(active_thread *t0, active_thread *t1,
389  const Gcalc_heap::Info *p0,
390  const Gcalc_heap::Info *p1,
391  double x, double y);
392  int handle_polygons_intersection(active_thread *t0, active_thread *t1,
393  Gcalc_dyn_list::Item **t_hook,
394  const Gcalc_heap::Info *p0,
395  const Gcalc_heap::Info *p1,
396  int prev_state, double x, double y,
397  const active_thread *prev_range);
398  int handle_line_polygon_intersection(active_thread *l,
399  const Gcalc_heap::Info *pl,
400  int line_state, int poly_state,
401  double x, double y);
402 
403  int get_single_result(res_point *res, Gcalc_result_receiver *storage);
404  int get_result_thread(res_point *cur, Gcalc_result_receiver *storage,
405  int move_upward);
406  int get_polygon_result(res_point *cur, Gcalc_result_receiver *storage);
407  int get_line_result(res_point *cur, Gcalc_result_receiver *storage);
408 
409  void free_result(res_point *res);
410 };
411 
412 #endif /*GCALC_TOOLS_INCLUDED*/
413