3 #define IMAGE_SEARCH_DIST_UNLIMITED (~0U)
5 /* FIXME: support full length of oid_t, currently must be <2^31 */
6 #define IMAGE_SEARCH_ITEM_TYPE 0x80000000U
7 struct image_search_item {
10 struct image_bbox bbox;
13 #define IMAGE_SEARCH_CMP(x,y) (is->buf[x].dist < is->buf[y].dist)
16 struct image_tree *tree;
17 struct image_node *nodes;
18 struct image_leaf *leaves;
19 struct image_vector query;
20 struct image_search_item *buf;
22 uns count, visited, size, max_dist;
25 #define SQR(x) ((x)*(x))
28 image_search_init(struct image_search *is, struct image_tree *tree, struct image_vector *query, uns max_dist)
32 is->nodes = tree->nodes;
33 is->leaves = tree->leaves;
35 is->max_dist = max_dist;
37 is->buf = xmalloc((is->size + 1) * sizeof(struct image_search_item));
38 is->heap = xmalloc((is->size + 1) * sizeof(u32));
39 is->visited = is->count = 1;
41 struct image_search_item *item = is->buf + 1;
43 item->bbox = tree->bbox;
45 for (uns i = 0; i < IMAGE_VEC_K; i++)
47 if (query->f[i] < item->bbox.vec[0].f[i])
48 item->dist += SQR(item->bbox.vec[0].f[i] - query->f[i]);
49 else if (query->f[i] > item->bbox.vec[1].f[i])
50 item->dist += SQR(query->f[i] - item->bbox.vec[0].f[i]);
60 image_search_done(struct image_search *is)
67 image_search_grow_slow(struct image_search *is)
70 is->buf = xrealloc(is->buf, (is->size + 1) * sizeof(struct image_search_item));
71 is->heap = xrealloc(is->heap, (is->size + 1) * sizeof(u32));
74 static inline struct image_search_item *
75 image_search_grow(struct image_search *is)
77 if (is->count == is->visited)
79 if (is->count == is->size)
80 image_search_grow_slow(is);
82 is->heap[is->visited] = is->visited;
84 return is->buf + is->heap[++is->count];
88 image_search_leaf_dist(struct image_search *is, struct image_bbox *bbox, struct image_leaf *leaf)
91 uns flags = leaf->flags;
92 for (uns i = 0; i < IMAGE_VEC_K; i++)
94 uns bits = IMAGE_LEAF_BITS(i);
95 uns mask = (1 << bits) - 1;
96 uns value = flags & mask;
98 int dif = bbox->vec[0].f[i] + (bbox->vec[1].f[i] - bbox->vec[0].f[i]) * value / ((1 << bits) - 1) - is->query.f[i];
105 image_search_next(struct image_search *is, oid_t *oid, uns *dist)
107 while (likely(is->count))
109 struct image_search_item *item = is->buf + is->heap[1];
110 DBG("Main loop... dist=%d count=%d visited=%d size=%d index=0x%08x bbox=[(%s),(%s)]",
111 item->dist, is->count, is->visited, is->size, item->index,
112 stk_print_image_vector(&item->bbox.vec[0]), stk_print_image_vector(&item->bbox.vec[1]));
113 if (unlikely(item->dist > is->max_dist))
115 DBG("Maximum distance reached");
120 if (item->index & IMAGE_SEARCH_ITEM_TYPE)
122 *oid = item->index & ~IMAGE_SEARCH_ITEM_TYPE;
124 DBG("Found item %d at distance %d", *oid, *dist);
125 HEAP_DELMIN(u32, is->heap, is->count, IMAGE_SEARCH_CMP, HEAP_SWAP);
129 /* Expand node with leaves */
130 else if (is->nodes[item->index].val & IMAGE_NODE_LEAF)
132 DBG("Expanding node to list of leaves");
133 struct image_leaf *leaf = is->leaves + (is->nodes[item->index].val & ~IMAGE_NODE_LEAF);
134 item->dist = image_search_leaf_dist(is, &item->bbox, leaf);
135 item->index = IMAGE_SEARCH_ITEM_TYPE | leaf->oid;
136 HEAP_INCREASE(u32, is->heap, is->count, IMAGE_SEARCH_CMP, HEAP_SWAP, 1);
137 while (!((leaf++)->flags & IMAGE_LEAF_LAST))
139 struct image_search_item *nitem = image_search_grow(is);
140 nitem->dist = image_search_leaf_dist(is, &item->bbox, leaf);
141 nitem->index = IMAGE_SEARCH_ITEM_TYPE | leaf->oid;
142 HEAP_INSERT(u32, is->heap, is->count, IMAGE_SEARCH_CMP, HEAP_SWAP);
146 /* Expand internal node */
149 DBG("Expanding internal node");
150 struct image_search_item *nitem = image_search_grow(is);
151 uns dim = is->nodes[item->index].val & IMAGE_NODE_DIM;
152 uns pivot = is->nodes[item->index].val >> 8;
154 nitem->bbox = item->bbox;
155 nitem->dist = item->dist;
156 uns query = is->query.f[dim];
157 int dif = query - pivot;
160 nitem->index = item->index++;
161 item->bbox.vec[0].f[dim] = pivot;
162 nitem->bbox.vec[1].f[dim] = pivot;
163 if (query > item->bbox.vec[1].f[dim])
164 nitem->dist -= SQR(query - item->bbox.vec[1].f[dim]);
168 nitem->index = item->index + 1;
169 item->bbox.vec[1].f[dim] = pivot;
170 nitem->bbox.vec[0].f[dim] = pivot;
171 if (query < item->bbox.vec[0].f[dim])
172 nitem->dist -= SQR(item->bbox.vec[0].f[dim] - query);
174 nitem->dist += SQR(dif);
175 HEAP_INSERT(u32, is->heap, is->count, IMAGE_SEARCH_CMP, HEAP_SWAP);
178 DBG("Heap is empty");