Esempio n. 1
0
gcc_const
static unsigned
ContourInterval(const TerrainHeight h, const unsigned contour_height_scale)
{
  if (gcc_unlikely(h.IsSpecial()) || h.GetValue() <= 0)
    return 0;

  return ContourInterval(h.GetValue(), contour_height_scale);
}
Esempio n. 2
0
bool
RasterTileCache::FirstIntersection(const int x0, const int y0,
                                   const int x1, const int y1,
                                   int h_origin,
                                   int h_dest,
                                   const int slope_fact, const int h_ceiling,
                                   const int h_safety,
                                   RasterLocation &_location, int &_h,
                                   const bool can_climb) const
{
  RasterLocation location(x0, y0);
  if (!IsInside(location))
    // origin is outside overall bounds
    return false;

  const TerrainHeight h_origin2 = GetFieldDirect(x0, y0).first;
  if (h_origin2.IsInvalid()) {
    _location = location;
    _h = h_origin;
    return true;
  }

  if (!h_origin2.IsSpecial())
    h_origin = std::max(h_origin, (int)h_origin2.GetValue());

  h_dest = std::max(h_dest, h_origin);

  // line algorithm parameters
  const int dx = abs(x1-x0);
  const int dy = abs(y1-y0);
  int err = dx-dy;
  const int sx = (x0 < x1)? 1: -1;
  const int sy = (y0 < y1)? 1: -1;

  // max number of steps to walk
  const int max_steps = (dx+dy);
  // calculate number of fine steps to produce a step on the overview field
  const int step_fine = std::max(1, max_steps >> INTERSECT_BITS);
  // number of steps for update to the overview map
  const int step_coarse = std::max(1<< OVERVIEW_BITS, step_fine);

  // number of steps to be cleared after climbing over obstruction
  const int intersect_steps = 32;

  // counter for steps to reach next position to be checked on the field.
  unsigned step_counter = 0;
  // total counter of fine steps
  int total_steps = 0;

  // number of steps since intersection
  int intersect_counter = 0;

#ifdef DEBUG_TILE
  printf("# max steps %d\n", max_steps);
  printf("# step coarse %d\n", step_coarse);
  printf("# step fine %d\n", step_fine);
#endif

  // early exit if origin is too high (should not occur)
  if (h_origin> h_ceiling) {
#ifdef DEBUG_TILE
    printf("# fint start above ceiling %d %d\n", h_origin, h_ceiling);
#endif
    _location = location;
    _h = h_origin;
    return true;
  }

#ifdef DEBUG_TILE
  printf("# fint width %d height %d\n", width, height);
#endif

  // location of last point within ceiling limit that doesnt intersect
  RasterLocation last_clear_location = location;
  int last_clear_h = h_origin;

  while (true) {

    if (!step_counter) {

      if (!IsInside(location))
        break; // outside bounds

      const auto field_direct = GetFieldDirect(location.x, location.y);
      if (field_direct.first.IsInvalid())
        break;

      const int h_terrain = field_direct.first.GetValueOr0() + h_safety;
      step_counter = field_direct.second ? step_fine : step_coarse;

      // calculate height of glide so far
      const int dh = (total_steps * slope_fact) >> RASTER_SLOPE_FACT;

      // current aircraft height
      int h_int = dh + h_origin;
      if (can_climb) {
        h_int = std::min(h_int, h_dest);
      }

#ifdef DEBUG_TILE
      printf("%d %d %d %d %d # fint\n", location.x, location.y, h_int, h_terrain, h_ceiling);
#endif

      // this point has intersected if aircraft is below terrain height
      const bool this_intersecting = (h_int< h_terrain);

      if (this_intersecting) {
        intersect_counter = 1;

        // when intersecting, consider origin to have started higher
        const int h_jump = h_terrain - h_int;
        h_origin += h_jump;

        if (can_climb) {
          // if intersecting beyond desired destination height, allow dest height
          // to be increased
          if (h_terrain> h_dest)
            h_dest = h_terrain;
        } else {
          // if can't climb, must jump so path is pure glide
          h_dest += h_jump;
        }
        h_int = h_terrain;

      }

      if (h_int > h_ceiling) {
        _location = last_clear_location;
        _h = last_clear_h;
#ifdef DEBUG_TILE
        printf("# fint reach ceiling\n");
#endif
        return true; // reached ceiling
      }

      if (!this_intersecting) {
        if (intersect_counter) {
          intersect_counter+= step_counter;

          // was intersecting, now cleared.
          // exit with small height above terrain
#ifdef DEBUG_TILE
          printf("# fint int->clear\n");
#endif
          if (intersect_counter >= intersect_steps) {
            _location = location;
            _h = h_int;
            return true;
          }
        } else {
          last_clear_location = location;
          last_clear_h = h_int;
        }
      }
    }

    if (!intersect_counter && (total_steps == max_steps)) {
#ifdef DEBUG_TILE
      printf("# fint cleared\n");
#endif
      return false;
    }

    const int e2 = 2*err;
    if (e2 > -dy) {
      err -= dy;
      location.x += sx;
      if (step_counter)
        step_counter--;
      total_steps++;
    }
    if (e2 < dx) {
      err += dx;
      location.y += sy;
      if (step_counter)
        step_counter--;
      total_steps++;
    }
  }

  // early exit due to inability to find clearance after intersecting
  if (intersect_counter) {
    _location = last_clear_location;
    _h = last_clear_h;
#ifdef DEBUG_TILE
    printf("# fint early exit\n");
#endif
    return true;
  }
  return false;
}
Esempio n. 3
0
static void
test_troute(const RasterMap &map, double mwind, double mc, int ceiling)
{
  GlideSettings settings;
  settings.SetDefaults();
  RoutePlannerConfig config;
  config.mode = RoutePlannerConfig::Mode::BOTH;

  GlidePolar polar(mc);
  SpeedVector wind(Angle::Degrees(0), mwind);
  TerrainRoute route;
  route.UpdatePolar(settings, config, polar, polar, wind);
  route.SetTerrain(&map);

  GeoPoint origin(map.GetMapCenter());

  auto pd = map.PixelDistance(origin, 1);
  printf("# pixel size %g\n", (double)pd);

  bool retval= true;

  {
    Directory::Create(Path(_T("output/results")));
    std::ofstream fout ("output/results/terrain.txt");
    unsigned nx = 100;
    unsigned ny = 100;
    for (unsigned i=0; i< nx; ++i) {
      for (unsigned j=0; j< ny; ++j) {
        auto fx = (double)i / (nx - 1) * 2 - 1;
        auto fy = (double)j / (ny - 1) * 2 - 1;
        GeoPoint x(origin.longitude + Angle::Degrees(0.6 * fx),
                   origin.latitude + Angle::Degrees(0.4 * fy));
        TerrainHeight h = map.GetInterpolatedHeight(x);
        fout << x.longitude.Degrees() << " " << x.latitude.Degrees()
             << " " << h.GetValue() << "\n";
      }
      fout << "\n";
    }
    fout << "\n";
  }

  unsigned i=0;
  for (double ang = 0; ang < M_2PI; ang += M_PI / 8) {
    GeoPoint dest = GeoVector(40000.0, Angle::Radians(ang)).EndPoint(origin);

    int hdest = map.GetHeight(dest).GetValueOr0() + 100;

    retval = route.Solve(AGeoPoint(origin,
                                   map.GetHeight(origin).GetValueOr0() + 100),
                         AGeoPoint(dest,
                                   mc > 0
                                   ? hdest
                                   : std::max(hdest, 3200)),
                         config, ceiling);
    char buffer[80];
    sprintf(buffer,"terrain route solve, dir=%g, wind=%g, mc=%g ceiling=%d",
            (double)ang, (double)mwind, (double)mc, (int)ceiling);
    ok(retval, buffer, 0);
    PrintHelper::print_route(route);
    i++;
  }

  // polar.SetMC(0);
  // route.UpdatePolar(polar, wind);
}
void
GlueMapWindow::DrawPanInfo(Canvas &canvas) const
{
  if (!render_projection.IsValid())
    return;

  GeoPoint location = render_projection.GetGeoLocation();

  TextInBoxMode mode;
  mode.shape = LabelShape::OUTLINED;
  mode.align = TextInBoxMode::Alignment::RIGHT;

  const Font &font = *look.overlay.overlay_font;
  canvas.Select(font);

  unsigned padding = Layout::FastScale(4);
  unsigned height = font.GetHeight();
  int y = 0 + padding;
  int x = render_projection.GetScreenWidth() - padding;

  if (compass_visible)
    /* don't obscure the north arrow */
    /* TODO: obtain offset from CompassRenderer */
    y += Layout::Scale(19) + Layout::FastScale(13);

  if (terrain) {
    TerrainHeight elevation = terrain->GetTerrainHeight(location);
    if (!elevation.IsSpecial()) {
      StaticString<64> elevation_long;
      elevation_long = _("Elevation: ");
      elevation_long += FormatUserAltitude(elevation.GetValue());

      TextInBox(canvas, elevation_long, x, y, mode,
                render_projection.GetScreenWidth(),
                render_projection.GetScreenHeight());

      y += height;
    }
  }

  TCHAR buffer[256];
  FormatGeoPoint(location, buffer, ARRAY_SIZE(buffer), _T('\n'));

  TCHAR *start = buffer;
  while (true) {
    auto *newline = StringFind(start, _T('\n'));
    if (newline != nullptr)
      *newline = _T('\0');

    TextInBox(canvas, start, x, y, mode,
              render_projection.GetScreenWidth(),
              render_projection.GetScreenHeight());

    y += height;

    if (newline == nullptr)
      break;

    start = newline + 1;
  }
}