bool Channel::read_tile_or_closest_ancestor(TileIndex ti, TileIndex &ret_index, Tile &ret) const { Locker lock(*this); // Lock self and hold lock until exiting this method ChannelInfo info; bool success = read_info(info); if (!success) { if (verbosity) log_f("read_tile_or_closest_ancestor: can't read info"); return false; } TileIndex root = info.nonnegative_root_tile_index; if (ti.is_ancestor_of(root)) { ret_index = root; } else { if (ti != root && !root.is_ancestor_of(ti)) { // Tile isn't under root return false; } assert(tile_exists(root)); ret_index = root; while (ret_index != ti) { TileIndex child = ti.start_time() < ret_index.left_child().end_time() ? ret_index.left_child() : ret_index.right_child(); if (!tile_exists(child)) break; ret_index = child; } } // ret_index now holds closest ancestor to ti (or ti itself if it exists) assert(read_tile(ret_index, ret)); return true; }
TileIndex Channel::find_successive_tile(TileIndex root, TileIndex ti, int desired_level) const { // Move upwards until parent has a different end time while (1) { if (ti.parent().is_null()) return TileIndex::null(); if (ti.parent().end_time() != ti.end_time()) break; ti = ti.parent(); if (ti.level >= root.level) { // No more underneath the root return TileIndex::null(); } } // We are now the left child of our parent; skip to the right child ti = ti.sibling(); return find_child_overlapping_time(ti, ti.start_time(), desired_level); }
void Channel::read_bottommost_tiles_in_range(Range times, bool (*callback)(const Tile &t, Range times)) const { ChannelInfo info; bool success = read_info(info); if (!success) return; if (!info.times.intersects(times)) return; double time = times.min; TileIndex ti = TileIndex::null(); while (time < times.max) { if (ti.is_null()) { ti = find_lowest_child_overlapping_time(info.nonnegative_root_tile_index, times.min); } else { ti = find_lowest_successive_tile(info.nonnegative_root_tile_index, ti); } if (ti.is_null() || ti.start_time() >= times.max) break; Tile t; assert(read_tile(ti, t)); if (!(*callback)(t, times)) break; } }