OpenCPN Partial API docs
Loading...
Searching...
No Matches
track_gui.cpp
1#include <list>
2
3#include <wx/colour.h>
4#include <wx/gdicmn.h>
5#include <wx/pen.h>
6
7#include "color_handler.h"
8#include "navutil.h"
9#include "own_ship.h"
10#include "routeman.h"
11#include "track_gui.h"
12#include "glChartCanvas.h"
13
14extern Routeman* g_pRouteMan;
15extern wxColour g_colourTrackLineColour;
16
17extern wxColor GetDimColor(wxColor c);
18extern bool g_bHighliteTracks;
19extern float g_GLMinSymbolLineWidth;
20
21extern ocpnGLOptions g_GLOptions;
22
23void TrackPointGui::Draw(ChartCanvas* cc, ocpnDC& dc) {
24 wxPoint r;
25 wxRect hilitebox;
26
27 cc->GetCanvasPointPix(m_point.m_lat, m_point.m_lon, &r);
28
29 wxPen *pen;
30 pen = g_pRouteMan->GetRoutePointPen();
31
32 int sx2 = 8;
33 int sy2 = 8;
34
35 wxRect r1(r.x - sx2, r.y - sy2, sx2 * 2, sy2 * 2); // the bitmap extents
36
37 hilitebox = r1;
38 hilitebox.x -= r.x;
39 hilitebox.y -= r.y;
40 float radius;
41 hilitebox.Inflate(4);
42 radius = 4.0f;
43
44 wxColour hi_colour = pen->GetColour();
45 unsigned char transparency = 100;
46
47 // Highlite any selected point
48 AlphaBlending(dc, r.x + hilitebox.x, r.y + hilitebox.y, hilitebox.width,
49 hilitebox.height, radius, hi_colour, transparency);
50}
51
52void TrackGui::Finalize() {
53 if (m_track.SubTracks.size()) // subtracks already computed
54 return;
55
56 // OCPNStopWatch sw1;
57
58 int n = m_track.TrackPoints.size() - 1;
59 int level = 0;
60 while (n > 0) {
61 std::vector<SubTrack> new_level;
62 new_level.resize(n);
63 if (level == 0)
64 for (int i = 0; i < n; i++) {
65 new_level[i].m_box.SetFromSegment(
66 m_track.TrackPoints[i]->m_lat, m_track.TrackPoints[i]->m_lon,
67 m_track.TrackPoints[i + 1]->m_lat,
68 m_track.TrackPoints[i + 1]->m_lon);
69 new_level[i].m_scale = 0;
70 }
71 else {
72 for (int i = 0; i < n; i++) {
73 int p = i << 1;
74 new_level[i].m_box = m_track.SubTracks[level - 1][p].m_box;
75 if (p + 1 < (int)m_track.SubTracks[level - 1].size())
76 new_level[i].m_box.Expand(m_track.SubTracks[level - 1][p + 1].m_box);
77
78 int left = i << level;
79 int right = wxMin(left + (1 << level), m_track.TrackPoints.size() - 1);
80 new_level[i].m_scale = m_track.ComputeScale(left, right);
81 }
82 }
83 m_track.SubTracks.push_back(new_level);
84
85 if (n > 1 && n & 1) n++;
86 n >>= 1;
87 level++;
88 }
89 // if(m_track.TrackPoints.size() > 100)
90 // printf("fin time %f %d\n", sw1.GetTime(), (int)m_track.TrackPoints.size());
91}
92
93
94void TrackGui::GetPointLists(ChartCanvas *cc,
95 std::list<std::list<wxPoint> > &pointlists,
96 ViewPort &VP, const LLBBox &box) {
97
98 if (!m_track.IsVisible() || m_track.GetnPoints() == 0) return;
99 Finalize();
100 // OCPNStopWatch sw;
101 Segments(cc, pointlists, box, VP.view_scale_ppm);
102#if 0
103 if(GetnPoints() > 40000) {
104 double t = sw.GetTime();
105 double c = 0;
106 for(std::list< std::list<wxPoint> >::iterator lines = pointlists.begin();
107 lines != pointlists.end(); lines++) {
108 if(lines->size() > 1)
109 c += lines->size();
110 continue;
111 }
112 printf("assemble time %f %f segments %f seg/ms\n", sw.GetTime(), c, c/t);
113 }
114#endif
115
116 // Add last segment, dynamically, maybe.....
117 // we should not add this segment if it is not on the screen...
118 if (m_track.IsRunning()) {
119 std::list<wxPoint> new_list;
120 pointlists.push_back(new_list);
121 AddPointToList(cc, pointlists, m_track.TrackPoints.size() - 1);
122 wxPoint r;
123 cc->GetCanvasPointPix(gLat, gLon, &r);
124 pointlists.back().push_back(r);
125 }
126}
127
128void TrackGui::Draw(ChartCanvas* cc, ocpnDC& dc, ViewPort& VP,
129 const LLBBox& box) {
130 std::list<std::list<wxPoint> > pointlists;
131 GetPointLists(cc, pointlists, VP, box);
132
133 if (!pointlists.size()) return;
134
135 // Establish basic colour
136 wxColour basic_colour;
137 if (m_track.IsRunning())
138 basic_colour = GetGlobalColor(_T ( "URED" ));
139 else
140 basic_colour = GetDimColor(g_colourTrackLineColour);
141
142 wxPenStyle style = wxPENSTYLE_SOLID;
143 int width = g_pRouteMan->GetTrackPen()->GetWidth();
144 wxColour col;
145 if (m_track.m_style != wxPENSTYLE_INVALID) style = m_track.m_style;
146 if (m_track.m_width != WIDTH_UNDEFINED) width = m_track.m_width;
147 if (m_track.m_Colour == wxEmptyString) {
148 col = basic_colour;
149 } else {
150 for (unsigned int i = 0; i < sizeof(::GpxxColorNames) / sizeof(wxString);
151 i++) {
152 if (m_track.m_Colour == ::GpxxColorNames[i]) {
153 col = ::GpxxColors[i];
154 break;
155 }
156 }
157 }
158
159 double radius = 0.;
160 if (g_bHighliteTracks) {
161 double radius_meters = 20; // 1.5 mm at original scale
162 radius = radius_meters * VP.view_scale_ppm;
163 if (radius < 1.0) radius = 0;
164 }
165
166 {
167 dc.SetPen(*wxThePenList->FindOrCreatePen(col, width, style));
168 dc.SetBrush(*wxTheBrushList->FindOrCreateBrush(col, wxBRUSHSTYLE_SOLID));
169 for (std::list<std::list<wxPoint> >::iterator lines = pointlists.begin();
170 lines != pointlists.end(); lines++) {
171 // convert from linked list to array
172 wxPoint *points = new wxPoint[lines->size()];
173 int i = 0;
174 for (std::list<wxPoint>::iterator line = lines->begin();
175 line != lines->end(); line++) {
176 points[i] = *line;
177 i++;
178 }
179
180 int hilite_width = radius;
181 if (hilite_width >= 1.0) {
182 wxPen psave = dc.GetPen();
183
184 dc.StrokeLines(i, points);
185
186 wxColor trackLine_dim_colour = GetDimColor(g_colourTrackLineColour);
187 wxColour hilt(trackLine_dim_colour.Red(), trackLine_dim_colour.Green(),
188 trackLine_dim_colour.Blue(), 128);
189
190 wxPen HiPen(hilt, hilite_width, wxPENSTYLE_SOLID);
191 dc.SetPen(HiPen);
192
193 dc.StrokeLines(i, points);
194
195 dc.SetPen(psave);
196 } else
197 dc.StrokeLines(i, points);
198
199 delete[] points;
200 }
201 }
202
203 if (m_track.m_HighlightedTrackPoint >= 0)
204 TrackPointGui(m_track.TrackPoints[m_track.m_HighlightedTrackPoint]).Draw(cc, dc);
205}
206
207// Entry to recursive Assemble at the head of the SubTracks tree
208void TrackGui::Segments(ChartCanvas *cc,
209 std::list<std::list<wxPoint> > &pointlists,
210 const LLBBox &box, double scale) {
211 if (!m_track.SubTracks.size()) return;
212
213 int level = m_track.SubTracks.size() - 1, last = -2;
214 Assemble(cc, pointlists, box, 1 / scale / scale, last, level, 0);
215}
216
217/* assembles lists of line strips from the given track recursively traversing
218 the subtracks data */
219void TrackGui::Assemble(ChartCanvas *cc,
220 std::list<std::list<wxPoint> > &pointlists,
221 const LLBBox &box, double scale, int &last, int level,
222 int pos) {
223 if (pos == (int)m_track.SubTracks[level].size()) return;
224
225 SubTrack &s = m_track.SubTracks[level][pos];
226 if (box.IntersectOut(s.m_box)) return;
227
228 if (s.m_scale < scale) {
229 pos <<= level;
230
231 if (last < pos - 1) {
232 std::list<wxPoint> new_list;
233 pointlists.push_back(new_list);
234 }
235
236 if (last < pos) AddPointToList(cc, pointlists, pos);
237 last = wxMin(pos + (1 << level), m_track.TrackPoints.size() - 1);
238 AddPointToList(cc, pointlists, last);
239 } else {
240 Assemble(cc, pointlists, box, scale, last, level - 1, pos << 1);
241 Assemble(cc, pointlists, box, scale, last, level - 1, (pos << 1) + 1);
242 }
243}
244
245void TrackGui::AddPointToList(ChartCanvas *cc,
246 std::list<std::list<wxPoint> > &pointlists, int n) {
247 wxPoint r(INVALID_COORD, INVALID_COORD);
248 if ((size_t)n < m_track.TrackPoints.size())
249 cc->GetCanvasPointPix(m_track.TrackPoints[n]->m_lat, m_track.TrackPoints[n]->m_lon, &r);
250
251 std::list<wxPoint> &pointlist = pointlists.back();
252 if (r.x == INVALID_COORD) {
253 if (pointlist.size()) {
254 std::list<wxPoint> new_list;
255 pointlists.push_back(new_list);
256 }
257 return;
258 }
259
260 if (pointlist.size() == 0)
261 pointlist.push_back(r);
262 else {
263 wxPoint l = pointlist.back();
264 // ensure the segment is at least 2 pixels
265 if ((abs(r.x - l.x) > 1) || (abs(r.y - l.y) > 1)) pointlist.push_back(r);
266 }
267}
268
269
Definition: ocpndc.h:55
Definition: track.h:43
Definition: Quilt.cpp:864