OpenCPN Partial API docs
Loading...
Searching...
No Matches
route_point_gui.cpp
1
2#include <wx/colour.h>
3#include <wx/gdicmn.h>
4#include <wx/pen.h>
5#include <wx/brush.h>
6
7#include "color_handler.h"
8#include "comm_n0183_output.h"
9#include "navutil.h"
10#include "routeman.h"
11#include "georef.h"
12#include "route_point_gui.h"
13#include "ocpn_frame.h"
14#include "FontMgr.h"
15#include "glChartCanvas.h"
16#include "viewport.h"
17#include "OCPNPlatform.h"
18#include "own_ship.h"
19#include "route.h"
20#include "waypointman_gui.h"
21#include "svg_utils.h"
22#include "styles.h"
23#include "ocpn_plugin.h"
24
25extern ocpnGLOptions g_GLOptions;
26extern float g_MarkScaleFactorExp;
27extern bool g_btouch;
28extern WayPointman* pWayPointMan;
29extern MyFrame* gFrame;
30extern wxRect g_blink_rect;
31extern OCPNPlatform* g_Platform;
32extern ocpnStyle::StyleManager* g_StyleManager;
33
34extern Routeman* g_pRouteMan;
35
36void RoutePointGui::Draw(ocpnDC& dc, ChartCanvas* canvas, wxPoint* rpn,
37 bool boverride_viz) {
38 wxPoint r;
39 wxRect hilitebox;
40
41 canvas->GetCanvasPointPix(m_point.m_lat, m_point.m_lon, &r);
42
43 // return the home point in this dc to allow "connect the dots"
44 if (NULL != rpn) *rpn = r;
45
46 if (!RoutePointGui(m_point).IsVisibleSelectable(canvas, boverride_viz)) return;
47
48 // If waypoint is well off screen, skip the drawing
49 if( (abs(r.x) > canvas->GetCanvasWidth() * 4 ) ||
50 (abs(r.y) > canvas->GetCanvasHeight() * 4))
51 return;
52
53 // If waypoint pixel location is invalid, skip the drawing
54 if ((abs(r.x) == INVALID_COORD ) ||
55 (abs(r.y) == INVALID_COORD) )
56 return;
57
58
59
60 // Optimization, especially apparent on tracks in normal cases
61 if (m_point.m_IconName == _T("empty") && !m_point.m_bShowName
62 && !m_point.m_bPtIsSelected){
63 return;
64 }
65
66 wxPen *pen;
67 if (m_point.m_bBlink)
68 pen = g_pRouteMan->GetActiveRoutePointPen();
69 else
70 pen = g_pRouteMan->GetRoutePointPen();
71
72 // Substitue icon?
73 if (m_point.m_IconIsDirty) ReLoadIcon();
74 wxBitmap *pbm;
75 if ((m_point.m_bIsActive) && (m_point.m_IconName != _T("mob")))
76 pbm = pWayPointMan->GetIconBitmap(_T ( "activepoint" ));
77 else
78 pbm = m_point.m_pbmIcon;
79
80 wxBitmap *pbms = NULL;
81 if ((g_MarkScaleFactorExp > 1.0) && !m_point.m_bPreScaled) {
82 if (m_point.m_IconScaleFactor != g_MarkScaleFactorExp) {
83 wxImage scaled_image = pbm->ConvertToImage();
84 int new_width = pbm->GetWidth() * g_MarkScaleFactorExp;
85 int new_height = pbm->GetHeight() * g_MarkScaleFactorExp;
86 m_point.m_ScaledBMP = wxBitmap(
87 scaled_image.Scale(new_width, new_height, wxIMAGE_QUALITY_HIGH));
88
89 m_point.m_IconScaleFactor = g_MarkScaleFactorExp;
90 }
91 if (m_point.m_ScaledBMP.IsOk()) pbm = &m_point.m_ScaledBMP;
92 }
93
94 int sx2 = pbm->GetWidth() / 2;
95 int sy2 = pbm->GetHeight() / 2;
96
97 // Calculate the mark drawing extents
98 wxRect r1(r.x - sx2, r.y - sy2, sx2 * 2, sy2 * 2); // the bitmap extents
99
100 if (m_point.m_bShowName) {
101 if (0 == m_point.m_pMarkFont) {
102 wxFont *dFont = FontMgr::Get().GetFont(_("Marks"));
103 int font_size = wxMax(8, dFont->GetPointSize());
104 font_size /= OCPN_GetWinDIPScaleFactor();
105
106 m_point.m_pMarkFont = FontMgr::Get().FindOrCreateFont(
107 font_size, dFont->GetFamily(), dFont->GetStyle(), dFont->GetWeight(),
108 false, dFont->GetFaceName());
109
110 m_point.m_FontColor = FontMgr::Get().GetFontColor(_("Marks"));
111 m_point.CalculateNameExtents();
112 }
113
114 if (m_point.m_pMarkFont) {
115 wxRect r2(r.x + m_point.m_NameLocationOffsetX, r.y + m_point.m_NameLocationOffsetY,
116 m_point.m_NameExtents.x, m_point.m_NameExtents.y);
117 r1.Union(r2);
118 }
119 }
120
121 hilitebox = r1;
122 hilitebox.x -= r.x;
123 hilitebox.y -= r.y;
124 float radius;
125 if (g_btouch) {
126 hilitebox.Inflate(20);
127 radius = 20.0f;
128 } else {
129 hilitebox.Inflate(4);
130 radius = 4.0f;
131 }
132
133 wxColour hi_colour = pen->GetColour();
134 unsigned char transparency = 100;
135 if (m_point.m_bRPIsBeingEdited) {
136 hi_colour = GetGlobalColor(_T ( "YELO1" ));
137 transparency = 150;
138 }
139
140 // Highlite any selected point
141 if (m_point.m_bPtIsSelected || m_point.m_bRPIsBeingEdited) {
142 AlphaBlending(dc, r.x + hilitebox.x, r.y + hilitebox.y, hilitebox.width,
143 hilitebox.height, radius, hi_colour, transparency);
144 }
145
146 bool bDrawHL = false;
147
148 if (m_point.m_bBlink && (gFrame->nBlinkerTick & 1)) bDrawHL = true;
149
150 if ((!bDrawHL) && (NULL != m_point.m_pbmIcon)) {
151 dc.DrawBitmap(*pbm, r.x - sx2, r.y - sy2, true);
152 // on MSW, the dc Bounding box is not updated on DrawBitmap() method.
153 // Do it explicitely here for all platforms.
154 dc.CalcBoundingBox(r.x - sx2, r.y - sy2);
155 dc.CalcBoundingBox(r.x + sx2, r.y + sy2);
156 }
157
158 if (m_point.m_bShowName && m_point.m_MarkName.Length()) {
159 if (m_point.m_pMarkFont) {
160 dc.SetFont(*m_point.m_pMarkFont);
161 dc.SetTextForeground(m_point.m_FontColor);
162
163 dc.DrawText(m_point.m_MarkName, r.x + m_point.m_NameLocationOffsetX,
164 r.y + m_point.m_NameLocationOffsetY);
165 }
166 }
167
168 // Draw waypoint radar rings if activated
169 if (m_point.m_iWaypointRangeRingsNumber && m_point.m_bShowWaypointRangeRings) {
170 double factor = 1.00;
171 if (m_point.m_iWaypointRangeRingsStepUnits == 1) // nautical miles
172 factor = 1 / 1.852;
173
174 factor *= m_point.m_fWaypointRangeRingsStep;
175
176 double tlat, tlon;
177 wxPoint r1;
178 ll_gc_ll(m_point.m_lat, m_point.m_lon, 0, factor, &tlat, &tlon);
179 canvas->GetCanvasPointPix(tlat, tlon, &r1);
180
181 double lpp =
182 sqrt(pow((double)(r.x - r1.x), 2) + pow((double)(r.y - r1.y), 2));
183 int pix_radius = (int)lpp;
184
185 wxPen ppPen1(m_point.m_wxcWaypointRangeRingsColour, 2);
186 wxBrush saveBrush = dc.GetBrush();
187 wxPen savePen = dc.GetPen();
188 dc.SetPen(ppPen1);
189 dc.SetBrush(
190 wxBrush(m_point.m_wxcWaypointRangeRingsColour, wxBRUSHSTYLE_TRANSPARENT));
191
192 for (int i = 1; i <= m_point.m_iWaypointRangeRingsNumber; i++)
193 dc.StrokeCircle(r.x, r.y, i * pix_radius);
194 dc.SetPen(savePen);
195 dc.SetBrush(saveBrush);
196 }
197
198 // Save the current draw rectangle in the current DC
199 // This will be useful for fast icon redraws
200 m_point.CurrentRect_in_DC.x = r.x + hilitebox.x;
201 m_point.CurrentRect_in_DC.y = r.y + hilitebox.y;
202 m_point.CurrentRect_in_DC.width = hilitebox.width;
203 m_point.CurrentRect_in_DC.height = hilitebox.height;
204
205 if (m_point.m_bBlink)
206 g_blink_rect = m_point.CurrentRect_in_DC; // also save for global blinker
207
208 delete pbms; // the potentially scaled bitmap
209}
210
211#ifdef ocpnUSE_GL
212void RoutePointGui::DrawGL(ViewPort &vp, ChartCanvas *canvas, ocpnDC &dc,
213 bool use_cached_screen_coords, bool bVizOverride) {
214 if (!RoutePointGui(m_point).IsVisibleSelectable(canvas, bVizOverride)) return;
215
216 // Optimization, especially apparent on tracks in normal cases
217 if (m_point.m_IconName == _T("empty") && !m_point.m_bShowName && !m_point.m_bPtIsSelected) return;
218
219 if (m_point.m_wpBBox.GetValid() && vp.view_scale_ppm == m_point.m_wpBBox_view_scale_ppm &&
220 vp.rotation == m_point.m_wpBBox_rotation) {
221 /* see if this waypoint can intersect with bounding box */
222 LLBBox vpBBox = vp.GetBBox();
223 if (vpBBox.IntersectOut(m_point.m_wpBBox)) {
224 // Are Range Rings enabled?
225 if (m_point.m_bShowWaypointRangeRings && (m_point.m_iWaypointRangeRingsNumber > 0)) {
226 double factor = 1.00;
227 if (m_point.m_iWaypointRangeRingsStepUnits == 1) // convert kilometers to NMi
228 factor = 1 / 1.852;
229
230 double radius = factor * m_point.m_iWaypointRangeRingsNumber *
231 m_point.m_fWaypointRangeRingsStep / 60.;
232
233 LLBBox radar_box = m_point.m_wpBBox;
234 radar_box.EnLarge(radius * 2);
235 if (vpBBox.IntersectOut(radar_box)) {
236 return;
237 }
238 } else
239 return;
240 }
241 }
242
243 wxPoint r;
244 wxRect hilitebox;
245 unsigned char transparency = 150;
246
247 if (use_cached_screen_coords && m_point.m_pos_on_screen)
248 r.x = m_point.m_screen_pos.m_x, r.y = m_point.m_screen_pos.m_y;
249 else
250 canvas->GetCanvasPointPix(m_point.m_lat, m_point.m_lon, &r);
251
252 if (r.x == INVALID_COORD) return;
253
254 // Substitute icon?
255 if (m_point.m_IconIsDirty) ReLoadIcon();
256 wxBitmap *pbm;
257 if ((m_point.m_bIsActive) && (m_point.m_IconName != _T("mob")))
258 pbm = pWayPointMan->GetIconBitmap(_T ( "activepoint" ));
259 else
260 pbm = m_point.m_pbmIcon;
261
262 // If icon is corrupt, there is really nothing else to do...
263 if (!pbm || !pbm->IsOk()) return;
264
265 int sx2 = pbm->GetWidth() / 2;
266 int sy2 = pbm->GetHeight() / 2;
267
268 // Calculate the mark drawing extents
269 wxRect r1(r.x - sx2, r.y - sy2, sx2 * 2, sy2 * 2); // the bitmap extents
270
271 wxRect r3 = r1;
272 if (m_point.m_bShowName) {
273 if (!m_point.m_pMarkFont) {
274 wxFont *dFont = FontMgr::Get().GetFont(_("Marks"));
275 int font_size = wxMax(8, dFont->GetPointSize());
276 font_size /= OCPN_GetWinDIPScaleFactor();
277
278 m_point.m_pMarkFont = FontMgr::Get().FindOrCreateFont(
279 font_size, dFont->GetFamily(), dFont->GetStyle(), dFont->GetWeight(),
280 false, dFont->GetFaceName());
281
282 m_point.m_FontColor = FontMgr::Get().GetFontColor(_("Marks"));
283 if (m_point.m_iTextTexture) {
284 glDeleteTextures(1, &m_point.m_iTextTexture);
285 m_point.m_iTextTexture = 0;
286 }
287
288 m_point.CalculateNameExtents();
289 }
290
291 if (m_point.m_pMarkFont) {
292 wxRect r2(r.x + m_point.m_NameLocationOffsetX, r.y + m_point.m_NameLocationOffsetY,
293 m_point.m_NameExtents.x, m_point.m_NameExtents.y);
294 r3.Union(r2);
295 }
296 }
297
298 hilitebox = r3;
299 hilitebox.x -= r.x;
300 hilitebox.y -= r.y;
301
302 if (!m_point.m_bPreScaled) {
303 hilitebox.x *= g_MarkScaleFactorExp;
304 hilitebox.y *= g_MarkScaleFactorExp;
305 hilitebox.width *= g_MarkScaleFactorExp;
306 hilitebox.height *= g_MarkScaleFactorExp;
307 }
308
309 float radius;
310 if (g_btouch) {
311 hilitebox.Inflate(20);
312 radius = 20.0f;
313 } else {
314 hilitebox.Inflate(4);
315 radius = 4.0f;
316 }
317
318 /* update bounding box */
319 if (!m_point.m_wpBBox.GetValid() || vp.view_scale_ppm != m_point.m_wpBBox_view_scale_ppm ||
320 vp.rotation != m_point.m_wpBBox_rotation) {
321 double lat1, lon1, lat2, lon2;
322 canvas->GetCanvasPixPoint(r.x + hilitebox.x,
323 r.y + hilitebox.y + hilitebox.height, lat1, lon1);
324 canvas->GetCanvasPixPoint(r.x + hilitebox.x + hilitebox.width,
325 r.y + hilitebox.y, lat2, lon2);
326
327 if (lon1 > lon2)
328 m_point.m_wpBBox.Set(lat1, lon1, lat2, lon2 + 360);
329 else
330 m_point.m_wpBBox.Set(lat1, lon1, lat2, lon2);
331
332 m_point.m_wpBBox_view_scale_ppm = vp.view_scale_ppm;
333 m_point.m_wpBBox_rotation = vp.rotation;
334 }
335
336 // if(region.Contains(r3) == wxOutRegion)
337 // return;
338
339 //ocpnDC dc;
340
341 // Highlite any selected point
342 if (m_point.m_bPtIsSelected) {
343 wxColour hi_colour;
344 if (m_point.m_bBlink) {
345 wxPen *pen = g_pRouteMan->GetActiveRoutePointPen();
346 hi_colour = pen->GetColour();
347 } else {
348 hi_colour = GetGlobalColor(_T ( "YELO1" ));
349 }
350
351 AlphaBlending(dc, r.x + hilitebox.x, r.y + hilitebox.y, hilitebox.width,
352 hilitebox.height, radius, hi_colour, transparency);
353 }
354
355 bool bDrawHL = false;
356
357 if (m_point.m_bBlink && (gFrame->nBlinkerTick & 1)) bDrawHL = true;
358
359 if ((!bDrawHL) && (NULL != m_point.m_pbmIcon)) {
360 int glw, glh;
361 unsigned int IconTexture = pWayPointMan->GetIconTexture(pbm, glw, glh);
362
363 glBindTexture(GL_TEXTURE_2D, IconTexture);
364
365 glEnable(GL_TEXTURE_2D);
366 glEnable(GL_BLEND);
367
368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
370
371 int w = r1.width, h = r1.height;
372
373 float scale = 1.0;
374 if (!m_point.m_bPreScaled) {
375 scale = g_MarkScaleFactorExp;
376 }
377
378 float ws = r1.width * scale;
379 float hs = r1.height * scale;
380 float xs = r.x - ws / 2.;
381 float ys = r.y - hs / 2.;
382 float u = (float)w / glw, v = (float)h / glh;
383
384 float coords[8];
385 float uv[8];
386 // normal uv
387 uv[0] = 0;
388 uv[1] = 0;
389 uv[2] = u;
390 uv[3] = 0;
391 uv[4] = u;
392 uv[5] = v;
393 uv[6] = 0;
394 uv[7] = v;
395
396 // pixels
397 coords[0] = xs;
398 coords[1] = ys;
399 coords[2] = xs + ws;
400 coords[3] = ys;
401 coords[4] = xs + ws;
402 coords[5] = ys + hs;
403 coords[6] = xs, coords[7] = ys + hs;
404
405 glChartCanvas::RenderSingleTexture(dc, coords, uv, &vp, 0, 0, 0);
406
407 glDisable(GL_BLEND);
408 glDisable(GL_TEXTURE_2D);
409 }
410
411 if (m_point.m_bShowName && m_point.m_pMarkFont) {
412 int w = m_point.m_NameExtents.x, h = m_point.m_NameExtents.y;
413 if (!m_point.m_iTextTexture && w && h) {
414#if 0
415 wxBitmap tbm(w, h); /* render text on dc */
416 wxMemoryDC dc;
417 dc.SelectObject(tbm);
418 dc.SetBackground(wxBrush(*wxBLACK));
419 dc.Clear();
420 dc.SetFont(*m_pMarkFont);
421 dc.SetTextForeground(*wxWHITE);
422 dc.DrawText(m_MarkName, 0, 0);
423 dc.SelectObject(wxNullBitmap);
424
425 /* make alpha texture for text */
426 wxImage image = tbm.ConvertToImage();
427 unsigned char *d = image.GetData();
428 unsigned char *e = new unsigned char[w * h];
429 if (d && e) {
430 for (int p = 0; p < w * h; p++) e[p] = d[3 * p + 0];
431 }
432
433 /* create texture for rendered text */
434 glGenTextures(1, &m_iTextTexture);
435 glBindTexture(GL_TEXTURE_2D, m_iTextTexture);
436
437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
438 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
439
440 m_iTextTextureWidth = NextPow2(w);
441 m_iTextTextureHeight = NextPow2(h);
442 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_iTextTextureWidth,
443 m_iTextTextureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
444 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_ALPHA, GL_UNSIGNED_BYTE,
445 e);
446 delete[] e;
447#else
448 wxScreenDC sdc;
449 sdc.SetFont(*m_point.m_pMarkFont);
450 sdc.GetTextExtent(m_point.m_MarkName, &w, &h, NULL, NULL, m_point.m_pMarkFont);
451
452 /* create bitmap of appropriate size and select it */
453 wxBitmap bmp(w, h);
454 wxMemoryDC temp_dc;
455 temp_dc.SelectObject(bmp);
456
457 /* fill bitmap with black */
458 temp_dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
459 temp_dc.Clear();
460
461 /* draw the text white */
462 temp_dc.SetFont(*m_point.m_pMarkFont);
463 temp_dc.SetTextForeground(wxColour(255, 255, 255));
464 temp_dc.DrawText(m_point.m_MarkName, 0, 0);
465 temp_dc.SelectObject(wxNullBitmap);
466
467 /* use the data in the bitmap for alpha channel,
468 and set the color to text foreground */
469 wxImage image = bmp.ConvertToImage();
470
471 unsigned char *data = new unsigned char[w * h * 4];
472 unsigned char *im = image.GetData();
473
474 if (im) {
475 unsigned int r = m_point.m_FontColor.Red();
476 unsigned int g = m_point.m_FontColor.Green();
477 unsigned int b = m_point.m_FontColor.Blue();
478 for (int i = 0; i < h; i++) {
479 for (int j = 0; j < w; j++) {
480 unsigned int index = ((i * w) + j) * 4;
481 data[index] = r;
482 data[index + 1] = g;
483 data[index + 2] = b;
484 data[index + 3] = im[((i * w) + j) * 3];
485 }
486 }
487 }
488
489 glGenTextures(1, &m_point.m_iTextTexture);
490
491 glBindTexture(GL_TEXTURE_2D, m_point.m_iTextTexture);
492
493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
494 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
495
496 m_point.m_iTextTextureWidth = NextPow2(w);
497 m_point.m_iTextTextureHeight = NextPow2(h);
498 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_point.m_iTextTextureWidth,
499 m_point.m_iTextTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
500 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
501 data);
502
503 glEnable(GL_TEXTURE_2D);
504 glEnable(GL_BLEND);
505 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
506
507#endif
508 }
509
510 if (m_point.m_iTextTexture) {
511 /* draw texture with text */
512 glBindTexture(GL_TEXTURE_2D, m_point.m_iTextTexture);
513
514 glEnable(GL_TEXTURE_2D);
515 glEnable(GL_BLEND);
516
517 int x = r.x + m_point.m_NameLocationOffsetX, y = r.y + m_point.m_NameLocationOffsetY;
518 float u = (float)w / m_point.m_iTextTextureWidth,
519 v = (float)h / m_point.m_iTextTextureHeight;
520 float coords[8];
521 float uv[8];
522 // normal uv
523 uv[0] = 0;
524 uv[1] = 0;
525 uv[2] = u;
526 uv[3] = 0;
527 uv[4] = u;
528 uv[5] = v;
529 uv[6] = 0;
530 uv[7] = v;
531
532 // pixels
533 coords[0] = x;
534 coords[1] = y;
535 coords[2] = x + w;
536 coords[3] = y;
537 coords[4] = x + w;
538 coords[5] = y + h;
539 coords[6] = x, coords[7] = y + h;
540
541 glChartCanvas::RenderSingleTexture(dc, coords, uv, &vp, 0, 0, 0);
542
543 glDisable(GL_BLEND);
544 glDisable(GL_TEXTURE_2D);
545 }
546 }
547
548 // Draw waypoint radar rings if activated
549 if (m_point.m_iWaypointRangeRingsNumber && m_point.m_bShowWaypointRangeRings) {
550 double factor = 1.00;
551 if (m_point.m_iWaypointRangeRingsStepUnits == 1) // nautical miles
552 factor = 1 / 1.852;
553
554 factor *= m_point.m_fWaypointRangeRingsStep;
555
556 double tlat, tlon;
557 wxPoint r1;
558 ll_gc_ll(m_point.m_lat, m_point.m_lon, 0, factor, &tlat, &tlon);
559 canvas->GetCanvasPointPix(tlat, tlon, &r1);
560
561 double lpp =
562 sqrt(pow((double)(r.x - r1.x), 2) + pow((double)(r.y - r1.y), 2));
563 int pix_radius = (int)lpp;
564
565 extern wxColor GetDimColor(wxColor c);
566 wxColor ring_dim_color = GetDimColor(m_point.m_wxcWaypointRangeRingsColour);
567
568 // 0.5 mm nominal, but not less than 1 pixel
569 double platform_pen_width = wxRound(
570 wxMax(1.0, g_Platform->GetDisplayDPmm() / 2));
571 wxPen ppPen1(ring_dim_color, platform_pen_width);
572 wxBrush saveBrush = dc.GetBrush();
573 wxPen savePen = dc.GetPen();
574 dc.SetPen(ppPen1);
575 dc.SetBrush(wxBrush(ring_dim_color, wxBRUSHSTYLE_TRANSPARENT));
576
577 for (int i = 1; i <= m_point.m_iWaypointRangeRingsNumber; i++)
578 dc.StrokeCircle(r.x, r.y, i * pix_radius);
579 dc.SetPen(savePen);
580 dc.SetBrush(saveBrush);
581 }
582
583 // Render Drag handle if enabled
584 if (m_point.m_bDrawDragHandle) {
585 // A line, southeast, scaled to the size of the icon
586 double platform_pen_width = wxRound(
587 wxMax(1.0, g_Platform->GetDisplayDPmm() /
588 2)); // 0.5 mm nominal, but not less than 1 pixel
589
590 wxColor dh_color = GetGlobalColor(_T ( "YELO1" ));
591 wxPen ppPen1(dh_color, 3 * platform_pen_width);
592 dc.SetPen(ppPen1);
593 dc.DrawLine(r.x + hilitebox.width / 4, r.y + hilitebox.height / 4,
594 r.x + m_point.m_drag_line_length_man, r.y + m_point.m_drag_line_length_man);
595
596 dh_color = wxColor(0, 0, 0);
597 wxPen ppPen2(dh_color, platform_pen_width);
598 dc.SetPen(ppPen2);
599 dc.DrawLine(r.x + hilitebox.width / 4, r.y + hilitebox.height / 4,
600 r.x + m_point.m_drag_line_length_man, r.y + m_point.m_drag_line_length_man);
601
602 // The drag handle
603 glBindTexture(GL_TEXTURE_2D, m_point.m_dragIconTexture);
604
605 glEnable(GL_TEXTURE_2D);
606 glEnable(GL_BLEND);
607
608 int x = r.x + m_point.m_drag_icon_offset, y = r.y + m_point.m_drag_icon_offset,
609 w = m_point.m_dragIcon.GetWidth(), h = m_point.m_dragIcon.GetHeight();
610
611 float scale = 1.0;
612
613 float ws = w * scale;
614 float hs = h * scale;
615 float xs = x - ws / 2.;
616 float ys = y - hs / 2.;
617 float u = (float)w / m_point.m_dragIconTextureWidth,
618 v = (float)h / m_point.m_dragIconTextureWidth;
619
620 float coords[8];
621 float uv[8];
622 // normal uv
623 uv[0] = 0;
624 uv[1] = 0;
625 uv[2] = u;
626 uv[3] = 0;
627 uv[4] = u;
628 uv[5] = v;
629 uv[6] = 0;
630 uv[7] = v;
631
632 // pixels
633 coords[0] = xs;
634 coords[1] = ys;
635 coords[2] = xs + ws;
636 coords[3] = ys;
637 coords[4] = xs + ws;
638 coords[5] = ys + hs;
639 coords[6] = xs, coords[7] = ys + hs;
640
641 glChartCanvas::RenderSingleTexture(dc, coords, uv, &vp, 0, 0, 0);
642
643 glDisable(GL_BLEND);
644 glDisable(GL_TEXTURE_2D);
645 }
646
647 if (m_point.m_bBlink)
648 g_blink_rect =m_point. CurrentRect_in_DC; // also save for global blinker
649
650 // This will be useful for fast icon redraws
651 m_point.CurrentRect_in_DC.x = r.x + hilitebox.x;
652 m_point.CurrentRect_in_DC.y = r.y + hilitebox.y;
653 m_point.CurrentRect_in_DC.width = hilitebox.width;
654 m_point.CurrentRect_in_DC.height = hilitebox.height;
655
656 if (m_point.m_bBlink)
657 g_blink_rect = m_point.CurrentRect_in_DC; // also save for global blinker
658}
659#endif
660
661void RoutePointGui::CalculateDCRect(wxDC &dc, ChartCanvas *canvas, wxRect *prect) {
662 dc.ResetBoundingBox();
663 dc.DestroyClippingRegion();
664
665 // Draw the mark on the dc
666 ocpnDC odc(dc);
667 Draw(odc, canvas, NULL);
668
669 // Retrieve the drawing extents
670 prect->x = dc.MinX() - 1;
671 prect->y = dc.MinY() - 1;
672 prect->width = dc.MaxX() - dc.MinX() + 2; // Mouse Poop?
673 prect->height = dc.MaxY() - dc.MinY() + 2;
674}
675
676bool RoutePointGui::IsVisibleSelectable(ChartCanvas* cc, bool boverrideViz) {
677 return m_point.IsVisibleSelectable(cc->GetScaleValue(), boverrideViz);
678}
679
680wxPoint2DDouble RoutePointGui::GetDragHandlePoint(ChartCanvas *canvas) {
681 if (!m_point.m_bDrawDragHandle)
682 return wxPoint2DDouble(m_point.m_lon, m_point.m_lat);
683 else {
684 return computeDragHandlePoint(canvas);
685 }
686}
687void RoutePointGui::SetPointFromDraghandlePoint(ChartCanvas *canvas, double lat,
688 double lon) {
689 wxPoint r;
690 canvas->GetCanvasPointPix(lat, lon, &r);
691 double tlat, tlon;
692 canvas->GetCanvasPixPoint(r.x - m_point.m_drag_icon_offset, r.y - m_point.m_drag_icon_offset,
693 tlat, tlon);
694 m_point.m_lat = tlat;
695 m_point.m_lon = tlon;
696}
697
698void RoutePointGui::SetPointFromDraghandlePoint(ChartCanvas *canvas, int x,
699 int y) {
700 double tlat, tlon;
701 canvas->GetCanvasPixPoint(x - m_point.m_drag_icon_offset - m_point.m_draggingOffsetx,
702 y - m_point.m_drag_icon_offset - m_point.m_draggingOffsety, tlat,
703 tlon);
704 m_point.m_lat = tlat;
705 m_point.m_lon = tlon;
706}
707
708void RoutePointGui::PresetDragOffset(ChartCanvas *canvas, int x, int y) {
709 wxPoint r;
710 canvas->GetCanvasPointPix(m_point.m_lat, m_point.m_lon, &r);
711
712 m_point.m_draggingOffsetx = x - (r.x + m_point.m_drag_icon_offset);
713 m_point.m_draggingOffsety = y - (r.y + m_point.m_drag_icon_offset);
714}
715
716wxPoint2DDouble RoutePointGui::computeDragHandlePoint(ChartCanvas *canvas) {
717 wxPoint r;
718 canvas->GetCanvasPointPix(m_point.m_lat, m_point.m_lon, &r);
719 double lat, lon;
720 canvas->GetCanvasPixPoint(r.x + m_point.m_drag_icon_offset, r.y + m_point.m_drag_icon_offset,
721 lat, lon);
722
723 // Keep the members updated
724 m_point.m_dragHandleLat = lat;
725 m_point.m_dragHandleLon = lon;
726
727 return wxPoint2DDouble(lon, lat);
728}
729
730void RoutePointGui::ShowScaleWarningMessage(ChartCanvas *canvas) {
731 wxString strA = _("The ScaMin value for new waypoints is set to");
732 wxString strB = _("but current chartscale is");
733 wxString strC =
734 _("Therefore the new waypoint will not be visible at this zoom level.");
735 wxString MessStr =
736 wxString::Format(_T("%s %li,\n %s %.0f.\n%s"), strA, m_point.GetScaMin(), strB,
737 canvas->GetScaleValue(), strC);
738 OCPNMessageBox(canvas, MessStr);
739}
740
741void RoutePointGui::EnableDragHandle(bool bEnable) {
742 m_point.m_bDrawDragHandle = bEnable;
743 if (bEnable) {
744 if (!m_point.m_dragIcon.IsOk()) {
745 // Get the icon
746 // What size?
747 int bm_size = g_Platform->GetDisplayDPmm() * 9; // 9 mm nominal
748
749 // What icon?
750 wxString UserIconPath = g_Platform->GetSharedDataDir()
751 + _T("uidata") + wxFileName::GetPathSeparator();
752
753 m_point.m_dragIcon = LoadSVG(UserIconPath + _T("DragHandle.svg"), bm_size,
754 bm_size, m_point.m_pbmIcon);
755
756 // build a texture
757#ifdef ocpnUSE_GL
758 /* make rgba texture */
759 if (m_point.m_dragIconTexture == 0) {
760 glGenTextures(1, &m_point.m_dragIconTexture);
761 glBindTexture(GL_TEXTURE_2D, m_point.m_dragIconTexture);
762
763 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
764 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
765 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
766
767 wxImage image = m_point.m_dragIcon.ConvertToImage();
768 int w = image.GetWidth(), h = image.GetHeight();
769
770 m_point.m_dragIconTextureWidth = NextPow2(w);
771 m_point.m_dragIconTextureHeight = NextPow2(h);
772
773 unsigned char *d = image.GetData();
774 unsigned char *a = image.GetAlpha();
775
776 unsigned char mr, mg, mb;
777 image.GetOrFindMaskColour(&mr, &mg, &mb);
778
779 unsigned char *e = new unsigned char[4 * w * h];
780 if (d && e) {
781 for (int y = 0; y < h; y++)
782 for (int x = 0; x < w; x++) {
783 unsigned char r, g, b;
784 int off = (y * image.GetWidth() + x);
785 r = d[off * 3 + 0];
786 g = d[off * 3 + 1];
787 b = d[off * 3 + 2];
788 e[off * 4 + 0] = r;
789 e[off * 4 + 1] = g;
790 e[off * 4 + 2] = b;
791
792 e[off * 4 + 3] =
793 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
794 }
795 }
796
797 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_point.m_dragIconTextureWidth,
798 m_point.m_dragIconTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
799 NULL);
800 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
801 e);
802
803 delete[] e;
804 }
805#endif
806
807 // set the drawing metrics
808 if (m_point.m_dragIcon.IsOk()) {
809 m_point.m_drag_line_length_man = bm_size;
810 m_point.m_drag_icon_offset = bm_size;
811 } else {
812 m_point.m_drag_line_length_man = 64;
813 m_point.m_drag_icon_offset = 64;
814 }
815 }
816 }
817}
818
819void RoutePointGui::ReLoadIcon(void) {
820 if (!pWayPointMan) return;
821 bool icon_exists = pWayPointMan->DoesIconExist(m_point.m_IconName);
822
823 wxString iconUse = m_point.m_IconName;
824 if (!icon_exists) {
825 // Try all lower case as a favor in the case where imported waypoints use
826 // mixed case names
827 wxString tentative_icon = m_point.m_IconName.Lower();
828 if (pWayPointMan->DoesIconExist(tentative_icon)) {
829 // if found, convert point's icon name permanently.
830 m_point.m_IconName = tentative_icon;
831 iconUse = m_point.m_IconName;
832 }
833 // Icon name is not in the standard or user lists, so add to the list a
834 // generic placeholder
835 else {
836 if (!pWayPointMan->DoesIconExist(_T("tempsub"))) {
837 ocpnStyle::Style *style = g_StyleManager->GetCurrentStyle();
838 if (style) {
839 wxBitmap bmp = style->GetIcon(_T("circle"));
840 if (bmp.IsOk())
841 WayPointmanGui(*pWayPointMan).ProcessIcon(bmp, "tempsub",
842 "tempsub");
843 }
844 }
845 iconUse = _T("tempsub");
846 }
847 }
848
849 m_point.m_pbmIcon = pWayPointMan->GetIconBitmap(iconUse);
850 m_point.m_bPreScaled = pWayPointMan->GetIconPrescaled(iconUse);
851
852#ifdef ocpnUSE_GL
853 m_point.m_wpBBox_view_scale_ppm = -1;
854
855 m_point.m_iTextTexture = 0;
856#endif
857
858 m_point.m_IconScaleFactor = -1; // Force scaled icon reload
859 m_point.m_pMarkFont = 0; // Force Font color reload
860 m_point.m_IconIsDirty = false;
861}
862
863bool RoutePointGui::SendToGPS(const wxString &com_name, SendToGpsDlg *dialog) {
864 int result = SendWaypointToGPS_N0183(&m_point, com_name);
865
866 wxString msg;
867 if (0 == result)
868 msg = _("Waypoint(s) Transmitted.");
869 else {
870 if (result == ERR_GARMIN_INITIALIZE)
871 msg = _("Error on Waypoint Upload. Garmin GPS not connected");
872 else
873 msg = _("Error on Waypoint Upload. Please check logfiles...");
874 }
875
876 OCPNMessageBox(NULL, msg, _("OpenCPN Info"), wxOK | wxICON_INFORMATION);
877
878 return (result == 0);
879}
880
881int RoutePointGui::GetIconImageIndex() {
882 if (m_point.IsShared()) {
883 // Get an array of all routes using this point
884 wxArrayPtrVoid *proute_array = g_pRouteMan->GetRouteArrayContaining(&m_point);
885
886 // Use route array (if any) to determine actual visibility for this point
887 bool brp_viz = false;
888 if (proute_array) {
889 for (unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
890 Route *pr = (Route *)proute_array->Item(ir);
891 if (pr->IsVisible()) {
892 brp_viz = true;
893 break;
894 }
895 }
896 }
897
898 if (brp_viz)
899 return (pWayPointMan->GetFIconImageListIndex(GetIconBitmap()));
900 else {
901 if (m_point.IsVisible())
902 return (pWayPointMan->GetIconImageListIndex(GetIconBitmap()));
903 else
904 return (pWayPointMan->GetXIconImageListIndex(GetIconBitmap()));
905 }
906 }
907
908 else { // point is not shared
909 if (m_point.IsVisible())
910 return (pWayPointMan->GetIconImageListIndex(GetIconBitmap()));
911 else
912 return (pWayPointMan->GetXIconImageListIndex(GetIconBitmap()));
913 }
914}
915
916
Definition: route.h:70
Route "Send to GPS..." Dialog Definition.
Definition: SendToGpsDlg.h:56
Definition: ocpndc.h:55
Definition: Quilt.cpp:864