AirspaceIntersectionVector AirspaceCircle::Intersects(const GeoPoint &start, const GeoPoint &end, const TaskProjection &projection) const { const fixed f_radius = projection.fproject_range(m_center, m_radius); const FlatPoint f_center = projection.fproject(m_center); const FlatPoint f_start = projection.fproject(start); const FlatPoint f_end = projection.fproject(end); const FlatLine line(f_start, f_end); FlatPoint f_p1, f_p2; if (!line.intersect_circle(f_radius, f_center, f_p1, f_p2)) return AirspaceIntersectionVector(); const fixed mag = line.dsq(); if (!positive(mag)) return AirspaceIntersectionVector(); const fixed inv_mag = fixed_one / mag; const fixed t1 = FlatLine(f_start, f_p1).dot(line); const fixed t2 = (f_p1 == f_p2) ? -fixed_one : FlatLine(f_start, f_p2).dot(line); const bool in_range = (t1 < mag) || (t2 < mag); // if at least one point is within range, capture both points AirspaceIntersectSort sorter(start, end, *this); if ((t1 >= fixed_zero) && in_range) sorter.add(t1 * inv_mag, projection.funproject(f_p1)); if ((t2 >= fixed_zero) && in_range) sorter.add(t2 * inv_mag, projection.funproject(f_p2)); return sorter.all(); }
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 ThermalLocator::Update(const fixed t_0, const GeoPoint &location_0, const SpeedVector wind, ThermalLocatorInfo &therm) { if (n_points < TLOCATOR_NMIN) { therm.estimate_valid = false; return; // nothing to do. } GeoPoint dloc = FindLatitudeLongitude(location_0, wind.bearing, wind.norm); TaskProjection projection; projection.reset(location_0); projection.update_fast(); // drift points Drift(t_0, projection, location_0 - dloc); FlatPoint av = glider_average(); // find thermal center relative to glider's average position FlatPoint f0(fixed_zero, fixed_zero); fixed acc = fixed_zero; for (unsigned i = 0; i < n_points; ++i) { f0 += (points[i].loc_drift-av)*points[i].lift_weight; acc += points[i].lift_weight; } // if sufficient data, estimate location if (!positive(acc)) { therm.estimate_valid = false; return; } f0 = f0 * (fixed_one/acc) + av; therm.estimate_location = projection.funproject(f0); therm.estimate_valid = true; }