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; }
const Airspaces::AirspaceVector Airspaces::find_inside(const AircraftState &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 (auto 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_range(const GeoPoint &location, const fixed range, const AirspacePredicate &condition) const { if (empty()) return AirspaceVector(); // nothing to do 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 (auto 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; }
void AirspaceNearestSort::populate_queue(const Airspaces &airspaces, const fixed range) { AirspacesInterface::AirspaceVector vectors = airspaces.scan_range(m_location, range, m_condition); for (auto v = vectors.begin(); v != vectors.end(); ++v) { const AbstractAirspace *as = v->get_airspace(); if (as != NULL) { const AirspaceInterceptSolution ais = solve_intercept(*as); const fixed value = metric(ais); if (!negative(value)) { m_q.push(std::make_pair(m_reverse? -value:value, std::make_pair(ais, *v))); } } } }
void Airspaces::optimise() { if (!m_owner || task_projection.update_fast()) { // dont update task_projection if not owner! // task projection changed, so need to push items back onto stack // to re-build airspace envelopes for (auto it = airspace_tree.begin(); it != airspace_tree.end(); ++it) tmp_as.push_back(it->get_airspace()); airspace_tree.clear(); } if (!tmp_as.empty()) { while (!tmp_as.empty()) { Airspace as(*tmp_as.front(), task_projection); airspace_tree.insert(as); tmp_as.pop_front(); } airspace_tree.optimise(); } }
/** * Equality operator, matches if contained airspace is the same */ bool operator==(Airspace const& a) const { return (get_airspace() == a.get_airspace()); }