1 #include "canvas/lookup_table.h"
2 #include "canvas/group.h"
5 using namespace ArdourCanvas;
7 LookupTable::LookupTable (Group const & group)
13 LookupTable::~LookupTable ()
18 DumbLookupTable::DumbLookupTable (Group const & group)
25 DumbLookupTable::get (Rect const &)
27 list<Item *> const & items = _group.items ();
28 vector<Item *> vitems;
29 copy (items.begin(), items.end(), back_inserter (vitems));
33 /* XXX: what coordinate system is the point in? parent of our group I think */
35 DumbLookupTable::items_at_point (Duple point) const
37 list<Item *> items = _group.items ();
38 vector<Item *> vitems;
40 for (list<Item *>::const_iterator i = items.begin(); i != items.end(); ++i) {
41 boost::optional<Rect> item_bbox = (*i)->bounding_box ();
43 Rect parent_bbox = (*i)->item_to_parent (item_bbox.get ());
44 if (parent_bbox.contains (point)) {
45 vitems.push_back (*i);
53 OptimizingLookupTable::OptimizingLookupTable (Group const & group, int items_per_cell)
55 , _items_per_cell (items_per_cell)
58 list<Item*> const & items = _group.items ();
61 int const cells = items.size() / _items_per_cell;
62 /* hence number down each side of the table's square */
63 _dimension = max (1, int (rint (sqrt (cells))));
65 _cells = new Cell*[_dimension];
66 for (int i = 0; i < _dimension; ++i) {
67 _cells[i] = new Cell[_dimension];
70 /* our group's bounding box in its coordinates */
71 boost::optional<Rect> bbox = _group.bounding_box ();
76 _cell_size.x = bbox.get().width() / _dimension;
77 _cell_size.y = bbox.get().height() / _dimension;
78 _offset.x = bbox.get().x0;
79 _offset.y = bbox.get().y0;
81 // cout << "BUILD bbox=" << bbox.get() << ", cellsize=" << _cell_size << ", offset=" << _offset << ", dimension=" << _dimension << "\n";
83 for (list<Item*>::const_iterator i = items.begin(); i != items.end(); ++i) {
85 /* item bbox in its own coordinates */
86 boost::optional<Rect> item_bbox = (*i)->bounding_box ();
91 /* and in the group's coordinates */
92 Rect const item_bbox_in_group = (*i)->item_to_parent (item_bbox.get ());
95 area_to_indices (item_bbox_in_group, x0, y0, x1, y1);
102 //assert (x0 <= _dimension);
103 //assert (y0 <= _dimension);
104 //assert (x1 <= _dimension);
105 //assert (y1 <= _dimension);
107 if (x0 > _dimension) {
108 cout << "WARNING: item outside bbox by " << (item_bbox_in_group.x0 - bbox.get().x0) << "\n";
111 if (x1 > _dimension) {
112 cout << "WARNING: item outside bbox by " << (item_bbox_in_group.x1 - bbox.get().x1) << "\n";
115 if (y0 > _dimension) {
116 cout << "WARNING: item outside bbox by " << (item_bbox_in_group.y0 - bbox.get().y0) << "\n";
119 if (y1 > _dimension) {
120 cout << "WARNING: item outside bbox by " << (item_bbox_in_group.y1 - bbox.get().y1) << "\n";
124 for (int x = x0; x < x1; ++x) {
125 for (int y = y0; y < y1; ++y) {
126 _cells[x][y].push_back (*i);
133 OptimizingLookupTable::area_to_indices (Rect const & area, int& x0, int& y0, int& x1, int& y1) const
135 if (_cell_size.x == 0 || _cell_size.y == 0) {
136 x0 = y0 = x1 = y1 = 0;
140 Rect const offset_area = area.translate (-_offset);
142 x0 = floor (offset_area.x0 / _cell_size.x);
143 y0 = floor (offset_area.y0 / _cell_size.y);
144 x1 = ceil (offset_area.x1 / _cell_size.x);
145 y1 = ceil (offset_area.y1 / _cell_size.y);
148 OptimizingLookupTable::~OptimizingLookupTable ()
150 for (int i = 0; i < _dimension; ++i) {
158 OptimizingLookupTable::point_to_indices (Duple point, int& x, int& y) const
160 if (_cell_size.x == 0 || _cell_size.y == 0) {
165 Duple const offset_point = point - _offset;
167 x = floor (offset_point.x / _cell_size.x);
168 y = floor (offset_point.y / _cell_size.y);
172 OptimizingLookupTable::items_at_point (Duple point) const
176 point_to_indices (point, x, y);
178 if (x >= _dimension) {
179 cout << "WARNING: x=" << x << ", dim=" << _dimension << ", px=" << point.x << " cellsize=" << _cell_size << "\n";
182 if (y >= _dimension) {
183 cout << "WARNING: y=" << y << ", dim=" << _dimension << ", py=" << point.y << " cellsize=" << _cell_size << "\n";
187 x = min (_dimension - 1, x);
188 y = min (_dimension - 1, y);
193 Cell const & cell = _cells[x][y];
195 for (Cell::const_iterator i = cell.begin(); i != cell.end(); ++i) {
196 boost::optional<Rect> const item_bbox = (*i)->bounding_box ();
198 Rect parent_bbox = (*i)->item_to_parent (item_bbox.get ());
199 if (parent_bbox.contains (point)) {
200 items.push_back (*i);
208 /** @param area Area in our owning group's coordinates */
210 OptimizingLookupTable::get (Rect const & area)
214 area_to_indices (area, x0, y0, x1, y1);
217 x0 = min (_dimension - 1, x0);
218 y0 = min (_dimension - 1, y0);
219 x1 = min (_dimension, x1);
220 y1 = min (_dimension, y1);
222 for (int x = x0; x < x1; ++x) {
223 for (int y = y0; y < y1; ++y) {
224 for (Cell::const_iterator i = _cells[x][y].begin(); i != _cells[x][y].end(); ++i) {
225 if (find (items.begin(), items.end(), *i) == items.end ()) {
226 items.push_back (*i);
232 vector<Item*> vitems;
233 copy (items.begin (), items.end (), back_inserter (vitems));