const Airspaces::AirspaceVector Airspaces::find_inside(const AIRCRAFT_STATE &state, const AirspacePredicate &condition) const { Airspace bb_target(state.Location, task_projection); AirspaceVector vectors; airspace_tree.find_within_range(bb_target, 0, std::back_inserter(vectors)); #ifdef INSTRUMENT_TASK n_queries++; #endif for (AirspaceVector::iterator v = vectors.begin(); v != vectors.end();) { #ifdef INSTRUMENT_TASK count_intersections++; #endif if (!condition(*v->get_airspace()) || !(*v).inside(state)) vectors.erase(v); else ++v; } return vectors; }
bool Airspaces::synchronise_in_range(const Airspaces& master, const GeoPoint &location, const fixed range, const AirspacePredicate &condition) { bool changed = false; const AirspaceVector contents_master = master.scan_range(location, range, condition); AirspaceVector contents_self; contents_self.reserve(max(airspace_tree.size(), contents_master.size())); task_projection = master.task_projection; // ensure these are up to date for (auto t = airspace_tree.begin(); t != airspace_tree.end(); ++t) contents_self.push_back(*t); // find items to add for (auto v = contents_master.begin(); v != contents_master.end(); ++v) { const AbstractAirspace* other = v->get_airspace(); bool found = false; for (auto s = contents_self.begin(); s != contents_self.end(); ++s) { const AbstractAirspace* self = s->get_airspace(); if (self == other) { found = true; contents_self.erase(s); break; } } if (!found && other->IsActive()) { insert(v->get_airspace()); changed = true; } } // anything left in the self list are items that were not in the query, // so delete them --- including the clearances! for (auto v = contents_self.begin(); v != contents_self.end();) { bool found = false; for (auto t = airspace_tree.begin(); t != airspace_tree.end(); ) { if (t->get_airspace() == v->get_airspace()) { AirspaceTree::const_iterator new_t = t; ++new_t; airspace_tree.erase_exact(*t); t = new_t; found = true; } else { ++t; } } assert(found); v->clear_clearance(); v = contents_self.erase(v); changed = true; } if (changed) optimise(); return changed; }
void Airspaces::visit_inside(const GeoPoint &loc, AirspaceVisitor& visitor) const { if (empty()) return; // nothing to do Airspace bb_target(loc, task_projection); AirspaceVector vectors; airspace_tree.find_within_range(bb_target, 0, std::back_inserter(vectors)); for (auto v = vectors.begin(); v != vectors.end(); ++v) { if ((*v).inside(loc)) visitor.Visit(*v); } }