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 }
virtual void OnPaint(Canvas &canvas) override { canvas.ClearWhite(); const GeoPoint a(Angle::Degrees(7.70722), Angle::Degrees(51.052)); const GeoPoint b(Angle::Degrees(11.5228), Angle::Degrees(50.3972)); WindowProjection projection; projection.SetScreenOrigin(canvas.GetWidth() / 2, canvas.GetHeight() / 2); projection.SetGeoLocation(a.Middle(b)); projection.SetScreenSize(canvas.GetSize()); projection.SetScaleFromRadius(fixed(400000)); projection.UpdateScreenBounds(); canvas.SelectBlackPen(); canvas.SelectHollowBrush(); RasterPoint pa = projection.GeoToScreen(a); canvas.DrawCircle(pa.x, pa.y, 4); RasterPoint pb = projection.GeoToScreen(b); canvas.DrawCircle(pb.x, pb.y, 4); RenderFAISector(canvas, projection, a, b, false, settings); }
static void GetPolygonPoints(std::vector<RasterPoint> &pts, const AirspacePolygon &airspace, const RasterPoint pt, unsigned radius) { GeoBounds bounds = airspace.GetGeoBounds(); GeoPoint center = bounds.GetCenter(); fixed geo_heigth = bounds.GetGeoHeight(); fixed geo_width = bounds.GetGeoWidth(); fixed geo_size = std::max(geo_heigth, geo_width); WindowProjection projection; projection.SetScreenSize({radius * 2, radius * 2}); projection.SetScreenOrigin(pt.x, pt.y); projection.SetGeoLocation(center); projection.SetScale(fixed(radius * 2) / geo_size); projection.SetScreenAngle(Angle::Zero()); projection.UpdateScreenBounds(); const SearchPointVector &border = airspace.GetPoints(); pts.reserve(border.size()); for (auto it = border.begin(), it_end = border.end(); it != it_end; ++it) pts.push_back(projection.GeoToScreen(it->GetLocation())); }
/** * Draws the terrain to the given canvas * @param canvas The drawing canvas * @param map_projection The Projection * @param sunazimuth Azimuth of the sun (for terrain shading) */ void TerrainRenderer::Draw(Canvas &canvas, const WindowProjection &map_projection) const { #ifdef ENABLE_OPENGL const GeoBounds &bounds = raster_renderer.GetBounds(); assert(bounds.IsValid()); const RasterPoint vertices[] = { map_projection.GeoToScreen(bounds.GetNorthWest()), map_projection.GeoToScreen(bounds.GetNorthEast()), map_projection.GeoToScreen(bounds.GetSouthWest()), map_projection.GeoToScreen(bounds.GetSouthEast()), }; glVertexPointer(2, GL_VALUE, 0, vertices); const GLTexture &texture = raster_renderer.BindAndGetTexture(); const PixelSize allocated = texture.GetAllocatedSize(); const int src_x = 0, src_y = 0, src_width = raster_renderer.GetWidth(), src_height = raster_renderer.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; const GLfloat coord[] = { x0, y0, x1, y0, x0, y1, x1, y1, }; OpenGL::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); GLEnable scope(GL_TEXTURE_2D); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, coord); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); #else CopyTo(canvas, map_projection.GetScreenWidth(), map_projection.GetScreenHeight()); #endif }
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); }
void TrackLineRenderer::DrawProjected(Canvas &canvas, const WindowProjection &projection, const NMEAInfo &basic, const DerivedInfo &calculated, const MapSettings &settings, bool wind_relative) { // projection.GetMapScale() <= 6000; GeoPoint traildrift; if (calculated.wind_available && !wind_relative) { GeoPoint tp1 = FindLatitudeLongitude(basic.location, calculated.wind.bearing, calculated.wind.norm); traildrift = basic.location - tp1; } else { traildrift = GeoPoint(Angle::Zero(), Angle::Zero()); } auto dt = ARC_SWEEP/ARC_STEPS/ std::max(MIN_RATE,calculated.turn_rate_heading_smoothed.Absolute()); Angle heading = basic.attitude.heading; GeoPoint loc = basic.location; RasterPoint pts[ARC_STEPS+1]; pts[0] = projection.GeoToScreen(loc); int i = 1; while (i <= ARC_STEPS) { GeoVector v(basic.true_airspeed*dt, heading); loc = v.EndPoint(loc.Parametric(traildrift, dt)); pts[i] = projection.GeoToScreen(loc); heading += calculated.turn_rate_heading_smoothed*dt; i++; } canvas.Select(look.track_line_pen); canvas.DrawPolyline(pts, i); }
void TrailRenderer::Draw(Canvas &canvas, const WindowProjection &projection, const ContestTraceVector &trace) { points.GrowDiscard(trace.size()); unsigned n = 0; for (auto i = trace.begin(), end = trace.end(); i != end; ++i) points[n++] = projection.GeoToScreen(i->get_location()); canvas.DrawPolyline(points.begin(), n); }
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); }
static void DrawPolygon(Canvas &canvas, const AirspacePolygon &airspace, const RasterPoint pt, unsigned radius) { if (IsAncientHardware()) { canvas.Rectangle(pt.x - radius, pt.y - radius, pt.x + radius, pt.y + radius); return; } GeoBounds bounds = airspace.GetGeoBounds(); GeoPoint center = bounds.GetCenter(); fixed geo_heigth = GeoPoint(center.longitude, bounds.north).Distance( GeoPoint(center.longitude, bounds.south)); fixed geo_width = GeoPoint(bounds.west, center.latitude).Distance( GeoPoint(bounds.east, center.latitude)); fixed geo_size = std::max(geo_heigth, geo_width); WindowProjection projection; projection.SetScreenSize(radius * 2, radius * 2); projection.SetScreenOrigin(pt.x, pt.y); projection.SetGeoLocation(center); projection.SetScale(fixed(radius * 2) / geo_size); projection.SetScreenAngle(Angle::Zero()); projection.UpdateScreenBounds(); const SearchPointVector &border = airspace.GetPoints(); std::vector<RasterPoint> pts; pts.reserve(border.size()); for (auto it = border.begin(), it_end = border.end(); it != it_end; ++it) pts.push_back(projection.GeoToScreen(it->get_location())); canvas.polygon(&pts[0], (unsigned)pts.size()); }
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::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); } } }
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 }
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); }
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); } }
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); }
void AirspaceLabelRenderer::DrawInternal(Canvas &canvas, #ifndef ENABLE_OPENGL Canvas &stencil_canvas, #endif const WindowProjection &projection, const AirspaceRendererSettings &settings, const AirspaceWarningCopy &awc, const AirspacePredicate &visible, const AirspaceWarningConfig &config) { AirspaceLabelList labels; for (const auto &i : airspaces->QueryWithinRange(projection.GetGeoScreenCenter(), projection.GetScreenDistanceMeters())) { const AbstractAirspace &airspace = i.GetAirspace(); if (visible(airspace)) labels.Add(airspace.GetCenter(), airspace.GetType(), airspace.GetBase(), airspace.GetTop()); } if(settings.label_selection == AirspaceRendererSettings::LabelSelection::ALL) { labels.Sort(config); // default paint settings canvas.SetTextColor(look.label_text_color); canvas.Select(*look.name_font); canvas.Select(look.label_pen); canvas.Select(look.label_brush); canvas.SetBackgroundTransparent(); // draw TCHAR topText[NAME_SIZE + 1]; TCHAR baseText[NAME_SIZE + 1]; for (const auto &label : labels) { // size of text AirspaceFormatter::FormatAltitudeShort(topText, label.top, false); PixelSize topSize = canvas.CalcTextSize(topText); AirspaceFormatter::FormatAltitudeShort(baseText, label.base, false); PixelSize baseSize = canvas.CalcTextSize(baseText); int labelWidth = std::max(topSize.cx, baseSize.cx) + 2 * Layout::GetTextPadding(); int labelHeight = topSize.cy + baseSize.cy; // box const auto pos = projection.GeoToScreen(label.pos); PixelRect rect; rect.left = pos.x - labelWidth / 2; rect.top = pos.y; rect.right = rect.left + labelWidth; rect.bottom = rect.top + labelHeight; canvas.Rectangle(rect.left, rect.top, rect.right, rect.bottom); #ifdef USE_GDI canvas.DrawLine(rect.left + Layout::GetTextPadding(), rect.top + labelHeight / 2, rect.right - Layout::GetTextPadding(), rect.top + labelHeight / 2); #else canvas.DrawHLine(rect.left + Layout::GetTextPadding(), rect.right - Layout::GetTextPadding(), rect.top + labelHeight / 2, look.label_pen.GetColor()); #endif // top text int x = rect.right - Layout::GetTextPadding() - topSize.cx; int y = rect.top; canvas.DrawText(x, y, topText); // base text x = rect.right - Layout::GetTextPadding() - baseSize.cx; y = rect.bottom - baseSize.cy; canvas.DrawText(x, y, baseText); } } }