gcc_pure static Angle CalcIntermediateAngle(const SeeYouTurnpointInformation &turnpoint_infos, const GeoPoint &location, const GeoPoint &start, const GeoPoint &previous, const GeoPoint &next) { switch (turnpoint_infos.style) { case SeeYouTurnpointInformation::FIXED: return turnpoint_infos.angle12.Reciprocal(); case SeeYouTurnpointInformation::SYMMETRICAL: break; case SeeYouTurnpointInformation::TO_NEXT_POINT: return next.Bearing(location); case SeeYouTurnpointInformation::TO_PREVIOUS_POINT: return previous.Bearing(location); case SeeYouTurnpointInformation::TO_START_POINT: return start.Bearing(location); } /* SYMMETRICAL is the fallback when the file contained an invalid/unknown style */ const Angle ap = previous.Bearing(location); const Angle an = next.Bearing(location); return ap.HalfAngle(an).Reciprocal(); }
/** * Creates the correct XCSoar OZ type from the See You OZ options for the point * Note: there are several rules enforced here related to the combinations * and types of Zones supported by XCSoar. When XCSoar adds more zone types, * the logic below will need to be updated. * @param turnpoint_infos Contains the See You turnpoint and OZ info * @param current point position * @param number wps in task * @param array of wps for each point in task * @param factType The XCSoar factory type * @return the XCSoar OZ */ static ObservationZonePoint* CreateOZ(const SeeYouTurnpointInformation &turnpoint_infos, unsigned pos, unsigned size, const Waypoint *wps[], TaskFactoryType factType) { ObservationZonePoint* oz = NULL; const bool is_intermediate = (pos > 0) && (pos < (size - 1)); const Waypoint *wp = wps[pos]; if (!turnpoint_infos.valid) return NULL; if (factType == TaskFactoryType::RACING && is_intermediate && isKeyhole(turnpoint_infos)) oz = KeyholeZone::CreateDAeCKeyholeZone(wp->location); else if (factType == TaskFactoryType::RACING && is_intermediate && isBGAEnhancedOptionZone(turnpoint_infos)) oz = KeyholeZone::CreateBGAEnhancedOptionZone(wp->location); else if (factType == TaskFactoryType::RACING && is_intermediate && isBGAFixedCourseZone(turnpoint_infos)) oz = KeyholeZone::CreateBGAFixedCourseZone(wp->location); else if (!is_intermediate && turnpoint_infos.is_line) // special case "is_line" oz = new LineSectorZone(wp->location, turnpoint_infos.radius1); // special case "Cylinder" else if (fabs(turnpoint_infos.angle1.Degrees() - fixed(180)) < fixed(1) ) oz = new CylinderZone(wp->location, turnpoint_infos.radius1); else if (factType == TaskFactoryType::RACING) { // XCSoar does not support fixed sectors for RT if (turnpoint_infos.style == SeeYouTurnpointInformation::FIXED) oz = new CylinderZone(wp->location, turnpoint_infos.radius1); else oz = SymmetricSectorZone::CreateFAISectorZone(wp->location, is_intermediate); } else if (is_intermediate) { //AAT intermediate point Angle A12adj; assert(wps[pos + 1]); assert(wps[pos - 1]); switch (turnpoint_infos.style) { case SeeYouTurnpointInformation::FIXED: { A12adj = turnpoint_infos.angle12.Reciprocal(); break; } case SeeYouTurnpointInformation::SYMMETRICAL: { const Angle ap = wps[pos - 1]->location.Bearing(wp->location); const Angle an = wps[pos + 1]->location.Bearing(wp->location); A12adj = ap.HalfAngle(an).Reciprocal(); break; } case SeeYouTurnpointInformation::TO_NEXT_POINT: { A12adj = wps[pos + 1]->location.Bearing(wp->location); break; } case SeeYouTurnpointInformation::TO_PREVIOUS_POINT: { A12adj = wps[pos - 1]->location.Bearing(wp->location); break; } case SeeYouTurnpointInformation::TO_START_POINT: { A12adj = wps[0]->location.Bearing(wp->location); break; } } const Angle RadialStart = (A12adj - turnpoint_infos.angle1).AsBearing(); const Angle RadialEnd = (A12adj + turnpoint_infos.angle1).AsBearing(); if (turnpoint_infos.radius2 > fixed(0) && (turnpoint_infos.angle2.AsBearing().Degrees()) < fixed(1)) { oz = new AnnularSectorZone(wp->location, turnpoint_infos.radius1, RadialStart, RadialEnd, turnpoint_infos.radius2); } else { oz = new SectorZone(wp->location, turnpoint_infos.radius1, RadialStart, RadialEnd); } } else { // catch-all oz = new CylinderZone(wp->location, turnpoint_infos.radius1); } return oz; }