Exemplo n.º 1
0
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();
}
Exemplo n.º 2
0
/**
 * 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;
}