/** * Calculate error distance, between last through this to next, * if this node is removed. This metric provides for Douglas-Peuker * thinning. * * @param last Point previous in time to this node * @param node This node * @param next Point succeeding this node * * @return Distance error if this node is thinned */ static unsigned distance_metric(const TracePoint& last, const TracePoint& node, const TracePoint& next) { const int d_this = last.flat_distance(node) + node.flat_distance(next); const int d_rem = last.flat_distance(next); return abs(d_this - d_rem); }
bool AbstractContest::IsFinishAltitudeValid(const TracePoint& start, const TracePoint& finish) const { return finish.GetIntegerAltitude() + (int)finish_alt_diff >= start.GetIntegerAltitude(); }
/** * Calculate error distance, between last through this to next, * if this node is removed. This metric provides for Douglas-Peuker * thinning. * * @param last Point previous in time to this node * @param node This node * @param next Point succeeding this node * * @return Distance error if this node is thinned */ static unsigned DistanceMetric(const TracePoint &last, const TracePoint &node, const TracePoint &next) { const int d_this = last.FlatDistanceTo(node) + node.FlatDistanceTo(next); const int d_rem = last.FlatDistanceTo(next); return abs(d_this - d_rem); }
gcc_const static TracePoint Invalid() { TracePoint point; point.Clear(); ((SearchPoint &)point).SetInvalid(); return point; }
/** * Retrieve coordinate value from object given coordinate index * @param d WaypointEnvelope object * @param k index of coordinate * * @return Coordinate value */ int operator() ( const TracePoint &d, const unsigned k) const { switch(k) { case 0: return d.get_flatLocation().Longitude; case 1: return d.get_flatLocation().Latitude; }; return 0; };
static void PrintTracePoint(const TracePoint &point, std::ofstream& fs) { fs << point.GetTime() << " " << point.GetLocation().longitude << " " << point.GetLocation().latitude << " " << point.GetAltitude() << " " << point.GetVario() << "\n"; }
TraceDelta(const TracePoint &p_last, const TracePoint &p, const TracePoint &p_next) :point(p), elim_time(time_metric(p_last, p, p_next)), elim_distance(distance_metric(p_last, p, p_next)), delta_distance(p.flat_distance(p_last)) { assert(elim_distance != null_delta); }
TraceDelta(const TracePoint &p_last, const TracePoint &p, const TracePoint &p_next) :point(p), elim_time(TimeMetric(p_last, p, p_next)), elim_distance(DistanceMetric(p_last, p, p_next)), delta_distance(p.FlatDistanceTo(p_last)) { assert(elim_distance != null_delta); }
gcc_pure int GetMinimumFinishAltitude(const TracePoint &start) const { return start.GetIntegerAltitude() - finish_alt_diff; }
gcc_pure int GetMaximumStartAltitude(const TracePoint &finish) const { return finish.GetIntegerAltitude() + finish_alt_diff; }
void update(const TracePoint &p_last, const TracePoint &p_next) { elim_time = time_metric(p_last, point, p_next); elim_distance = distance_metric(p_last, point, p_next); delta_distance = point.flat_distance(p_last); }
/** * Calculate approximate squared (flat projected) distance between this point * and another * * @param tp Point to calculate distance to * * @return Approximate squared distance */ gcc_pure unsigned approx_sq_dist(const TracePoint& tp) const { return dsqr(get_flatLocation().Longitude-tp.get_flatLocation().Longitude)+ dsqr(get_flatLocation().Latitude-tp.get_flatLocation().Latitude); }
/** * Calculate error time, between last through this to next, * if this node is removed. This metric provides for fair thinning * (tendency to to result in equal time steps) * * @param last Point previous in time to this node * @param node This node * @param next Point succeeding this node * * @return Time delta if this node is thinned */ static unsigned TimeMetric(const TracePoint &last, const TracePoint &node, const TracePoint &next) { return next.DeltaTime(last) - std::min(next.DeltaTime(node), node.DeltaTime(last)); }
void Update(const TracePoint &p_last, const TracePoint &p_next) { elim_time = TimeMetric(p_last, point, p_next); elim_distance = DistanceMetric(p_last, point, p_next); delta_distance = point.FlatDistanceTo(p_last); }
TriangleSecondLeg(bool _fai, const TracePoint &_a, const TracePoint &_b) :is_fai(_fai), a(_a), b(_b), df_1(a.flat_distance(b)) {}
TriangleSecondLeg::Result TriangleSecondLeg::Calculate(const TracePoint &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.flat_distance(c); const unsigned df_3 = c.flat_distance(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 = min(df_1, min(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 = max(df_1, max(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.get_location().distance(b.get_location()); } else if (df_2 == shortest) { leg = b.get_location().distance(c.get_location()); } else if (df_3 == shortest) { leg = c.get_location().distance(a.get_location()); } // 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); }
inline ContestTracePoint::ContestTracePoint(const TracePoint &src) :time(src.GetTime()), location(src.GetLocation()) {}