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