Renderer, ...: use PixelRect::GetCenter()
[xcsoar.git] / src / CrossSection / CrossSectionRenderer.cpp
blob8cd766a66a15379d95d396451e247025fe6edb5d
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "CrossSectionRenderer.hpp"
25 #include "Renderer/ChartRenderer.hpp"
26 #include "Renderer/GradientRenderer.hpp"
27 #include "Screen/Canvas.hpp"
28 #include "Screen/Layout.hpp"
29 #include "Look/CrossSectionLook.hpp"
30 #include "Terrain/RasterTerrain.hpp"
31 #include "Units/Units.hpp"
32 #include "NMEA/Aircraft.hpp"
33 #include "Navigation/Aircraft.hpp"
34 #include "Engine/GlideSolvers/GlideState.hpp"
35 #include "Engine/GlideSolvers/MacCready.hpp"
37 #ifdef ENABLE_OPENGL
38 #include "Screen/OpenGL/Scope.hpp"
39 #endif
41 CrossSectionRenderer::CrossSectionRenderer(const CrossSectionLook &_look,
42 const AirspaceLook &_airspace_look,
43 const ChartLook &_chart_look)
44 :look(_look), chart_look(_chart_look), airspace_renderer(_airspace_look),
45 terrain_renderer(look), terrain(NULL), airspace_database(NULL),
46 start(GeoPoint::Invalid()),
47 vec(fixed(50000), Angle::Zero()) {}
49 void
50 CrossSectionRenderer::ReadBlackboard(const MoreData &_gps_info,
51 const DerivedInfo &_calculated_info,
52 const GlideSettings &_glide_settings,
53 const GlidePolar &_glide_polar,
54 const AirspaceRendererSettings &ar_settings)
56 gps_info = _gps_info;
57 calculated_info = _calculated_info;
58 glide_settings = _glide_settings;
59 glide_polar = _glide_polar;
60 airspace_renderer.SetSettings(ar_settings);
63 void
64 CrossSectionRenderer::Paint(Canvas &canvas, const PixelRect rc) const
66 DrawVerticalGradient(canvas, rc,
67 look.sky_color, look.background_color,
68 look.background_color);
70 canvas.SetTextColor(look.text_color);
71 canvas.Select(*look.grid_font);
73 ChartRenderer chart(chart_look, canvas, rc);
75 if (!vec.IsValid() || !start.IsValid()) {
76 chart.DrawNoData();
77 return;
80 const fixed nav_altitude = gps_info.NavAltitudeAvailable()
81 ? gps_info.nav_altitude
82 : fixed(0);
83 fixed hmin = std::max(fixed(0), nav_altitude - fixed(3300));
84 fixed hmax = std::max(fixed(3300), nav_altitude + fixed(1000));
86 chart.ResetScale();
87 chart.ScaleXFromValue(fixed(0));
88 chart.ScaleXFromValue(vec.distance);
89 chart.ScaleYFromValue(hmin);
90 chart.ScaleYFromValue(hmax);
92 short elevations[NUM_SLICES];
93 UpdateTerrain(elevations);
95 if (airspace_database)
96 airspace_renderer.Draw(canvas, chart, *airspace_database, start, vec,
97 ToAircraftState(Basic(), Calculated()));
98 terrain_renderer.Draw(canvas, chart, elevations);
99 PaintGlide(chart);
100 PaintAircraft(canvas, chart, rc);
101 PaintGrid(canvas, chart);
104 void
105 CrossSectionRenderer::UpdateTerrain(short *elevations) const
107 if (terrain == NULL) {
108 const auto invalid = RasterBuffer::TERRAIN_INVALID;
109 std::fill(elevations, elevations + NUM_SLICES, invalid);
110 return;
113 const GeoPoint point_diff = vec.EndPoint(start) - start;
115 RasterTerrain::Lease map(*terrain);
116 for (unsigned i = 0; i < NUM_SLICES; ++i) {
117 const fixed slice_distance_factor = fixed(i) / (NUM_SLICES - 1);
118 const GeoPoint slice_point = start + point_diff * slice_distance_factor;
120 elevations[i] = map->GetHeight(slice_point);
124 void
125 CrossSectionRenderer::PaintGlide(ChartRenderer &chart) const
127 if (!gps_info.NavAltitudeAvailable() || !glide_polar.IsValid())
128 return;
130 const fixed altitude = gps_info.nav_altitude;
132 const MacCready mc(glide_settings, glide_polar);
133 const GlideState task(vec, fixed(0), altitude,
134 calculated_info.GetWindOrZero());
135 const GlideResult result = mc.SolveStraight(task);
136 if (!result.IsOk())
137 return;
139 chart.DrawLine(fixed(0), altitude, result.vector.distance,
140 result.GetArrivalAltitude(),
141 ChartLook::STYLE_BLUETHIN);
144 void
145 CrossSectionRenderer::PaintAircraft(Canvas &canvas, const ChartRenderer &chart,
146 const PixelRect rc) const
148 if (!gps_info.NavAltitudeAvailable())
149 return;
151 canvas.Select(look.aircraft_brush);
152 canvas.SelectNullPen();
154 RasterPoint line[4];
155 line[0] = chart.ToScreen(fixed(0), gps_info.nav_altitude);
156 line[1].x = rc.left;
157 line[1].y = line[0].y;
158 line[2].x = line[1].x;
159 line[2].y = line[0].y - (line[0].x - line[1].x) / 2;
160 line[3].x = (line[1].x + line[0].x) / 2;
161 line[3].y = line[0].y;
162 canvas.DrawTriangleFan(line, 4);
165 void
166 CrossSectionRenderer::PaintGrid(Canvas &canvas, ChartRenderer &chart) const
168 canvas.SetTextColor(look.text_color);
170 chart.DrawXGrid(Units::ToSysDistance(fixed(5)),
171 look.grid_pen, fixed(5), true);
172 chart.DrawYGrid(Units::ToSysAltitude(fixed(1000)),
173 look.grid_pen, fixed(1000), true);
175 chart.DrawXLabel(_T("D"), Units::GetDistanceName());
176 chart.DrawYLabel(_T("h"), Units::GetAltitudeName());