void AATPoint::set_target(const fixed range, const fixed radial, const TaskProjection &proj) { fixed oldrange = fixed_zero; fixed oldradial = fixed_zero; get_target_range_radial(oldrange, oldradial); const FlatPoint fprev = proj.fproject(get_previous()->get_location_remaining()); const FlatPoint floc = proj.fproject(get_location()); const FlatLine flb (fprev,floc); const FlatLine fradius (floc,proj.fproject(get_location_min())); const fixed bearing = fixed_minus_one * flb.angle().value_degrees(); const fixed radius = fradius.d(); fixed swapquadrants = fixed_zero; if (positive(range) != positive(oldrange)) swapquadrants = fixed(180); const FlatPoint ftarget1 (fabs(range) * radius * cos((bearing + radial + swapquadrants) / fixed(360) * fixed_two_pi), fabs(range) * radius * sin( fixed_minus_one * (bearing + radial + swapquadrants) / fixed(360) * fixed_two_pi)); const FlatPoint ftarget2 = floc + ftarget1; const GeoPoint targetG = proj.funproject(ftarget2); set_target(targetG, true); }
void AATPoint::SetTarget(const fixed range, const fixed radial, const TaskProjection &proj) { fixed oldrange = fixed_zero; fixed oldradial = fixed_zero; GetTargetRangeRadial(oldrange, oldradial); const FlatPoint fprev = proj.ProjectFloat(GetPrevious()->GetLocationRemaining()); const FlatPoint floc = proj.ProjectFloat(GetLocation()); const FlatLine flb (fprev,floc); const FlatLine fradius (floc,proj.ProjectFloat(GetLocationMin())); const fixed bearing = fixed_minus_one * flb.angle().Degrees(); const fixed radius = fradius.d(); fixed swapquadrants = fixed_zero; if (positive(range) != positive(oldrange)) swapquadrants = fixed(180); const FlatPoint ftarget1 (fabs(range) * radius * cos((bearing + radial + swapquadrants) / fixed(360) * fixed_two_pi), fabs(range) * radius * sin( fixed_minus_one * (bearing + radial + swapquadrants) / fixed(360) * fixed_two_pi)); const FlatPoint ftarget2 = floc + ftarget1; const GeoPoint targetG = proj.Unproject(ftarget2); SetTarget(targetG, true); }
bool FlatLine::intersect_circle(const fixed r, const FlatPoint c, FlatPoint &i1, FlatPoint &i2) const { FlatLine that = *this; that.sub(c); if (that.intersect_czero(r, i1, i2)) { i1 = i1 + c; i2 = i2 + c; return true; } return false; }
/** * Check if the two wave lines match, and attempt to merge them. * * TODO: this is clumsy and unoptimised code; please improve! * * @return true if the lines have been merged into #a */ static bool MergeLines(FlatLine &a, const FlatLine b) { const double a_sq = a.GetSquaredDistance(); const double b_sq = b.GetSquaredDistance(); const double max_sq_distance = (std::max(a_sq, b_sq) + 2 * std::min(a_sq, b_sq)) / 250; const RatioAndDistance results[] = { CalcRatioAndDistance(a, b.a), CalcRatioAndDistance(a, b.b), CalcRatioAndDistance(b, a.a), CalcRatioAndDistance(b, a.b), }; /* if two out of 4 line endpoints must be near the other line */ unsigned n_distance_ok = 0; for (auto i : results) if (i.squared_distance <= max_sq_distance) ++n_distance_ok; if (n_distance_ok < 2) return false; /* the ratio of at least one point must be in range */ unsigned n_ratio_ok = 0; for (auto i : results) if (IsRatioInRange(i.ratio)) ++n_ratio_ok; if (n_ratio_ok == 0) return false; /* we can merge! now check if we should extend the original (old) line because the new one exceeds it */ if (results[0].ratio < 0) a.a = b.a; if (results[1].ratio > 1) a.b = b.b; return true; }
/** * Wrapper for FlatLine::Interpolate() which will clip the ratio to * [0..1] so the result stays within the [a..b] bounds. */ static constexpr FlatPoint InterpolateClip(const FlatLine line, double ratio) { return ratio <= 0 ? line.a : (ratio >= 1 ? line.b : line.Interpolate(ratio)); }
gcc_pure static RatioAndDistance CalcRatioAndDistance(const FlatLine line, const FlatPoint point) { RatioAndDistance result; result.ratio = line.ProjectedRatio(point); FlatPoint projected = InterpolateClip(line, result.ratio); result.squared_distance = (point - projected).MagnitudeSquared(); return result; }
void AATPoint::SetTarget(RangeAndRadial rar, const FlatProjection &proj) { const auto fprev = proj.ProjectFloat(GetPrevious()->GetLocationRemaining()); const auto floc = proj.ProjectFloat(GetLocation()); const FlatLine flb (fprev,floc); const FlatLine fradius(floc, proj.ProjectFloat(negative(rar.range) ? GetLocationMin() : GetLocationMax())); const auto radius = fradius.d() * fabs(rar.range); const auto angle = rar.radial - flb.angle(); const FlatPoint ftarget1(radius * angle.cos(), radius * -(angle).sin()); const auto ftarget2 = floc + ftarget1; const auto targetG = proj.Unproject(ftarget2); SetTarget(targetG, true); }