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)) {}