lulu 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/ext/lulu/merger.h CHANGED
@@ -10,8 +10,6 @@
10
10
 
11
11
  #include "marker.h"
12
12
 
13
- void merge_markers(MARKER_INFO *info, MARKER *markers, int markers_size);
14
13
  int merge_markers_fast(MARKER_INFO *info, MARKER *markers, int markers_size);
15
- int merge_test(int test_markers_size);
16
14
 
17
15
  #endif /* MERGER_H_ */
data/ext/lulu/pq.c CHANGED
@@ -17,228 +17,155 @@
17
17
 
18
18
  // Move index at heap location j upward until its parent's value is no bigger.
19
19
  static void pq_sift_up(PRIORITY_QUEUE *q, int j) {
20
- int i = q->heap[j];
21
- PRIORITY_QUEUE_VALUE val = q->values[i];
22
- while (j > 0) {
23
- int j_pnt = (j - 1) / 2;
24
- if (q->values[q->heap[j_pnt]] <= val)
25
- break;
26
- int k = q->heap[j] = q->heap[j_pnt];
27
- q->locs[k] = j;
28
- j = j_pnt;
29
- }
30
- int k = q->heap[j] = i;
31
- q->locs[k] = j;
20
+ int i = q->heap[j];
21
+ PRIORITY_QUEUE_VALUE val = q->values[i];
22
+ while (j > 0) {
23
+ int j_pnt = (j - 1) / 2;
24
+ if (q->values[q->heap[j_pnt]] <= val)
25
+ break;
26
+ int k = q->heap[j] = q->heap[j_pnt];
27
+ q->locs[k] = j;
28
+ j = j_pnt;
29
+ }
30
+ int k = q->heap[j] = i;
31
+ q->locs[k] = j;
32
32
  }
33
33
 
34
34
  // Move index at heap location j downward until its children's values are no smaller.
35
35
  // Pay some attention to efficiency because this is bottleneck code.
36
36
  static void pq_sift_down(PRIORITY_QUEUE *q, int j) {
37
- int i = q->heap[j];
38
- PRIORITY_QUEUE_VALUE val = q->values[i];
39
- for (;;) {
40
- int j_rgt = 2 * j + 2;
41
- if (j_rgt < q->size) {
42
- // two children
43
- int j_lft = j_rgt - 1;
44
- PRIORITY_QUEUE_VALUE val_lft = q->values[q->heap[j_lft]];
45
- PRIORITY_QUEUE_VALUE val_rgt = q->values[q->heap[j_rgt]];
46
- if (val_lft < val_rgt) {
47
- if (val <= val_lft)
48
- break;
49
- int k = q->heap[j] = q->heap[j_lft];
50
- q->locs[k] = j;
51
- j = j_lft;
52
- } else {
53
- if (val <= val_rgt)
54
- break;
55
- int k = q->heap[j] = q->heap[j_rgt];
56
- q->locs[k] = j;
57
- j = j_rgt;
58
- }
59
- } else if (j_rgt == q->size) {
60
- // left child only
61
- int j_lft = j_rgt - 1;
62
- if (val <= q->values[q->heap[j_lft]])
63
- break;
64
- int k = q->heap[j] = q->heap[j_lft];
65
- q->locs[k] = j;
66
- j = j_lft;
67
- break; // this node has no children
68
- } else {
69
- break; // no children at all
70
- }
71
- }
72
- int k = q->heap[j] = i;
73
- q->locs[k] = j;
37
+ int i = q->heap[j];
38
+ PRIORITY_QUEUE_VALUE val = q->values[i];
39
+ for (;;) {
40
+ int j_rgt = 2 * j + 2;
41
+ if (j_rgt < q->size) {
42
+ // two children
43
+ int j_lft = j_rgt - 1;
44
+ PRIORITY_QUEUE_VALUE val_lft = q->values[q->heap[j_lft]];
45
+ PRIORITY_QUEUE_VALUE val_rgt = q->values[q->heap[j_rgt]];
46
+ if (val_lft < val_rgt) {
47
+ if (val <= val_lft)
48
+ break;
49
+ int k = q->heap[j] = q->heap[j_lft];
50
+ q->locs[k] = j;
51
+ j = j_lft;
52
+ } else {
53
+ if (val <= val_rgt)
54
+ break;
55
+ int k = q->heap[j] = q->heap[j_rgt];
56
+ q->locs[k] = j;
57
+ j = j_rgt;
58
+ }
59
+ } else if (j_rgt == q->size) {
60
+ // left child only
61
+ int j_lft = j_rgt - 1;
62
+ if (val <= q->values[q->heap[j_lft]])
63
+ break;
64
+ int k = q->heap[j] = q->heap[j_lft];
65
+ q->locs[k] = j;
66
+ j = j_lft;
67
+ break; // this node has no children
68
+ } else {
69
+ break; // no children at all
70
+ }
71
+ }
72
+ int k = q->heap[j] = i;
73
+ q->locs[k] = j;
74
74
  }
75
75
 
76
76
  // Initialize a newly allocated priority queue structure.
77
77
  void pq_init(PRIORITY_QUEUE *q) {
78
- q->max_size = q->size = 0;
79
- q->heap = NULL;
80
- q->locs = NULL;
81
- q->values = NULL;
78
+ q->max_size = q->size = 0;
79
+ q->heap = NULL;
80
+ q->locs = NULL;
81
+ q->values = NULL;
82
82
  }
83
83
 
84
84
  // Clear a previously initialized and possibly set up priority queue, returning
85
85
  // it to the initialized state but with all resourced freed. Note the values
86
86
  // are owned by the user and are not freed here.
87
87
  void pq_clear(PRIORITY_QUEUE *q) {
88
- Free(q->heap);
89
- Free(q->locs);
90
- pq_init(q);
88
+ Free(q->heap);
89
+ Free(q->locs);
90
+ pq_init(q);
91
91
  }
92
92
 
93
93
  // Build the queue with given pre-allocated and filled array of values.
94
94
  void pq_set_up(PRIORITY_QUEUE *q, PRIORITY_QUEUE_VALUE *values, int size) {
95
- q->max_size = q->size = size;
96
- q->values = values;
97
- NewArray(q->heap, size);
98
- NewArray(q->locs, size);
99
- for (int i = 0; i < size; i++)
100
- q->heap[i] = q->locs[i] = i;
101
- // heapify
102
- for (int j = size / 2 - 1; j >= 0; j--)
103
- pq_sift_down(q, j);
95
+ q->max_size = q->size = size;
96
+ q->values = values;
97
+ NewArray(q->heap, size);
98
+ NewArray(q->locs, size);
99
+ for (int i = 0; i < size; i++)
100
+ q->heap[i] = q->locs[i] = i;
101
+ // heapify
102
+ for (int j = size / 2 - 1; j >= 0; j--)
103
+ pq_sift_down(q, j);
104
104
  }
105
105
 
106
106
  // Build the queue with given pre-allocated and filled array of values
107
107
  // and given heap indices. Note the indices are owned by the heap
108
108
  // after set up and will be freed with the heap.
109
109
  void pq_set_up_heap(PRIORITY_QUEUE *q, int *heap, int size,
110
- PRIORITY_QUEUE_VALUE *values, int max_size) {
111
- q->max_size = max_size;
112
- q->values = values;
113
- q->size = size;
114
- q->heap = heap;
115
- NewArray(q->locs, max_size);
116
- for (int i = 0; i < max_size; i++)
117
- q->locs[i] = -1;
118
- for (int j = 0; j < size; j++)
119
- q->locs[heap[j]] = j;
120
- for (int j = size / 2 - 1; j >= 0; j--)
121
- pq_sift_down(q, j);
110
+ PRIORITY_QUEUE_VALUE *values, int max_size) {
111
+ q->max_size = max_size;
112
+ q->values = values;
113
+ q->size = size;
114
+ q->heap = heap;
115
+ NewArray(q->locs, max_size);
116
+ for (int i = 0; i < max_size; i++)
117
+ q->locs[i] = -1;
118
+ for (int j = 0; j < size; j++)
119
+ q->locs[heap[j]] = j;
120
+ for (int j = size / 2 - 1; j >= 0; j--)
121
+ pq_sift_down(q, j);
122
122
  }
123
123
 
124
124
  // Return the index of the minimum value on the queue.
125
125
  int pq_peek_min(PRIORITY_QUEUE *q) {
126
- return q->size <= 0 ? -1 : q->heap[0];
126
+ return q->size <= 0 ? -1 : q->heap[0];
127
127
  }
128
128
 
129
129
  // Remove and return the index of the minimum value on the queue.
130
130
  int pq_get_min(PRIORITY_QUEUE *q) {
131
- if (q->size <= 0)
132
- return -1;
133
- int i = q->heap[0];
134
- q->locs[i] = -1;
135
- if (--q->size > 0) {
136
- q->heap[0] = q->heap[q->size];
137
- pq_sift_down(q, 0);
138
- }
139
- return i;
131
+ if (q->size <= 0)
132
+ return -1;
133
+ int i = q->heap[0];
134
+ q->locs[i] = -1;
135
+ if (--q->size > 0) {
136
+ q->heap[0] = q->heap[q->size];
137
+ pq_sift_down(q, 0);
138
+ }
139
+ return i;
140
140
  }
141
141
 
142
142
  // Add a new value with index i into the queue.
143
143
  void pq_add(PRIORITY_QUEUE *q, int i) {
144
- if (q->size >= q->max_size)
145
- return;
146
- int j = q->size++;
147
- q->heap[j] = i;
148
- pq_sift_up(q, j);
144
+ if (q->size >= q->max_size)
145
+ return;
146
+ int j = q->size++;
147
+ q->heap[j] = i;
148
+ pq_sift_up(q, j);
149
149
  }
150
150
 
151
151
  // Restore the heap after the value at index i is changed.
152
152
  void pq_update(PRIORITY_QUEUE *q, int i) {
153
- int j = q->locs[i];
154
- if (j >= 0) {
155
- pq_sift_down(q, j);
156
- pq_sift_up(q, j);
157
- }
153
+ int j = q->locs[i];
154
+ if (j >= 0) {
155
+ pq_sift_down(q, j);
156
+ pq_sift_up(q, j);
157
+ }
158
158
  }
159
159
 
160
160
  // Delete index i from the heap, making the corresponding key an orphan.
161
161
  void pq_delete(PRIORITY_QUEUE *q, int i) {
162
- int j = q->locs[i];
163
- if (0 <= j) {
164
- q->locs[i] = -1;
165
- if (j < --q->size) {
166
- q->heap[j] = q->heap[q->size];
167
- pq_sift_down(q, j);
168
- pq_sift_up(q, j);
169
- }
170
- }
162
+ int j = q->locs[i];
163
+ if (0 <= j) {
164
+ q->locs[i] = -1;
165
+ if (j < --q->size) {
166
+ q->heap[j] = q->heap[q->size];
167
+ pq_sift_down(q, j);
168
+ pq_sift_up(q, j);
169
+ }
170
+ }
171
171
  }
172
-
173
- #ifndef EXCLUDE_UNIT_TEST
174
-
175
- /* Randomly permute the given distance array. */
176
- void permute(PRIORITY_QUEUE_VALUE *a, int size) {
177
- for (int i = size - 1; i > 0; i--) {
178
- int j = rand() % (i + 1);
179
- PRIORITY_QUEUE_VALUE tmp = a[i];
180
- a[i] = a[j];
181
- a[j] = tmp;
182
- }
183
- }
184
-
185
- // Run a unit test on a priority queue of random data with given size.
186
- int pq_test(int size) {
187
- PRIORITY_QUEUE q[1];
188
- pq_init(q);
189
-
190
- fprintf(stderr, "test: heap_ops (n = %d):\n", size);
191
-
192
- // Build linear pointer array of random keys.
193
- PRIORITY_QUEUE_VALUE *dist;
194
- NewArray(dist, size);
195
- for (int i = 0; i < size; i++)
196
- dist[i] = i;
197
- permute(dist, size);
198
- fprintf(stderr, " built random data\n");
199
-
200
- pq_set_up(q, dist, size);
201
- fprintf(stderr, " finished set up\n");
202
-
203
- // Pull min repeatedly and verify vals are what they should be.
204
- PRIORITY_QUEUE_VALUE should_be = 0;
205
- for (int n = 0; n < size; n++) {
206
- int i = pq_get_min(q);
207
- if (dist[i] != should_be++) {
208
- fprintf(stderr, "fail 1: %i -> %g\n", i, dist[i]);
209
- return 42;
210
- }
211
- }
212
- fprintf(stderr, " finished checking heapify\n");
213
-
214
- // Now rebuild the heap by inserting one key at a time.
215
- for (int n = 0; n < size; n++)
216
- pq_add(q, n);
217
- fprintf(stderr, " finished insertions\n");
218
-
219
- // And verify values again.
220
- should_be = 0;
221
- for (int n = 0; n < size; n++) {
222
- int i = pq_get_min(q);
223
- if (dist[i] != should_be++) {
224
- fprintf(stderr, " fail 2: %i -> %g\n", i, dist[i]);
225
- return 4242;
226
- }
227
- }
228
- fprintf(stderr, " finished checking insert\n");
229
-
230
- // Now rebuild the heap by inserting one key at a time in reverse.
231
- for (int n = size - 1; n >= 0; n--)
232
- pq_add(q, n);
233
- fprintf(stderr, " finished reverse insertions\n");
234
-
235
- // Now delete one by one.
236
- for (int n = 0; n < size; n++)
237
- pq_delete(q, n);
238
- fprintf(stderr, " finished reverse deletions\n");
239
-
240
- pq_clear(q);
241
- return 0;
242
- }
243
-
244
- #endif
data/ext/lulu/pq.h CHANGED
@@ -11,11 +11,11 @@
11
11
  typedef double PRIORITY_QUEUE_VALUE;
12
12
 
13
13
  typedef struct priority_queue_s {
14
- int max_size; // max number of items in heap
15
- int size; // current number of items in heap
16
- int *heap; // heap of indices to values
17
- int *locs; // map of value indices to heap locations
18
- PRIORITY_QUEUE_VALUE *values; // values referred to by heap
14
+ int max_size; // max number of items in heap
15
+ int size; // current number of items in heap
16
+ int *heap; // heap of indices to values
17
+ int *locs; // map of value indices to heap locations
18
+ PRIORITY_QUEUE_VALUE *values; // values referred to by heap
19
19
  } PRIORITY_QUEUE;
20
20
 
21
21
  // Initialize a newly allocated priority queue structure.
@@ -34,8 +34,8 @@ void pq_set_up(PRIORITY_QUEUE *q, PRIORITY_QUEUE_VALUE *values, int size);
34
34
  // and given heap indices. Note the indices are owned by the heap
35
35
  // after set up and will be freed with the heap.
36
36
  void pq_set_up_heap(PRIORITY_QUEUE *q,
37
- int *heap, int size,
38
- PRIORITY_QUEUE_VALUE *values, int max_size);
37
+ int *heap, int size,
38
+ PRIORITY_QUEUE_VALUE *values, int max_size);
39
39
 
40
40
  // Return the index of the minimum value on the queue.
41
41
  int pq_peek_min(PRIORITY_QUEUE *q);
@@ -53,18 +53,15 @@ void pq_add(PRIORITY_QUEUE *q, int i);
53
53
  void pq_delete(PRIORITY_QUEUE *q, int i);
54
54
 
55
55
  // Return an array containing indices currently in the heap.
56
- #define pq_index_set(Q) ((Q)->heap)
56
+ #define pq_index_set(Q) ((Q)->heap)
57
57
 
58
58
  // Return an array containing indices currently in the heap.
59
- #define pq_index(Q, I) ((Q)->heap[I])
59
+ #define pq_index(Q, I) ((Q)->heap[I])
60
60
 
61
61
  // Return the size of the index array contained above.
62
- #define pq_index_set_size(Q) ((Q)->size)
62
+ #define pq_index_set_size(Q) ((Q)->size)
63
63
 
64
64
  // Return non-zero iff the queue is empty.
65
65
  #define pq_empty_p(Q) ((Q)->size <= 0)
66
66
 
67
- // Run the heap module through some unit tests.
68
- int pq_test(int size);
69
-
70
67
  #endif /* PRIORITY_QUEUE_H_ */
data/ext/lulu/qt.c CHANGED
@@ -14,31 +14,31 @@
14
14
 
15
15
  // Declare the given quadrant of a given bounding box.
16
16
  #define QUADRANT_DECL(Q, QX, QY, QW, QH, X, Y, W, H) \
17
- double QW = W * 0.5; \
18
- double QH = H * 0.5; \
19
- double QX = (Q & 1) ? X + QW : X; \
20
- double QY = (Q & 2) ? Y + QH : Y
17
+ MARKER_DISTANCE QW = W * 0.5; \
18
+ MARKER_DISTANCE QH = H * 0.5; \
19
+ MARKER_COORD QX = (Q & 1) ? X + QW : X; \
20
+ MARKER_COORD QY = (Q & 2) ? Y + QH : Y
21
21
 
22
22
  // Initialize a node to an empty leaf.
23
23
  static void init_leaf(NODE *node) {
24
- node->children = NULL;
25
- node->markers = NULL;
26
- node->marker_count = node->markers_size = 0;
24
+ node->children = NULL;
25
+ node->markers = NULL;
26
+ node->marker_count = node->markers_size = 0;
27
27
  }
28
28
 
29
29
  // Clear contents of a leaf, returning it to the init_leaf state.
30
30
  static void clear_leaf(NODE *node) {
31
- Free(node->markers);
32
- init_leaf(node);
31
+ Free(node->markers);
32
+ init_leaf(node);
33
33
  }
34
34
 
35
35
  // Make a leaf into an internal node with four empty leaves.
36
36
  static void subdivide(NODE *node) {
37
- if (leaf_p(node)) {
38
- NewArray(node->children, 4);
39
- for (int i = 0; i < 4; i++)
40
- init_leaf(node->children + i);
41
- }
37
+ if (leaf_p(node)) {
38
+ NewArray(node->children, 4);
39
+ for (int i = 0; i < 4; i++)
40
+ init_leaf(node->children + i);
41
+ }
42
42
  }
43
43
 
44
44
  static void clear_node(NODE *node);
@@ -46,254 +46,198 @@ static void clear_node(NODE *node);
46
46
  // Recursively clear an internal node by removing all
47
47
  // subtrees, returning this node to the init_leaf state.
48
48
  static void clear_internal(NODE *node) {
49
- for (int i = 0; i < 4; i++)
50
- clear_node(node->children + i);
51
- Free(node->children);
52
- clear_leaf(node);
49
+ for (int i = 0; i < 4; i++)
50
+ clear_node(node->children + i);
51
+ Free(node->children);
52
+ clear_leaf(node);
53
53
  }
54
54
 
55
55
  // Clear any node, returning it to the init_leaf state.
56
56
  // Recursively removes all subtrees.
57
57
  static void clear_node(NODE *node) {
58
- if (internal_p(node))
59
- clear_internal(node);
60
- else
61
- clear_leaf(node);
58
+ if (internal_p(node))
59
+ clear_internal(node);
60
+ else
61
+ clear_leaf(node);
62
62
  }
63
63
 
64
64
  // Add a marker to the given node's marker list.
65
65
  static void add_marker(NODE *node, MARKER *marker) {
66
- if (node->marker_count == node->markers_size) {
67
- node->markers_size = 2 + 2 * node->markers_size;
68
- RenewArray(node->markers, node->markers_size);
69
- }
70
- node->markers[node->marker_count++] = marker;
66
+ if (node->marker_count == node->markers_size) {
67
+ node->markers_size = 2 + 2 * node->markers_size;
68
+ RenewArray(node->markers, node->markers_size);
69
+ }
70
+ node->markers[node->marker_count++] = marker;
71
71
  }
72
72
 
73
73
  // Find a marker in the given node's marker list.
74
74
  static int find_marker(NODE *node, MARKER *marker) {
75
- for (int i = 0; i < node->marker_count; i++)
76
- if (node->markers[i] == marker)
77
- return i;
78
- return -1;
75
+ for (int i = 0; i < node->marker_count; i++)
76
+ if (node->markers[i] == marker)
77
+ return i;
78
+ return -1;
79
79
  }
80
80
 
81
81
  // Delete a marker from the given node's marker list.
82
82
  static int delete_marker(NODE *node, MARKER *marker) {
83
- int i = find_marker(node, marker);
84
- if (i != -1 && --node->marker_count != 0)
85
- node->markers[i] = node->markers[node->marker_count];
86
- return i;
83
+ int i = find_marker(node, marker);
84
+ if (i != -1 && --node->marker_count != 0)
85
+ node->markers[i] = node->markers[node->marker_count];
86
+ return i;
87
87
  }
88
88
 
89
89
  // Return non-zero iff the given bounding box lies inside the marker including its boundary.
90
- static int bounds_inside_marker(double x, double y, double w, double h, MARKER *marker) {
91
- double mx = mr_x(marker);
92
- double my = mr_y(marker);
93
- double mr = mr_r(marker);
94
- return mx - mr <= x && x + w <= mx + mr && my - mr <= y && y + h <= my + mr ;
90
+ static int bounds_inside_marker(MARKER_COORD x, MARKER_COORD y, MARKER_DISTANCE w, MARKER_DISTANCE h, MARKER *marker) {
91
+ MARKER_COORD mx = mr_x(marker);
92
+ MARKER_COORD my = mr_y(marker);
93
+ MARKER_DISTANCE mr = mr_r(marker);
94
+ return mx - mr <= x && x + w <= mx + mr && my - mr <= y && y + h <= my + mr;
95
95
  }
96
96
 
97
97
  // Return an integer code with bits showing which quadrants of the given
98
98
  // bounding box are overlapped by the given marker.
99
- static int touch_code(double x, double y, double w, double h, MARKER *marker) {
100
- double xm = x + 0.5 * w;
101
- double ym = y + 0.5 * h;
102
- int code = bit(SW) | bit(SE) | bit(NW) | bit(NE);
103
- if (mr_e(marker) < xm) code &= ~(bit(NE) | bit(SE));
104
- if (mr_w(marker) > xm) code &= ~(bit(NW) | bit(SW));
105
- if (mr_n(marker) < ym) code &= ~(bit(NW) | bit(NE));
106
- if (mr_s(marker) > ym) code &= ~(bit(SW) | bit(SE));
107
- return code;
99
+ static int touch_code(MARKER_COORD x, MARKER_COORD y, MARKER_DISTANCE w, MARKER_DISTANCE h, MARKER *marker) {
100
+ MARKER_COORD xm = x + 0.5 * w;
101
+ MARKER_COORD ym = y + 0.5 * h;
102
+ int code = bit(SW) | bit(SE) | bit(NW) | bit(NE);
103
+ if (mr_e(marker) < xm) code &= ~(bit(NE) | bit(SE));
104
+ if (mr_w(marker) > xm) code &= ~(bit(NW) | bit(SW));
105
+ if (mr_n(marker) < ym) code &= ~(bit(NW) | bit(NE));
106
+ if (mr_s(marker) > ym) code &= ~(bit(SW) | bit(SE));
107
+ return code;
108
108
  }
109
109
 
110
110
  // Insert the given marker into the quadtree with given root and corresponding bounding box,
111
111
  // subdividing no more than the given number of levels.
112
- static void insert(NODE *node, int levels, double x, double y, double w, double h, MARKER *marker) {
113
- if (bounds_inside_marker(x, y, w, h, marker) || levels == 0)
114
- add_marker(node, marker);
115
- else {
116
- if (leaf_p(node))
117
- subdivide(node);
118
- int code = touch_code(x, y, w, h, marker);
119
- for (int q = 0; q < 4; q++)
120
- if (code & bit(q)) {
121
- QUADRANT_DECL(q, qx, qy, qw, qh, x, y, w, h);
122
- insert(node->children + q, levels - 1, qx, qy, qw, qh, marker);
123
- }
124
- }
112
+ static void insert(NODE *node, int levels, MARKER_COORD x, MARKER_COORD y, MARKER_DISTANCE w, MARKER_DISTANCE h, MARKER *marker) {
113
+ if (bounds_inside_marker(x, y, w, h, marker) || levels == 0)
114
+ add_marker(node, marker);
115
+ else {
116
+ if (leaf_p(node))
117
+ subdivide(node);
118
+ int code = touch_code(x, y, w, h, marker);
119
+ for (int q = 0; q < 4; q++)
120
+ if (code & bit(q)) {
121
+ QUADRANT_DECL(q, qx, qy, qw, qh, x, y, w, h);
122
+ insert(node->children + q, levels - 1, qx, qy, qw, qh, marker);
123
+ }
124
+ }
125
125
  }
126
126
 
127
127
  // A helper function that returns true iff the given array of 4 child quadtrees are all empty leaves.
128
128
  static int empty_leaves_p(NODE *children) {
129
- for (int i = 0; i < 4; i++)
130
- if (internal_p(children + i) || children[i].marker_count > 0)
131
- return 0;
132
- return 1;
129
+ for (int i = 0; i < 4; i++)
130
+ if (internal_p(children + i) || children[i].marker_count > 0)
131
+ return 0;
132
+ return 1;
133
133
  }
134
134
 
135
135
  // Delete the given marker from the quadtree with given root and corresponding bounding box,
136
136
  // trimming any remaining empty leaves.
137
- static void delete(NODE *node, int levels, double x, double y, double w, double h, MARKER *marker) {
138
- if (bounds_inside_marker(x, y, w, h, marker) || levels == 0)
139
- delete_marker(node, marker);
140
- else if (internal_p(node)){
141
- int code = touch_code(x, y, w, h, marker);
142
- for (int q = 0; q < 4; q++)
143
- if (code & bit(q)) {
144
- QUADRANT_DECL(q, qx, qy, qw, qh, x, y, w, h);
145
- delete(node->children + q, levels - 1, qx, qy, qw, qh, marker);
146
- }
147
- if (empty_leaves_p(node->children))
148
- Free(node->children);
149
- }
137
+ static void delete(NODE *node, int levels,
138
+ MARKER_COORD x, MARKER_COORD y, MARKER_DISTANCE w, MARKER_DISTANCE h,
139
+ MARKER *marker) {
140
+ if (bounds_inside_marker(x, y, w, h, marker) || levels == 0)
141
+ delete_marker(node, marker);
142
+ else if (internal_p(node)){
143
+ int code = touch_code(x, y, w, h, marker);
144
+ for (int q = 0; q < 4; q++)
145
+ if (code & bit(q)) {
146
+ QUADRANT_DECL(q, qx, qy, qw, qh, x, y, w, h);
147
+ delete(node->children + q, levels - 1, qx, qy, qw, qh, marker);
148
+ }
149
+ if (empty_leaves_p(node->children))
150
+ Free(node->children);
151
+ }
150
152
  }
151
153
 
152
154
  // Local struct to hold information about the nearest marker seen so far in a search.
153
155
  struct nearest_info {
154
156
  MARKER_INFO *info;
155
157
  MARKER *target, *nearest;
156
- double distance;
158
+ MARKER_DISTANCE distance;
157
159
  };
158
160
 
159
161
  // Use the marker list of the given node to update nearest information with
160
162
  // respect to the given marker.
161
163
  static void update_nearest(NODE *node, struct nearest_info *nearest_info) {
162
- for (int i = 0; i < node->marker_count; i++) {
163
- // This < assumes the markers are in an array. It sustains the invariant.
164
- if (node->markers[i] < nearest_info->target) {
165
- double d = mr_distance(nearest_info->info, nearest_info->target, node->markers[i]);
166
- if (d < nearest_info->distance) {
167
- nearest_info->distance = d;
168
- nearest_info->nearest = node->markers[i];
169
- }
170
- }
171
- }
164
+ for (int i = 0; i < node->marker_count; i++) {
165
+ // This < assumes the markers are in an array. It sustains the invariant.
166
+ if (node->markers[i] < nearest_info->target) {
167
+ MARKER_DISTANCE d = mr_distance(nearest_info->info, nearest_info->target, node->markers[i]);
168
+ if (d < nearest_info->distance) {
169
+ nearest_info->distance = d;
170
+ nearest_info->nearest = node->markers[i];
171
+ }
172
+ }
173
+ }
172
174
  }
173
175
 
174
176
  // Search out the nearest marker that overlaps the given one. This just visits every
175
177
  // quad that overlaps the given marker and remembers the closest marker it sees. The
176
178
  // circle distance function renders quite impossible the ruling out of quads as in
177
179
  // nearest point neighbor search.
178
- static void search_for_nearest(NODE *node, double x, double y, double w, double h, struct nearest_info *nearest_info) {
179
- update_nearest(node, nearest_info);
180
- if (internal_p(node)) {
181
- // Search the children that include some part of the marker.
182
- int code = touch_code(x, y, w, h, nearest_info->target);
183
- for (int q = 0; q < 4; q++)
184
- if (code & bit(q)) {
185
- QUADRANT_DECL(q, qx, qy, qw, qh, x, y, w, h);
186
- search_for_nearest(node->children + q, qx, qy, qw, qh, nearest_info);
187
- }
188
- }
189
- }
190
-
191
- static MARKER *nearest(MARKER_INFO *info, NODE *node, double x, double y, double w, double h, MARKER *marker) {
192
- struct nearest_info nearest_info[1] = {{ info, marker, NULL, 0 }};
193
- search_for_nearest(node, x, y, w, h, nearest_info);
194
- return nearest_info->nearest;
180
+ static void search_for_nearest(NODE *node,
181
+ MARKER_COORD x, MARKER_COORD y, MARKER_DISTANCE w, MARKER_DISTANCE h,
182
+ struct nearest_info *nearest_info) {
183
+ update_nearest(node, nearest_info);
184
+ if (internal_p(node)) {
185
+ // Search the children that include some part of the marker.
186
+ int code = touch_code(x, y, w, h, nearest_info->target);
187
+ for (int q = 0; q < 4; q++)
188
+ if (code & bit(q)) {
189
+ QUADRANT_DECL(q, qx, qy, qw, qh, x, y, w, h);
190
+ search_for_nearest(node->children + q, qx, qy, qw, qh, nearest_info);
191
+ }
192
+ }
193
+ }
194
+
195
+ static MARKER *nearest(MARKER_INFO *info, NODE *node,
196
+ MARKER_COORD x, MARKER_COORD y, MARKER_DISTANCE w, MARKER_DISTANCE h,
197
+ MARKER *marker) {
198
+ struct nearest_info nearest_info[1] = {{ info, marker, NULL, 0 }};
199
+ search_for_nearest(node, x, y, w, h, nearest_info);
200
+ return nearest_info->nearest;
195
201
  }
196
202
 
197
203
  void qt_init(QUADTREE *qt) {
198
- init_leaf(qt->root);
199
- qt->x = qt->y = qt->w = qt->h = 0;
204
+ init_leaf(qt->root);
205
+ qt->x = qt->y = qt->w = qt->h = 0;
200
206
  }
201
207
 
202
- void qt_setup(QUADTREE *qt, int max_depth, double x, double y, double w, double h, MARKER_INFO *info) {
203
- qt->x = x;
204
- qt->y = y;
205
- qt->w = w;
206
- qt->h = h;
207
- qt->max_depth = max_depth;
208
- qt->info = info;
208
+ void qt_setup(QUADTREE *qt, int max_depth,
209
+ MARKER_COORD x, MARKER_COORD y, MARKER_DISTANCE w, MARKER_DISTANCE h,
210
+ MARKER_INFO *info) {
211
+ qt->x = x;
212
+ qt->y = y;
213
+ qt->w = w;
214
+ qt->h = h;
215
+ qt->max_depth = max_depth;
216
+ qt->info = info;
209
217
  }
210
218
 
211
219
  void qt_clear(QUADTREE *qt) {
212
- clear_node(qt->root);
213
- qt_init(qt);
220
+ clear_node(qt->root);
221
+ qt_init(qt);
214
222
  }
215
223
 
216
224
  void qt_insert(QUADTREE *qt, MARKER *marker) {
217
- double x = mr_x(marker);
218
- double y = mr_y(marker);
219
- double r = mr_r(marker);
220
- if (x + r >= qt->x && x - r <= qt->x + qt->w && y + r >= qt->y && y - r <= qt->y + qt->h)
221
- insert(qt->root, qt->max_depth, qt->x, qt->y, qt->w, qt->h, marker);
225
+ MARKER_COORD x = mr_x(marker);
226
+ MARKER_COORD y = mr_y(marker);
227
+ MARKER_DISTANCE r = mr_r(marker);
228
+ if (x + r >= qt->x && x - r <= qt->x + qt->w && y + r >= qt->y && y - r <= qt->y + qt->h)
229
+ insert(qt->root, qt->max_depth, qt->x, qt->y, qt->w, qt->h, marker);
222
230
  }
223
231
 
224
232
  void qt_delete(QUADTREE *qt, MARKER *marker) {
225
- delete(qt->root, qt->max_depth, qt->x, qt->y, qt->w, qt->h, marker);
233
+ delete(qt->root, qt->max_depth, qt->x, qt->y, qt->w, qt->h, marker);
226
234
  }
227
235
 
228
236
  MARKER *qt_nearest(QUADTREE *qt, MARKER *marker) {
229
- return nearest(qt->info, qt->root, qt->x, qt->y, qt->w, qt->h, marker);
237
+ return nearest(qt->info, qt->root, qt->x, qt->y, qt->w, qt->h, marker);
230
238
  }
231
239
 
232
240
  int qt_nearest_wrt(MARKER *markers, QUADTREE *qt, int a) {
233
- MARKER *nearest = qt_nearest(qt, markers + a);
234
- return nearest ? (int)(nearest - markers) : -1;
235
- }
236
-
237
- #ifndef EXCLUDE_UNIT_TEST
238
-
239
- static void draw(FILE *f, NODE *node, double x, double y, double w, double h) {
240
- emit_rectangle(f, x, y, w, h);
241
- emit_marker_ptr_array(f, node->markers, node->marker_count);
242
- if (internal_p(node)) {
243
- for (int q = 0; q < 4; q++) {
244
- QUADRANT_DECL(q, qx, qy, qw, qh, x, y, w, h);
245
- draw(f, node->children + q, qx, qy, qw, qh);
246
- }
247
- }
248
- }
249
-
250
- static void draw_nearest(FILE *f, MARKER *markers, MARKER **nearest_markers, int n_markers) {
251
- for (int i = 0; i < n_markers; i++) {
252
- if (nearest_markers[i])
253
- emit_segment(f, markers + i, nearest_markers[i]);
254
- }
241
+ MARKER *nearest = qt_nearest(qt, markers + a);
242
+ return nearest ? (int)(nearest - markers) : -1;
255
243
  }
256
-
257
- int qt_draw(QUADTREE *qt, MARKER *markers, MARKER **nearest_markers, int n_markers, const char *name) {
258
- char buf[1024];
259
- sprintf(buf, "test/%s.js", name);
260
- FILE *f = fopen(buf, "w");
261
- if (!f)
262
- return -1;
263
- fprintf(f, "var %s = [\n", name);
264
- draw(f, qt->root, qt->x, qt->y, qt->w, qt->h);
265
- draw_nearest(f, markers, nearest_markers, n_markers);
266
- fprintf(f, "];\n");
267
- fclose(f);
268
- return EXIT_SUCCESS;
269
- }
270
-
271
- int qt_test(int size) {
272
- QUADTREE_DECL(qt);
273
- MARKER_INFO_DECL(info);
274
- MARKER *markers, **nearest_markers;
275
- NewArray(markers, size);
276
- NewArray(nearest_markers, size);
277
- set_random_markers(info, markers, size);
278
- qt_setup(qt, 5, 0, 0, 1024, 724, info);
279
- fprintf(stderr, "inserting %d:\n", size);
280
- for (int i = 0; i < size; i++) {
281
- qt_insert(qt, markers + i);
282
- }
283
- fprintf(stderr, "inserted %d\n", size);
284
- for (int i = 0; i < size; i++) {
285
- nearest_markers[i] = qt_nearest(qt, markers + i);
286
- }
287
- fprintf(stderr, "looked up %d\n", size);
288
- qt_draw(qt, markers, nearest_markers, size, "qt");
289
- fprintf(stderr, "drew %d\n", size);
290
- for (int i = 0; i < size; i++) {
291
- qt_delete(qt, markers + i);
292
- }
293
- fprintf(stderr, "after delete all, root is %s\n",
294
- leaf_p(qt->root) ? "leaf (ok)" : "internal (not ok)");
295
-
296
- return EXIT_SUCCESS;
297
- }
298
-
299
- #endif