void write_point(const SearchPoint& sp, const FlatGeoPoint& p, const char* name) { printf("%g %g %d %d # %s\n", (double)sp.get_location().longitude.Degrees(), (double)sp.get_location().latitude.Degrees(), p.Longitude, p.Latitude, name); fflush(stdout); }
gcc_pure static bool IsInRange(const SearchPoint &a, const SearchPoint &b, unsigned half_max_range_sq, double max_distance) { /* optimisation: if the flat distance is much smaller than the maximum range, we don't need to call the method GeoPoint::Distance() which is very expensive */ return a.GetFlatLocation().DistanceSquared(b.GetFlatLocation()) <= half_max_range_sq || a.GetLocation().DistanceS(b.GetLocation()) <= max_distance; }
/** * Test whether two points (as previous search locations) are significantly * different to warrant a new search * * @param a1 First point to compare * @param a2 Second point to compare * @param dist_threshold Threshold distance for significance * * @return True if distance is significant */ gcc_pure static bool DistanceIsSignificant(const SearchPoint &a1, const SearchPoint &a2, const unsigned dist_threshold = 1) { return a1.FlatSquareDistance(a2) > (dist_threshold * dist_threshold); }
/** * Distance function for free point * * @param curNode Destination node * @param currentLocation Origin location * * @return Distance (flat) from origin to destination */ gcc_pure unsigned CalcDistance(const ScanTaskPoint curNode, const SearchPoint ¤tLocation) const { /* using expensive floating point formulas here to avoid integer rounding errors */ const GeoPoint &a = GetPoint(curNode).GetLocation(); const GeoPoint &b = currentLocation.GetLocation(); return (unsigned)a.Distance(b); }
bool TaskDijkstraMin::DistanceMin(const SearchPoint ¤tLocation) { dijkstra.Clear(); dijkstra.Reserve(256); if (currentLocation.IsValid()) { AddStartEdges(0, currentLocation); } else { AddZeroStartEdges(); } return Run(); }
static bool sortleft (const SearchPoint& sp1, const SearchPoint& sp2) { return sp1.sort(sp2); }
bool OLCTriangle::FindClosingPairs(unsigned old_size) { if (predict) { return closing_pairs.Insert(ClosingPair(0, n_points-1)); } struct TracePointNode { const TracePoint *point; unsigned index; }; struct TracePointNodeAccessor { gcc_pure int GetX(const TracePointNode &node) const { return node.point->GetFlatLocation().x; } gcc_pure int GetY(const TracePointNode &node) const { return node.point->GetFlatLocation().y; } }; QuadTree<TracePointNode, TracePointNodeAccessor> search_point_tree; for (unsigned i = old_size; i < n_points; ++i) { TracePointNode node; node.point = &GetPoint(i); node.index = i; search_point_tree.insert(node); } search_point_tree.Optimise(); bool new_pair = false; for (unsigned i = old_size; i < n_points; ++i) { TracePointNode point; point.point = &GetPoint(i); point.index = i; const SearchPoint start = *point.point; const unsigned max_range = trace_master.ProjectRange(start.GetLocation(), max_distance); const unsigned half_max_range_sq = max_range * max_range / 2; const int min_altitude = GetMinimumFinishAltitude(*point.point); const int max_altitude = GetMaximumStartAltitude(*point.point); unsigned last = 0, first = i; const auto visitor = [this, i, start, half_max_range_sq, min_altitude, max_altitude, &first, &last] (const TracePointNode &node) { const auto &dest = *node.point; if (node.index + 2 < i && dest.GetIntegerAltitude() <= max_altitude && IsInRange(start, dest, half_max_range_sq, max_distance)) { // point i is last point first = std::min(node.index, first); last = i; } else if (node.index > i + 2 && dest.GetIntegerAltitude() >= min_altitude && IsInRange(start, dest, half_max_range_sq, max_distance)) { // point i is first point first = i; last = std::max(node.index, last); } }; search_point_tree.VisitWithinRange(point, max_range, visitor); if (last != 0 && closing_pairs.Insert(ClosingPair(first, last))) new_pair = true; } return new_pair; }
/** * Accessor to retrieve location of the sample/boundary polygon * node that produces the minimum task distance. * * @return Location of minimum distance node */ const GeoPoint &GetLocationMin() const { return search_min.GetLocation(); };
/** * Accessor to retrieve location of the sample/boundary polygon * node that produces the maximum task distance. * * @return Location of max distance node */ gcc_pure const GeoPoint &GetLocationMax() const { return search_max.GetLocation(); };
TriangleSecondLeg::Result TriangleSecondLeg::Calculate(const SearchPoint &c, unsigned best) const { // this is a heuristic to remove invalid triangles // we do as much of this in flat projection for speed const unsigned df_2 = b.FlatDistanceTo(c); const unsigned df_3 = c.FlatDistanceTo(a); const unsigned df_total = df_1+df_2+df_3; // require some distance! if (df_total<20) { return Result(0, 0); } // no point scanning if worst than best if (df_total<= best) { return Result(0, 0); } const unsigned shortest = std::min({df_1, df_2, df_3}); // require all legs to have distance if (!shortest) return Result(0, 0); if (is_fai && (shortest*4<df_total)) // fails min < 25% worst-case rule! return Result(0, 0); const unsigned d = df_3 + df_2; // without FAI rules, allow any triangle if (!is_fai) return Result(d, df_total); if (shortest * 25 >= df_total * 7) // passes min > 28% rule, // this automatically means we pass max > 45% worst-case return Result(d, df_total); const unsigned longest = std::max({df_1, df_2, df_3}); if (longest * 20 > df_total * 9) // fails max > 45% worst-case rule! return Result(0, 0); // passed basic tests, now detailed ones // find accurate min leg distance fixed leg(0); if (df_1 == shortest) leg = a.GetLocation().Distance(b.GetLocation()); else if (df_2 == shortest) leg = b.GetLocation().Distance(c.GetLocation()); else if (df_3 == shortest) leg = c.GetLocation().Distance(a.GetLocation()); // estimate total distance by scaling. // this is a slight approximation, but saves having to do // three accurate distance calculations. const fixed d_total(df_total* leg / shortest); if (d_total >= fixed(500000)) { // long distance, ok that it failed 28% rule return Result(d, df_total); } return Result(0, 0); }
TriangleSecondLeg(bool _fai, const SearchPoint &_a, const SearchPoint &_b) :is_fai(_fai), a(_a), b(_b), df_1(a.FlatDistanceTo(b)) {}
/** * Set the location of the sample/boundary polygon node * that produces the minimum task distance. * * @param locmin Location of min distance node */ void SetSearchMin(const SearchPoint &locmin) { assert(locmin.IsValid()); search_min = locmin; }
/** * Set the location of the sample/boundary polygon node * that produces the maximum task distance. * * @param locmax Location of max distance node */ void SetSearchMax(const SearchPoint &locmax) { assert(locmax.IsValid()); search_max = locmax; }