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; }
const Airspaces::AirspaceVector Airspaces::scan_nearest(const GeoPoint &location, const AirspacePredicate &condition) const { Airspace bb_target(location, task_projection); std::pair<AirspaceTree::const_iterator, double> found = airspace_tree.find_nearest(bb_target); #ifdef INSTRUMENT_TASK n_queries++; #endif AirspaceVector res; if (found.first != airspace_tree.end()) { // also should do scan_range with range = 0 since there // could be more than one with zero dist if (found.second == 0) { return scan_range(location, fixed_zero, condition); } else { if (condition(*found.first->get_airspace())) res.push_back(*found.first); } } return res; }
const Airspaces::AirspaceVector Airspaces::scan_range(const GeoPoint &location, const fixed range, const AirspacePredicate &condition) const { Airspace bb_target(location, task_projection); int mrange = task_projection.project_range(location, range); std::deque< Airspace > vectors; airspace_tree.find_within_range(bb_target, -mrange, std::back_inserter(vectors)); #ifdef INSTRUMENT_TASK n_queries++; #endif AirspaceVector res; for (std::deque<Airspace>::iterator v = vectors.begin(); v != vectors.end(); ++v) { if (!condition(*v->get_airspace())) continue; if (fixed((*v).distance(bb_target)) > range) continue; if ((*v).inside(location) || positive(range)) res.push_back(*v); } return res; }
const Airspaces::AirspaceVector Airspaces::ScanRange(const GeoPoint &location, fixed range, const AirspacePredicate &condition) const { if (empty()) // nothing to do return AirspaceVector(); Airspace bb_target(location, task_projection); int projected_range = task_projection.ProjectRangeInteger(location, range); std::deque< Airspace > vectors; airspace_tree.find_within_range(bb_target, -projected_range, std::back_inserter(vectors)); #ifdef INSTRUMENT_TASK n_queries++; #endif AirspaceVector res; for (const auto &v : vectors) { if (!condition(*v.GetAirspace())) continue; if (fixed(v.Distance(bb_target)) > range) continue; if (v.IsInside(location) || positive(range)) res.push_back(v); } return res; }
const Airspaces::AirspaceVector Airspaces::FindInside(const AircraftState &state, const AirspacePredicate &condition) const { Airspace bb_target(state.location, task_projection); AirspaceVector vectors; #ifdef INSTRUMENT_TASK n_queries++; #endif std::function<void(const Airspace &)> visitor = [&state, &condition, &vectors](const Airspace &v){ #ifdef INSTRUMENT_TASK count_intersections++; #endif if (condition(v.GetAirspace()) && v.IsInside(state)) vectors.push_back(v); }; airspace_tree.visit_within_range(bb_target, 0, visitor); return vectors; }
const Airspaces::AirspaceVector Airspaces::ScanRange(const GeoPoint &location, fixed range, const AirspacePredicate &condition) const { if (IsEmpty()) // nothing to do return AirspaceVector(); Airspace bb_target(location, task_projection); int projected_range = task_projection.ProjectRangeInteger(location, range); #ifdef INSTRUMENT_TASK n_queries++; #endif AirspaceVector res; std::function<void(const Airspace &)> visitor = [&location, range, &condition, &bb_target, &res](const Airspace &v){ if (condition(v.GetAirspace()) && fixed(v.Distance(bb_target)) <= range && (v.IsInside(location) || positive(range))) res.push_back(v); }; airspace_tree.visit_within_range(bb_target, -projected_range, visitor); return res; }
const Airspaces::AirspaceVector Airspaces::ScanNearest(const GeoPoint &location, const AirspacePredicate &condition) const { if (empty()) // nothing to do return AirspaceVector(); Airspace bb_target(location, task_projection); std::pair<AirspaceTree::const_iterator, AirspaceTree::distance_type> found = airspace_tree.find_nearest(bb_target); #ifdef INSTRUMENT_TASK n_queries++; #endif AirspaceVector res; if (found.first != airspace_tree.end()) { // also should do scan_range with range = 0 since there // could be more than one with zero dist if (found.second.is_zero()) return ScanRange(location, fixed_zero, condition); if (condition(*found.first->GetAirspace())) res.push_back(*found.first); } return res; }
bool Airspaces::SynchroniseInRange(const Airspaces& master, const GeoPoint &location, const fixed range, const AirspacePredicate &condition) { bool changed = false; const AirspaceVector contents_master = master.ScanRange(location, range, condition); AirspaceVector contents_self; contents_self.reserve(std::max(airspace_tree.size(), contents_master.size())); task_projection = master.task_projection; // ensure these are up to date for (const auto &v : airspace_tree) contents_self.push_back(v); // find items to add for (const auto &v : contents_master) { const AbstractAirspace* other = v.GetAirspace(); bool found = false; for (auto s = contents_self.begin(); s != contents_self.end(); ++s) { const AbstractAirspace* self = s->GetAirspace(); if (self == other) { found = true; contents_self.erase(s); break; } } if (!found && other->IsActive()) { Add(v.GetAirspace()); 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->GetAirspace() == v->GetAirspace()) { AirspaceTree::const_iterator new_t = t; ++new_t; airspace_tree.erase_exact(*t); t = new_t; found = true; } else { ++t; } } assert(found); v->ClearClearance(); v = contents_self.erase(v); changed = true; } if (changed) Optimise(); return changed; }
inline AirspacesInterface::AirspaceVector Airspaces::AsVector() const { AirspaceVector v; v.reserve(airspace_tree.size()); for (const auto &i : QueryAll()) v.push_back(i); return v; }
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); } }