Beispiel #1
2
void
MapOverlayBitmap::Draw(Canvas &canvas,
                       const WindowProjection &projection) noexcept
{
  if (!simple_bounds.Overlaps(projection.GetScreenBounds()))
    /* not visible, outside of screen area */
    return;

  const RasterPoint vertices[] = {
    projection.GeoToScreen(bounds.top_left),
    projection.GeoToScreen(bounds.top_right),
    projection.GeoToScreen(bounds.bottom_left),
    projection.GeoToScreen(bounds.bottom_right),
  };

  const ScopeVertexPointer vp(vertices);

  GLTexture &texture = *bitmap.GetNative();
  texture.Bind();

  const PixelSize allocated = texture.GetAllocatedSize();
  const unsigned src_x = 0, src_y = 0;
  const unsigned src_width = texture.GetWidth();
  const unsigned src_height = texture.GetHeight();

  GLfloat x0 = (GLfloat)src_x / allocated.cx;
  GLfloat y0 = (GLfloat)src_y / allocated.cy;
  GLfloat x1 = (GLfloat)(src_x + src_width) / allocated.cx;
  GLfloat y1 = (GLfloat)(src_y + src_height) / allocated.cy;

  if (bitmap.IsFlipped()) {
    y0 = 1 - y0;
    y1 = 1 - y1;
  }

  const Point2D<GLfloat> coord[] = {
    {x0, y0},
    {x1, y0},
    {x0, y1},
    {x1, y1},
  };

  const ScopeTextureConstantAlpha blend(alpha);

#ifdef USE_GLSL
  OpenGL::texture_shader->Use();
  glEnableVertexAttribArray(OpenGL::Attribute::TEXCOORD);
  glVertexAttribPointer(OpenGL::Attribute::TEXCOORD, 2, GL_FLOAT, GL_FALSE,
                        0, coord);
#else
  const GLEnable<GL_TEXTURE_2D> scope;
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  glTexCoordPointer(2, GL_FLOAT, 0, coord);
#endif

  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

#ifdef USE_GLSL
  glDisableVertexAttribArray(OpenGL::Attribute::TEXCOORD);
  OpenGL::solid_shader->Use();
#else
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
#endif
}
void
TopographyFileRenderer::UpdateVisibleShapes(const WindowProjection &projection)
{
  if (file.GetSerial() == visible_serial &&
      visible_bounds.IsInside(projection.GetScreenBounds()) &&
      projection.GetScreenBounds().Scale(fixed_two).IsInside(visible_bounds))
    /* cache is clean */
    return;

  visible_serial = file.GetSerial();
  visible_bounds = projection.GetScreenBounds().Scale(fixed(1.2));
  visible_shapes.clear();
  visible_labels.clear();

  for (auto it = file.begin(), end = file.end(); it != end; ++it) {
    const XShape &shape = *it;

    if (!visible_bounds.Overlaps(shape.get_bounds()))
      continue;

    if (shape.get_type() != MS_SHAPE_NULL)
      visible_shapes.push_back(&shape);

    if (shape.get_label() != NULL)
      visible_labels.push_back(&shape);
  }
}
Beispiel #3
0
bool
TopographyFile::Update(const WindowProjection &map_projection)
{
  if (IsEmpty())
    return false;

  if (map_projection.GetMapScale() > scale_threshold)
    /* not visible, don't update cache now */
    return false;

  const GeoBounds screenRect =
    map_projection.GetScreenBounds();
  if (cache_bounds.IsValid() && cache_bounds.IsInside(screenRect))
    /* the cache is still fresh */
    return false;

  cache_bounds = map_projection.GetScreenBounds().Scale(fixed(2));

  rectObj deg_bounds = ConvertRect(cache_bounds);

  // Test which shapes are inside the given bounds and save the
  // status to file.status
  msShapefileWhichShapes(&file, dir, deg_bounds, 0);

  // If not a single shape is inside the bounds
  if (!file.status) {
    // ... clear the whole buffer
    ClearCache();
    return false;
  }

  // Iterate through the shapefile entries
  const ShapeList **current = &first;
  auto it = shapes.begin();
  for (int i = 0; i < file.numshapes; ++i, ++it) {
    if (!msGetBit(file.status, i)) {
      // If the shape is outside the bounds
      // delete the shape from the cache
      delete it->shape;
      it->shape = NULL;
    } else {
      // is inside the bounds
      if (it->shape == NULL)
        // shape isn't cached yet -> cache the shape
        it->shape = new XShape(&file, i, label_field);
      // update list pointer
      *current = it;
      current = &it->next;
    }
  }
  // end of list marker
  *current = NULL;

  ++serial;
  return true;
}
Beispiel #4
0
void
MapOverlayBitmap::Draw(Canvas &canvas,
                       const WindowProjection &projection) noexcept
{
  if (!simple_bounds.Overlaps(projection.GetScreenBounds()))
    /* not visible, outside of screen area */
    return;

  auto clipped = Clip(bounds, projection.GetScreenBounds());
  if (clipped.empty())
    return;

  GLTexture &texture = *bitmap.GetNative();
  const PixelSize allocated = texture.GetAllocatedSize();
  const double x_factor = double(texture.GetWidth()) / allocated.cx;
  const double y_factor = double(texture.GetHeight()) / allocated.cy;

  Point2D<GLfloat> coord[16];
  BulkPixelPoint vertices[16];

  const ScopeVertexPointer vp(vertices);

  texture.Bind();

  const ScopeTextureConstantAlpha blend(use_bitmap_alpha, alpha);

  glEnableVertexAttribArray(OpenGL::Attribute::TEXCOORD);
  glVertexAttribPointer(OpenGL::Attribute::TEXCOORD, 2, GL_FLOAT, GL_FALSE,
                        0, coord);

  for (const auto &polygon : clipped) {
    const auto &ring = polygon.outer();

    size_t n = ring.size();
    if (ring.front() == ring.back())
      --n;

    for (size_t i = 0; i < n; ++i) {
      const auto v = GeoFrom2D(ring[i]);

      auto p = MapInQuadrilateral(bounds, v);
      coord[i].x = p.x * x_factor;
      coord[i].y = p.y * y_factor;

      if (bitmap.IsFlipped())
        coord[i].y = 1 - coord[i].y;

      vertices[i] = projection.GeoToScreen(v);
    }

    glDrawArrays(GL_TRIANGLE_FAN, 0, n);
  }

  glDisableVertexAttribArray(OpenGL::Attribute::TEXCOORD);
}
Beispiel #5
0
void
TopographyThread::Trigger(const WindowProjection &_projection)
{
  assert(_projection.IsValid());

  const GeoBounds new_bounds = _projection.GetScreenBounds();
  if (last_bounds.IsValid() && last_bounds.IsInside(new_bounds)) {
    /* still inside cache bounds - now check if we crossed a scale
       threshold for at least one file, which would mean we have to
       update a file which was not updated for the current cache
       bounds */
    if (scale_threshold < 0 ||
        _projection.GetMapScale() >= scale_threshold)
      /* the cache is still fresh */
      return;
  }

  last_bounds = new_bounds.Scale(1.1);
  scale_threshold = store.GetNextScaleThreshold(_projection.GetMapScale());

  {
    const ScopeLock protect(mutex);
    next_projection = _projection;
    StandbyThread::Trigger();
  }
}
Beispiel #6
0
bool
RaspRenderer::Generate(const WindowProjection &projection,
                       const TerrainRendererSettings &settings)
{
  const auto &style = LookupWeatherTerrainStyle(cache.GetMapName());
  const bool do_water = style.do_water;
  const unsigned height_scale = style.height_scale;
  const int interp_levels = 5;
  const ColorRamp *color_ramp = style.color_ramp;

  const RasterMap *map = cache.GetMap();
  if (map == nullptr)
    return false;

  if (!map->GetBounds().Overlaps(projection.GetScreenBounds()))
    /* not visible */
    return false;

  if (color_ramp != last_color_ramp) {
    raster_renderer.PrepareColorTable(color_ramp, do_water,
                                      height_scale, interp_levels);
    last_color_ramp = color_ramp;
  }

  raster_renderer.ScanMap(*map, projection);

  raster_renderer.GenerateImage(false, height_scale,
                                settings.contrast, settings.brightness,
                                Angle::Zero(), false);
  return true;
}
Beispiel #7
0
void
TerrainRenderer::Generate(const WindowProjection &map_projection,
                          const Angle sunazimuth)
{
#ifdef ENABLE_OPENGL
  const GeoBounds &old_bounds = raster_renderer.GetBounds();
  const GeoBounds &new_bounds = map_projection.GetScreenBounds();
  assert(new_bounds.IsValid());

  if (old_bounds.IsValid() && old_bounds.IsInside(new_bounds) &&
      !IsLargeSizeDifference(old_bounds, new_bounds) &&
      terrain_serial == terrain->GetSerial() &&
      sunazimuth.CompareRoughly(last_sun_azimuth) &&
      !raster_renderer.UpdateQuantisation())
    /* no change since previous frame */
    return;

#else
  if (compare_projection.Compare(map_projection) &&
      terrain_serial == terrain->GetSerial() &&
      sunazimuth.CompareRoughly(last_sun_azimuth))
    /* no change since previous frame */
    return;

  compare_projection = CompareProjection(map_projection);
#endif

  terrain_serial = terrain->GetSerial();

  last_sun_azimuth = sunazimuth;

  const bool do_water = true;
  const unsigned height_scale = 4;
  const int interp_levels = 2;
  const bool is_terrain = true;
  const bool do_shading = is_terrain &&
                          settings.slope_shading != SlopeShading::OFF;
  const bool do_contour = is_terrain &&
                          settings.contours != Contours::OFF;

  const ColorRamp *const color_ramp = &terrain_colors[settings.ramp][0];
  if (color_ramp != last_color_ramp) {
    raster_renderer.ColorTable(color_ramp, do_water,
                               height_scale, interp_levels);
    last_color_ramp = color_ramp;
  }

  {
    RasterTerrain::Lease map(*terrain);
    raster_renderer.ScanMap(map, map_projection);
  }

  raster_renderer.GenerateImage(do_shading, height_scale,
                                settings.contrast, settings.brightness,
                                sunazimuth,
				do_contour);
}
Beispiel #8
0
 AirspaceFillRenderer(Canvas &_canvas, const WindowProjection &_projection,
                      const AirspaceLook &_look,
                      const AirspaceWarningCopy &_warnings,
                      const AirspaceRendererSettings &_settings)
   :MapCanvas(_canvas, _projection,
              _projection.GetScreenBounds().Scale(fixed(1.1))),
    look(_look), warning_manager(_warnings), settings(_settings)
 {
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 }
Beispiel #9
0
 AirspaceOutlineRenderer(Canvas &_canvas, const WindowProjection &_projection,
                         const AirspaceLook &_airspace_look,
                         bool _black)
   :MapCanvas(_canvas, _projection,
              _projection.GetScreenBounds().Scale(fixed(1.1))),
    airspace_look(_airspace_look),
    black(_black) {
   if (black)
     canvas.SelectBlackPen();
   canvas.SelectHollowBrush();
 }
Beispiel #10
0
 AirspaceOutlineRenderer(Canvas &_canvas, const WindowProjection &_projection,
                         const AirspaceLook &_look,
                         const AirspaceRendererSettings &_settings)
   :MapCanvas(_canvas, _projection,
              _projection.GetScreenBounds().Scale(fixed(1.1))),
    look(_look), settings(_settings)
 {
   if (settings.black_outline)
     canvas.SelectBlackPen();
   canvas.SelectHollowBrush();
 }
Beispiel #11
0
StencilMapCanvas::StencilMapCanvas(Canvas &_buffer, Canvas &_stencil,
                                   const WindowProjection &_proj,
                                   const AirspaceRendererSettings &_settings)
  :clip(_proj.GetScreenBounds().Scale(fixed(1.1))),
   buffer(_buffer),
   stencil(_stencil),
   proj(_proj),
   buffer_drawn(false),
   use_stencil(false),
   settings(_settings)
{
}
Beispiel #12
0
 AirspaceVisitorRenderer(Canvas &_canvas, const WindowProjection &_projection,
                         const AirspaceLook &_look,
                         const AirspaceWarningCopy &_warnings,
                         const AirspaceRendererSettings &_settings)
   :MapCanvas(_canvas, _projection,
              _projection.GetScreenBounds().Scale(fixed(1.1))),
    look(_look), warning_manager(_warnings), settings(_settings)
 {
   glStencilMask(0xff);
   glClear(GL_STENCIL_BUFFER_BIT);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 }
Beispiel #13
0
MapDrawHelper::MapDrawHelper(Canvas &_canvas, Canvas &_buffer, Canvas &_stencil,
                             const WindowProjection &_proj,
                             const AirspaceRendererSettings &_settings)
  :clip(_proj.GetScreenBounds().Scale(fixed(1.1))),
   m_canvas(_canvas),
   m_buffer(_buffer),
   m_stencil(_stencil),
   m_proj(_proj),
   m_buffer_drawn(false),
   m_use_stencil(false),
   settings(_settings)
{
}
Beispiel #14
0
void
RasterRenderer::ScanMap(const RasterMap &map, const WindowProjection &projection)
{
  // Coordinates of the MapWindow center
  unsigned x = projection.GetScreenWidth() / 2;
  unsigned y = projection.GetScreenHeight() / 2;
  // GeoPoint corresponding to the MapWindow center
  GeoPoint center = projection.ScreenToGeo(x, y);
  // GeoPoint "next to" Gmid (depends on terrain resolution)
  GeoPoint neighbor = projection.ScreenToGeo(x + quantisation_pixels,
                                             y + quantisation_pixels);

  // Geographical edge length of pixel in the MapWindow center in meters
  pixel_size = M_SQRT1_2 * center.DistanceS(neighbor);

  // set resolution

  if (pixel_size < 3000) {
    // Data point size of the (terrain) map in meters multiplied by 256
    auto map_pixel_size = map.PixelDistance(center, 1);

    // How many screen pixels does one data point stretch?
    auto q = map_pixel_size / pixel_size;

    /* round down to reduce slope shading artefacts (caused by
       RasterBuffer interpolation) */
    quantisation_effective = std::max(1, (int)q);

    /* disable slope shading when zoomed in very near (not enough
       terrain resolution to make a useful slope calculation) */
    if (quantisation_effective > 25)
      quantisation_effective = 0;

  } else
    /* disable slope shading when zoomed out very far (too tiny) */
    quantisation_effective = 0;

#ifdef ENABLE_OPENGL
  bounds = projection.GetScreenBounds().Scale(1.5);
  bounds.IntersectWith(map.GetBounds());

  height_matrix.Fill(map, bounds,
                     projection.GetScreenWidth() / quantisation_pixels,
                     projection.GetScreenHeight() / quantisation_pixels,
                     true);

  last_quantisation_pixels = quantisation_pixels;
#else
  height_matrix.Fill(map, projection, quantisation_pixels, true);
#endif
}
Beispiel #15
0
void
RasterRenderer::ScanMap(const RasterMap &map, const WindowProjection &projection)
{
  // Coordinates of the MapWindow center
  unsigned x = projection.GetScreenWidth() / 2;
  unsigned y = projection.GetScreenHeight() / 2;
  // GeoPoint corresponding to the MapWindow center
  GeoPoint Gmid = projection.ScreenToGeo(x, y);
  // GeoPoint "next to" Gmid (depends on terrain resolution)
  GeoPoint Gneighbor = projection.ScreenToGeo(x + quantisation_pixels,
                                              y + quantisation_pixels);

  // Geographical edge length of pixel in the MapWindow center in meters
  pixel_size = fixed_sqrt_half * Gmid.Distance(Gneighbor);

  // set resolution

  if (pixel_size < fixed(3000)) {
    /* round down to reduce slope shading artefacts (caused by
       RasterBuffer interpolation) */

    fixed map_pixel_size = map.PixelDistance(Gmid, 1);
    fixed q = map_pixel_size / pixel_size;
    quantisation_effective = std::max(1, (int)q);

    if (quantisation_effective > 25)
      /* disable slope shading when zoomed in very near (not enough
         terrain resolution to make a useful slope calculation) */
      quantisation_effective = 0;
  } else
    /* disable slope shading when zoomed out very far (too tiny) */
    quantisation_effective = 0;

#ifdef ENABLE_OPENGL
  bounds = projection.GetScreenBounds().Scale(fixed(1.5));
  height_matrix.Fill(map, bounds,
                     projection.GetScreenWidth() / quantisation_pixels,
                     projection.GetScreenHeight() / quantisation_pixels,
                     true);

  last_quantisation_pixels = quantisation_pixels;
#else
  height_matrix.Fill(map, projection, quantisation_pixels, true);
#endif
}
Beispiel #16
0
static void
PaintTask(Canvas &canvas, const WindowProjection &projection,
          const OrderedTask &task,
          const GeoPoint &location, const MapSettings &settings_map,
          const TaskLook &task_look,
          const AirspaceLook &airspace_look,
          const RasterTerrain *terrain)
{
  BackgroundRenderer background;
  background.SetTerrain(terrain);
  background.Draw(canvas, projection, settings_map.terrain);

  OZRenderer ozv(task_look, airspace_look, settings_map.airspace);
  RenderTaskPoint tpv(canvas, projection, task_look,
                      task.GetTaskProjection(),
                      ozv, false, RenderTaskPoint::NONE, location);
  TaskRenderer dv(tpv, projection.GetScreenBounds());
  dv.Draw(task);
}
Beispiel #17
0
static void
PaintTask(Canvas &canvas, const WindowProjection &projection,
          const OrderedTask &task,
          const GeoPoint &location, const SETTINGS_MAP &settings_map,
          const TaskLook &task_look,
          const AirspaceLook &airspace_look,
          const RasterTerrain *terrain)
{
  BackgroundDrawHelper background;
  background.set_terrain(terrain);
  background.Draw(canvas, projection, settings_map.terrain);

  RenderObservationZone ozv(task_look, airspace_look);
  RenderTaskPoint tpv(canvas, NULL, projection, settings_map, task_look,
                      task.get_task_projection(),
                      ozv, false, false, location);
  RenderTask dv(tpv, projection.GetScreenBounds());
  dv.Visit(task);
}
Beispiel #18
0
static void
PaintTask(Canvas &canvas, const WindowProjection &projection,
          const OrderedTask &task,
          const GeoPoint &location, const MapSettings &settings_map,
          const TaskLook &task_look,
          const AirspaceLook &airspace_look,
          const RasterTerrain *terrain, const Airspaces *airspaces)
{
  BackgroundRenderer background;
  background.SetTerrain(terrain);
  background.Draw(canvas, projection, settings_map.terrain);

  if (airspaces != NULL) {
    AirspaceRenderer airspace_renderer(airspace_look);
    airspace_renderer.SetAirspaces(airspaces);

#ifndef ENABLE_OPENGL
    BufferCanvas buffer_canvas, stencil_canvas;
    buffer_canvas.set(canvas);
    stencil_canvas.set(canvas);
#endif

    airspace_renderer.Draw(canvas,
#ifndef ENABLE_OPENGL
                           buffer_canvas, stencil_canvas,
#endif
                           projection,
                           settings_map.airspace);
  }

#ifdef ENABLE_OPENGL
  /* desaturate the map background, to focus on the task */
  canvas.FadeToWhite(0xc0);
#endif

  OZRenderer ozv(task_look, airspace_look, settings_map.airspace);
  RenderTaskPoint tpv(canvas, projection, task_look,
                      task.GetTaskProjection(),
                      ozv, false, RenderTaskPoint::NONE, location);
  TaskRenderer dv(tpv, projection.GetScreenBounds());
  dv.Draw(task);
}
void
RenderFAISector(Canvas &canvas, const WindowProjection &projection,
                const GeoPoint &pt1, const GeoPoint &pt2,
                bool reverse, const FAITriangleSettings &settings)
{
  GeoPoint geo_points[FAI_TRIANGLE_SECTOR_MAX];
  GeoPoint *geo_end = GenerateFAITriangleArea(geo_points, pt1, pt2,
                                              reverse, settings);

  GeoPoint clipped[FAI_TRIANGLE_SECTOR_MAX * 3],
    *clipped_end = clipped +
    GeoClip(projection.GetScreenBounds().Scale(fixed(1.1)))
    .ClipPolygon(clipped, geo_points, geo_end - geo_points);

  RasterPoint points[FAI_TRIANGLE_SECTOR_MAX], *p = points;
  for (GeoPoint *geo_i = clipped; geo_i != clipped_end;)
    *p++ = projection.GeoToScreen(*geo_i++);

  canvas.DrawPolygon(points, p - points);
}
Beispiel #20
0
RenderTaskPoint::RenderTaskPoint(Canvas &_canvas,
                                 const WindowProjection &_projection,
                                 const TaskLook &_task_look,
                                 const TaskProjection &_task_projection,
                                 OZRenderer &_ozv,
                                 bool _draw_bearing,
                                 TargetVisibility _target_visibility,
                                 const GeoPoint &_location)
    :canvas(_canvas), m_proj(_projection),
     map_canvas(_canvas, _projection,
                _projection.GetScreenBounds().Scale(fixed(1.1))),
     task_look(_task_look),
     task_projection(_task_projection),
     draw_bearing(_draw_bearing),
     target_visibility(_target_visibility),
     index(0),
     ozv(_ozv),
     active_index(0),
     location(_location),
     mode_optional_start(false)
{
}
Beispiel #21
0
void
TrailRenderer::Draw(Canvas &canvas, const TraceComputer &trace_computer,
                    const WindowProjection &projection, unsigned min_time,
                    bool enable_traildrift, const RasterPoint pos,
                    const NMEAInfo &basic, const DerivedInfo &calculated,
                    const TrailSettings &settings)
{
  if (settings.length == TrailSettings::Length::OFF)
    return;

  if (!LoadTrace(trace_computer, min_time, projection))
    return;

  if (!calculated.wind_available)
    enable_traildrift = false;

  GeoPoint traildrift;
  if (enable_traildrift) {
    GeoPoint tp1 = FindLatitudeLongitude(basic.location,
                                         calculated.wind.bearing,
                                         calculated.wind.norm);
    traildrift = basic.location - tp1;
  }

  auto minmax = GetMinMax(settings.type, trace);
  auto value_min = minmax.first;
  auto value_max = minmax.second;

  bool scaled_trail = settings.scaling_enabled &&
                      projection.GetMapScale() <= 6000;

  const GeoBounds bounds = projection.GetScreenBounds().Scale(4);

  RasterPoint last_point = RasterPoint(0, 0);
  bool last_valid = false;
  for (auto it = trace.begin(), end = trace.end(); it != end; ++it) {
    const GeoPoint gp = enable_traildrift
      ? it->GetLocation().Parametric(traildrift,
                                     it->CalculateDrift(basic.time))
      : it->GetLocation();
    if (!bounds.IsInside(gp)) {
      /* the point is outside of the MapWindow; don't paint it */
      last_valid = false;
      continue;
    }

    RasterPoint pt = projection.GeoToScreen(gp);

    if (last_valid) {
      if (settings.type == TrailSettings::Type::ALTITUDE) {
        unsigned index = GetAltitudeColorIndex(it->GetAltitude(),
                                               value_min, value_max);
        canvas.Select(look.trail_pens[index]);
        canvas.DrawLinePiece(last_point, pt);
      } else {
        unsigned color_index = GetSnailColorIndex(it->GetVario(),
                                                  value_min, value_max);
        if (it->GetVario() < 0 &&
            (settings.type == TrailSettings::Type::VARIO_1_DOTS ||
             settings.type == TrailSettings::Type::VARIO_2_DOTS ||
             settings.type == TrailSettings::Type::VARIO_DOTS_AND_LINES)) {
          canvas.SelectNullPen();
          canvas.Select(look.trail_brushes[color_index]);
          canvas.DrawCircle((pt.x + last_point.x) / 2, (pt.y + last_point.y) / 2,
                            look.trail_widths[color_index]);
        } else {
          // positive vario case

          if (settings.type == TrailSettings::Type::VARIO_DOTS_AND_LINES) {
            canvas.Select(look.trail_brushes[color_index]);
            canvas.Select(look.trail_pens[color_index]); //fixed-width pen
            canvas.DrawCircle((pt.x + last_point.x) / 2, (pt.y + last_point.y) / 2,
                              look.trail_widths[color_index]);
          } else if (scaled_trail)
            // width scaled to vario
            canvas.Select(look.scaled_trail_pens[color_index]);
          else
            // fixed-width pen
            canvas.Select(look.trail_pens[color_index]);

          canvas.DrawLinePiece(last_point, pt);
        }
      }
    }
    last_point = pt;
    last_valid = true;
  }

  if (last_valid)
    canvas.DrawLine(last_point, pos);
}
Beispiel #22
0
void
TrailRenderer::Draw(Canvas &canvas, const TraceComputer &trace_computer,
                    const WindowProjection &projection, unsigned min_time,
                    bool enable_traildrift, const RasterPoint pos,
                    const NMEAInfo &basic, const DerivedInfo &calculated,
                    const MapSettings &settings)
{
  if (settings.trail_length == TRAIL_OFF)
    return;

  if (!LoadTrace(trace_computer, min_time, projection))
    return;

  if (!calculated.wind_available)
    enable_traildrift = false;

  GeoPoint traildrift;
  if (enable_traildrift) {
    GeoPoint tp1 = FindLatitudeLongitude(basic.location,
                                         calculated.wind.bearing,
                                         calculated.wind.norm);
    traildrift = basic.location - tp1;
  }

  fixed value_max, value_min;

  if (settings.snail_type == stAltitude) {
    value_max = fixed(1000);
    value_min = fixed(500);
    for (auto it = trace.begin(); it != trace.end(); ++it) {
      value_max = max(it->GetAltitude(), value_max);
      value_min = min(it->GetAltitude(), value_min);
    }
  } else {
    value_max = fixed(0.75);
    value_min = fixed(-2.0);
    for (auto it = trace.begin(); it != trace.end(); ++it) {
      value_max = max(it->GetVario(), value_max);
      value_min = min(it->GetVario(), value_min);
    }
    value_max = min(fixed(7.5), value_max);
    value_min = max(fixed(-5.0), value_min);
  }

  bool scaled_trail = settings.snail_scaling_enabled &&
                      projection.GetMapScale() <= fixed_int_constant(6000);

  const GeoBounds bounds = projection.GetScreenBounds().Scale(fixed_four);

  RasterPoint last_point;
  bool last_valid = false;
  for (auto it = trace.begin(), end = trace.end(); it != end; ++it) {
    const GeoPoint gp = enable_traildrift
      ? it->get_location().Parametric(traildrift,
                                      it->CalculateDrift(basic.time))
      : it->get_location();
    if (!bounds.IsInside(gp)) {
      /* the point is outside of the MapWindow; don't paint it */
      last_valid = false;
      continue;
    }

    RasterPoint pt = projection.GeoToScreen(gp);

    if (last_valid) {
      if (settings.snail_type == stAltitude) {
        unsigned index((it->GetAltitude() - value_min) / (value_max - value_min)
                       * (TrailLook::NUMSNAILCOLORS - 1));
        index = max(0u, min(TrailLook::NUMSNAILCOLORS - 1, index));
        canvas.Select(look.hpSnail[index]);
      } else {
        const fixed colour_vario = negative(it->GetVario())
          ? - it->GetVario() / value_min
          : it->GetVario() / value_max ;

        if (!scaled_trail)
          canvas.Select(look.hpSnail[GetSnailColorIndex(colour_vario)]);
        else
          canvas.Select(look.hpSnailVario[GetSnailColorIndex(colour_vario)]);
      }
      canvas.line_piece(last_point, pt);
    }
    last_point = pt;
    last_valid = true;
  }

  canvas.line(last_point, pos);
}
void
TopographyFileRenderer::Paint(Canvas &canvas,
                              const WindowProjection &projection)
{
  if (file.IsEmpty())
    return;

  fixed map_scale = projection.GetMapScale();
  if (!file.IsVisible(map_scale))
    return;

  UpdateVisibleShapes(projection);

  if (visible_shapes.empty())
    return;

  // TODO code: only draw inside screen!
  // this will save time with rendering pixmaps especially
  // we already do an outer visibility test, but may need a test
  // in screen coords

#ifdef ENABLE_OPENGL
  pen.Set();
  brush.Set();
#else
  shape_renderer.Configure(&pen, &brush);
#endif

  // get drawing info

#ifdef ENABLE_OPENGL
  const unsigned level = file.GetThinningLevel(map_scale);
  const unsigned min_distance = file.GetMinimumPointDistance(level)
    / Layout::Scale(1);

#ifndef HAVE_GLES
  float opengl_matrix[16];
  glGetFloatv(GL_MODELVIEW_MATRIX, opengl_matrix);
#endif

  glPushMatrix();
  fixed angle = projection.GetScreenAngle().Degrees();
  fixed scale = projection.GetScale();
  const RasterPoint &screen_origin = projection.GetScreenOrigin();
#ifdef HAVE_GLES
#ifdef FIXED_MATH
  GLfixed fixed_angle = angle.as_glfixed();
  GLfixed fixed_scale = scale.as_glfixed_scale();
#else
  GLfixed fixed_angle = angle * (1<<16);
  GLfixed fixed_scale = scale * (1LL<<32);
#endif
  glTranslatex((int)screen_origin.x << 16, (int)screen_origin.y << 16, 0);
  glRotatex(fixed_angle, 0, 0, -(1<<16));
  glScalex(fixed_scale, fixed_scale, 1<<16);
#else
  glTranslatef(screen_origin.x, screen_origin.y, 0.);
  glRotatef((GLfloat)angle, 0., 0., -1.);
  glScalef((GLfloat)scale, (GLfloat)scale, 1.);
#endif
#else // !ENABLE_OPENGL
  const GeoClip clip(projection.GetScreenBounds().Scale(fixed(1.1)));
  AllocatedArray<GeoPoint> geo_points;

  int iskip = file.GetSkipSteps(map_scale);
#endif

  for (auto it = visible_shapes.begin(), end = visible_shapes.end();
       it != end; ++it) {
    const XShape &shape = **it;

    if (!projection.GetScreenBounds().Overlaps(shape.get_bounds()))
      continue;

#ifdef ENABLE_OPENGL
    const ShapePoint *points = shape.get_points();

    const ShapePoint translation =
      shape.shape_translation(projection.GetGeoLocation());
    glPushMatrix();
#ifdef HAVE_GLES
    glTranslatex(translation.x, translation.y, 0);
#else
    glTranslatef(translation.x, translation.y, 0.);
#endif
#else // !ENABLE_OPENGL
    const unsigned short *lines = shape.get_lines();
    const unsigned short *end_lines = lines + shape.get_number_of_lines();
    const GeoPoint *points = shape.get_points();
#endif

    switch (shape.get_type()) {
    case MS_SHAPE_NULL:
      break;

    case MS_SHAPE_POINT:
#ifdef ENABLE_OPENGL
#ifdef HAVE_GLES
      PaintPoint(canvas, projection, shape, NULL);
#else
      PaintPoint(canvas, projection, shape, opengl_matrix);
#endif
#else // !ENABLE_OPENGL
      PaintPoint(canvas, projection, lines, end_lines, points);
#endif
      break;

    case MS_SHAPE_LINE:
      {
#ifdef ENABLE_OPENGL
#ifdef HAVE_GLES
        glVertexPointer(2, GL_FIXED, 0, &points[0].x);
#else
        glVertexPointer(2, GL_INT, 0, &points[0].x);
#endif

        const GLushort *indices, *count;
        if (level == 0 ||
            (indices = shape.get_indices(level, min_distance, count)) == NULL) {
          count = shape.get_lines();
          const GLushort *end_count = count + shape.get_number_of_lines();
          for (int offset = 0; count < end_count; offset += *count++)
            glDrawArrays(GL_LINE_STRIP, offset, *count);
        } else {
          const GLushort *end_count = count + shape.get_number_of_lines();
          for (; count < end_count; indices += *count++)
            glDrawElements(GL_LINE_STRIP, *count, GL_UNSIGNED_SHORT, indices);
        }
#else // !ENABLE_OPENGL
      for (; lines < end_lines; ++lines) {
        unsigned msize = *lines;
        shape_renderer.Begin(msize);

        const GeoPoint *end = points + msize - 1;
        for (; points < end; ++points)
          shape_renderer.AddPointIfDistant(projection.GeoToScreen(*points));

        // make sure we always draw the last point
        shape_renderer.AddPoint(projection.GeoToScreen(*points));

        shape_renderer.FinishPolyline(canvas);
      }
#endif
      }
      break;

    case MS_SHAPE_POLYGON:
#ifdef ENABLE_OPENGL
      {
        const GLushort *index_count;
        const GLushort *triangles = shape.get_indices(level, min_distance,
                                                        index_count);

#ifdef HAVE_GLES
        glVertexPointer(2, GL_FIXED, 0, &points[0].x);
#else
        glVertexPointer(2, GL_INT, 0, &points[0].x);
#endif
        glDrawElements(GL_TRIANGLE_STRIP, *index_count, GL_UNSIGNED_SHORT,
                       triangles);
      }
#else // !ENABLE_OPENGL
      for (; lines < end_lines; ++lines) {
        unsigned msize = *lines / iskip;

        /* copy all polygon points into the geo_points array and clip
           them, to avoid integer overflows (as RasterPoint may store
           only 16 bit integers on some platforms) */

        geo_points.GrowDiscard(msize * 3);

        for (unsigned i = 0; i < msize; ++i)
          geo_points[i] = points[i * iskip];

        msize = clip.ClipPolygon(geo_points.begin(),
                                 geo_points.begin(), msize);
        if (msize < 3)
          continue;

        shape_renderer.Begin(msize);

        for (unsigned i = 0; i < msize; ++i) {
          GeoPoint g = geo_points[i];
          shape_renderer.AddPointIfDistant(projection.GeoToScreen(g));
        }

        shape_renderer.FinishPolygon(canvas);
      }
#endif
      break;
    }
#ifdef ENABLE_OPENGL
    glPopMatrix();
#endif
  }
#ifdef ENABLE_OPENGL
  glPopMatrix();
#else
  shape_renderer.Commit();
#endif
}
Beispiel #24
0
void
TrailRenderer::Draw(Canvas &canvas, const TraceComputer &trace_computer,
                    const WindowProjection &projection, unsigned min_time,
                    bool enable_traildrift, const RasterPoint pos,
                    const NMEAInfo &basic, const DerivedInfo &calculated,
                    const TrailSettings &settings)
{
  if (settings.length == TrailSettings::Length::OFF)
    return;

  if (!LoadTrace(trace_computer, min_time, projection))
    return;

  if (!calculated.wind_available)
    enable_traildrift = false;

  GeoPoint traildrift;
  if (enable_traildrift) {
    GeoPoint tp1 = FindLatitudeLongitude(basic.location,
                                         calculated.wind.bearing,
                                         calculated.wind.norm);
    traildrift = basic.location - tp1;
  }

  fixed value_max, value_min;
  GetMinMax(value_min, value_max, settings.type, trace);

  bool scaled_trail = settings.scaling_enabled &&
                      projection.GetMapScale() <= fixed_int_constant(6000);

  const GeoBounds bounds = projection.GetScreenBounds().Scale(fixed_four);

  RasterPoint last_point;
  bool last_valid = false;
  for (auto it = trace.begin(), end = trace.end(); it != end; ++it) {
    const GeoPoint gp = enable_traildrift
      ? it->GetLocation().Parametric(traildrift,
                                     it->CalculateDrift(basic.time))
      : it->GetLocation();
    if (!bounds.IsInside(gp)) {
      /* the point is outside of the MapWindow; don't paint it */
      last_valid = false;
      continue;
    }

    RasterPoint pt = projection.GeoToScreen(gp);

    if (last_valid) {
      if (settings.type == TrailSettings::Type::ALTITUDE) {
        unsigned index((it->GetAltitude() - value_min) / (value_max - value_min)
                       * (TrailLook::NUMSNAILCOLORS - 1));
        index = max(0u, min(TrailLook::NUMSNAILCOLORS - 1, index));
        canvas.Select(look.trail_pens[index]);
        canvas.DrawLinePiece(last_point, pt);
      } else {
        const fixed colour_vario = negative(it->GetVario())
          ? - it->GetVario() / value_min
          : it->GetVario() / value_max ;

        unsigned color_index = GetSnailColorIndex(colour_vario);
        if (negative(it->GetVario()) &&
            (settings.type == TrailSettings::Type::VARIO_1_DOTS ||
             settings.type == TrailSettings::Type::VARIO_2_DOTS)) {
          canvas.SelectNullPen();
          canvas.Select(look.trail_brushes[color_index]);
          canvas.DrawCircle((pt.x + last_point.x) / 2, (pt.y + last_point.y) / 2,
                            look.trail_widths[color_index]);

        } else {
          if (!scaled_trail)
            canvas.Select(look.trail_pens[color_index]);
          else
            canvas.Select(look.scaled_trail_pens[color_index]);

          canvas.DrawLinePiece(last_point, pt);
        }
      }
    }
    last_point = pt;
    last_valid = true;
  }

  if (last_valid)
    canvas.DrawLine(last_point, pos);
}
Beispiel #25
0
bool
TopographyFile::Update(const WindowProjection &map_projection)
{
    if (IsEmpty())
        return false;

    if (map_projection.GetMapScale() > scale_threshold)
        /* not visible, don't update cache now */
        return false;

    const GeoBounds screenRect =
        map_projection.GetScreenBounds();
    if (cache_bounds.IsValid() && cache_bounds.IsInside(screenRect))
        /* the cache is still fresh */
        return false;

    cache_bounds = screenRect.Scale(2);

    rectObj deg_bounds = ConvertRect(cache_bounds);

    // Test which shapes are inside the given bounds and save the
    // status to file.status
    switch (msShapefileWhichShapes(&file, dir, deg_bounds, 0)) {
    case MS_FAILURE:
        ClearCache();
        return false;

    case MS_DONE:
        /* screen is outside of map bounds */
        return false;

    case MS_SUCCESS:
        break;
    }

    assert(file.status != nullptr);

    // Iterate through the shapefile entries
    const ShapeList **current = &first;
    auto it = shapes.begin();
    for (int i = 0; i < file.numshapes; ++i, ++it) {
        if (!msGetBit(file.status, i)) {
            // If the shape is outside the bounds
            // delete the shape from the cache
            if (it->shape != nullptr) {
                assert(*current == it);

                /* remove from linked list (protected) */
                {
                    const ScopeLock lock(mutex);
                    *current = it->next;
                    ++serial;
                }

                /* now it's unreachable, and we can delete the XShape without
                   holding a lock */
                delete it->shape;
                it->shape = nullptr;
            }
        } else {
            // is inside the bounds
            if (it->shape == nullptr) {
                assert(*current != it);

                // shape isn't cached yet -> cache the shape
                it->shape = LoadShape(&file, center, i, label_field);
                it->next = *current;

                /* insert into linked list (protected) */
                {
                    const ScopeLock lock(mutex);
                    *current = it;
                    ++serial;
                }
            }

            current = &it->next;
        }
    }
    // end of list marker
    assert(*current == nullptr);

    return true;
}
Beispiel #26
0
void
PaintTask(Canvas &canvas, const WindowProjection &projection,
          const OrderedTask &task,
          const GeoPoint &location,
          const MapSettings &settings_map,
          const TaskLook &task_look,
          const AirspaceLook &airspace_look,
          const RasterTerrain *terrain, const Airspaces *airspaces,
          bool fai_sectors,
          int highlight_index)
{
  BackgroundRenderer background;
  background.SetTerrain(terrain);
  background.Draw(canvas, projection, settings_map.terrain);

  if (airspaces != NULL) {
    AirspaceRenderer airspace_renderer(airspace_look);
    airspace_renderer.SetAirspaces(airspaces);

#ifndef ENABLE_OPENGL
    BufferCanvas stencil_canvas;
    stencil_canvas.Create(canvas);
#endif

    airspace_renderer.Draw(canvas,
#ifndef ENABLE_OPENGL
                           stencil_canvas,
#endif
                           projection, settings_map.airspace);
  }

#ifdef ENABLE_OPENGL
  /* desaturate the map background, to focus on the task */
  canvas.FadeToWhite(0xc0);
#endif

  if (fai_sectors && IsFAITriangleApplicable(task)) {
    static constexpr Color fill_color = COLOR_YELLOW;
#if defined(ENABLE_OPENGL) || defined(USE_MEMORY_CANVAS)
#ifdef ENABLE_OPENGL
    const ScopeAlphaBlend alpha_blend;
#endif

    canvas.Select(Brush(fill_color.WithAlpha(40)));
    canvas.Select(Pen(1, COLOR_BLACK.WithAlpha(80)));
    RenderFAISectors(canvas, projection, task);
#else
    BufferCanvas buffer_canvas;
    buffer_canvas.Create(canvas);
    buffer_canvas.ClearWhite();
#ifdef HAVE_HATCHED_BRUSH
    buffer_canvas.Select(airspace_look.brushes[3]);
    buffer_canvas.SetTextColor(fill_color);
    buffer_canvas.SetBackgroundColor(COLOR_WHITE);
#else
    buffer_canvas.Select(Brush(fill_color));
#endif
    buffer_canvas.SelectNullPen();
    RenderFAISectors(buffer_canvas, projection, task);
    canvas.CopyAnd(buffer_canvas);

    canvas.SelectHollowBrush();
    canvas.SelectBlackPen();
    RenderFAISectors(canvas, projection, task);
#endif
  }

  OZRenderer ozv(task_look, airspace_look, settings_map.airspace);
  TaskPointRenderer tpv(canvas, projection, task_look,
                        task.GetTaskProjection(),
                        ozv, false, TaskPointRenderer::NONE,
                        location);
  TaskRenderer dv(tpv, projection.GetScreenBounds());
  dv.Draw(task);

  // highlight a task point
  if (highlight_index >= 0 && highlight_index < (int) task.TaskSize()) {
    /* TODO: clumsy way of highlighting. maybe it should be done by
     *       painting the task point with a different pen and brush,
     *       e.g. red, 4px wide
     */
    auto pt = projection.GeoToScreen(task.GetPoint(highlight_index).
                                     GetLocation());
    canvas.Select(task_look.highlight_pen);
    canvas.DrawLine(pt.x - 7, pt.y - 7, pt.x + 7, pt.y + 7);
    canvas.DrawLine(pt.x + 7, pt.y - 7, pt.x - 7, pt.y + 7);
  }
}
Beispiel #27
0
bool
TopographyFile::Update(const WindowProjection &map_projection)
{
  if (IsEmpty())
    return false;

  if (map_projection.GetMapScale() > scale_threshold)
    /* not visible, don't update cache now */
    return false;

  const GeoBounds screenRect =
    map_projection.GetScreenBounds();
  if (cache_bounds.inside(screenRect))
    /* the cache is still fresh */
    return false;

  cache_bounds = map_projection.GetScreenBounds().scale(fixed_two);

  rectObj deg_bounds = ConvertRect(cache_bounds);

  // Test which shapes are inside the given bounds and save the
  // status to file.status
  msShapefileWhichShapes(&file, dir, deg_bounds, 0);

  // If not a single shape is inside the bounds
  if (!file.status) {
    // ... clear the whole buffer
    ClearCache();
    return false;
  }

  // Iterate through the shapefile entries
  for (int i = 0; i < file.numshapes; i++) {
    if (!msGetBit(file.status, i)) {
      // If the shape is outside the bounds
      // delete the shape from the cache
      delete shapes[i].shape;
      shapes[i].shape = NULL;
    } else if (shapes[i].shape == NULL) {
      // If the shape is inside the bounds and if the
      // shape isn't cached yet -> cache the shape
      shapes[i].shape = new XShape(&file, i, label_field);
    }
  }

  ShapeList::NotNull not_null;
  XShapePointerArray::iterator end = shapes.end(), it = shapes.begin();
  it = std::find_if(it, end, not_null);
  if (it != shapes.end()) {
    ShapeList *current = &*it;
    first = current;

    while (true) {
      ++it;
      it = std::find_if(it, end, not_null);
      if (it == end) {
        current->next = NULL;
        break;
      }

      ShapeList *next = &*it;
      current->next = next;
      current = next;
    }
  } else
    first = NULL;

  return true;
}
void
TopographyFileRenderer::PaintLabels(Canvas &canvas,
                                    const WindowProjection &projection,
                                    LabelBlock &label_block)
{
  if (file.IsEmpty())
    return;

  fixed map_scale = projection.GetMapScale();
  if (!file.IsVisible(map_scale) || !file.IsLabelVisible(map_scale))
    return;

  UpdateVisibleShapes(projection);

  if (visible_labels.empty())
    return;

  // TODO code: only draw inside screen!
  // this will save time with rendering pixmaps especially
  // we already do an outer visibility test, but may need a test
  // in screen coords

  canvas.Select(file.IsLabelImportant(map_scale) ?
                Fonts::map_label_important : Fonts::map_label);
  canvas.SetTextColor(Color(0x20, 0x20, 0x20));
  canvas.SetBackgroundTransparent();

  // get drawing info

  int iskip = file.GetSkipSteps(map_scale);

#ifdef ENABLE_OPENGL
  Matrix2D m1;
  m1.Translate(projection.GetScreenOrigin());
  m1.Rotate(projection.GetScreenAngle());
  m1.Scale(projection.GetScale());
#endif

  // Iterate over all shapes in the file
  for (auto it = visible_labels.begin(), end = visible_labels.end();
       it != end; ++it) {
    const XShape &shape = **it;

    if (!projection.GetScreenBounds().Overlaps(shape.get_bounds()))
      continue;

    // Skip shapes without a label
    const TCHAR *label = shape.get_label();
    if (label == NULL)
      continue;

    const unsigned short *lines = shape.get_lines();
    const unsigned short *end_lines = lines + shape.get_number_of_lines();
#ifdef ENABLE_OPENGL
    const ShapePoint *points = shape.get_points();

    Matrix2D m2(m1);
    m2.Translatex(shape.shape_translation(projection.GetGeoLocation()));
#else
    const GeoPoint *points = shape.get_points();
#endif

    for (; lines < end_lines; ++lines) {
      int minx = canvas.get_width();
      int miny = canvas.get_height();

#ifdef ENABLE_OPENGL
      const ShapePoint *end = points + *lines;
#else
      const GeoPoint *end = points + *lines;
#endif
      for (; points < end; points += iskip) {
#ifdef ENABLE_OPENGL
        RasterPoint pt = m2.Apply(*points);
#else
        RasterPoint pt = projection.GeoToScreen(*points);
#endif

        if (pt.x <= minx) {
          minx = pt.x;
          miny = pt.y;
        }
      }

      points = end;

      minx += 2;
      miny += 2;

      PixelSize tsize = canvas.CalcTextSize(label);
      PixelRect brect;
      brect.left = minx;
      brect.right = brect.left + tsize.cx;
      brect.top = miny;
      brect.bottom = brect.top + tsize.cy;

      if (!label_block.check(brect))
        continue;

      canvas.text(minx, miny, label);
    }
  }
}