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"
38 #include "Screen/OpenGL/Scope.hpp"
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()) {}
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
)
57 calculated_info
= _calculated_info
;
58 glide_settings
= _glide_settings
;
59 glide_polar
= _glide_polar
;
60 airspace_renderer
.SetSettings(ar_settings
);
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()) {
80 const fixed nav_altitude
= gps_info
.NavAltitudeAvailable()
81 ? gps_info
.nav_altitude
83 fixed hmin
= std::max(fixed(0), nav_altitude
- fixed(3300));
84 fixed hmax
= std::max(fixed(3300), nav_altitude
+ fixed(1000));
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
);
100 PaintAircraft(canvas
, chart
, rc
);
101 PaintGrid(canvas
, chart
);
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
);
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
);
125 CrossSectionRenderer::PaintGlide(ChartRenderer
&chart
) const
127 if (!gps_info
.NavAltitudeAvailable() || !glide_polar
.IsValid())
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
);
139 chart
.DrawLine(fixed(0), altitude
, result
.vector
.distance
,
140 result
.GetArrivalAltitude(),
141 ChartLook::STYLE_BLUETHIN
);
145 CrossSectionRenderer::PaintAircraft(Canvas
&canvas
, const ChartRenderer
&chart
,
146 const PixelRect rc
) const
148 if (!gps_info
.NavAltitudeAvailable())
151 canvas
.Select(look
.aircraft_brush
);
152 canvas
.SelectNullPen();
155 line
[0] = chart
.ToScreen(fixed(0), gps_info
.nav_altitude
);
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);
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());