26#include <wx/dcscreen.h>
27#include <wx/tokenzr.h>
31#include "RoutePoint.h"
32#include "multiplexer.h"
37#include "wx28compat.h"
38#include "OCPNPlatform.h"
39#include "glChartCanvas.h"
45extern bool g_bIsNewLayer;
48extern wxRect g_blink_rect;
53extern double g_n_arrival_circle_radius;
54extern int g_iWaypointRangeRingsNumber;
55extern float g_fWaypointRangeRingsStep;
56extern int g_iWaypointRangeRingsStepUnits;
57extern wxColour g_colourWaypointRangeRingsColour;
59extern float g_ChartScaleFactorExp;
60extern int g_iWpt_ScaMin;
61extern bool g_bUseWptScaMin;
62extern bool g_bOverruleScaMin;
64extern wxImage LoadSVGIcon(wxString filename,
int width,
int height);
66#include <wx/listimpl.cpp>
67WX_DEFINE_LIST(RoutePointList);
69RoutePoint::RoutePoint() {
76 m_seg_etd = wxInvalidDateTime;
79 m_seg_eta = wxInvalidDateTime;
80 m_bDynamicName =
false;
81 m_bPtIsSelected =
false;
82 m_bRPIsBeingEdited =
false;
86 m_CreateTimeX = wxDateTime::Now();
87 m_bIsolatedMark =
false;
92 CurrentRect_in_DC = wxRect(0, 0, 0, 0);
93 m_NameLocationOffsetX = -10;
94 m_NameLocationOffsetY = 8;
102 m_HyperlinkList =
new HyperlinkList;
104 m_GUID = pWayPointMan->CreateGUID(
this);
106 m_IconName = wxEmptyString;
109 m_MarkName = wxEmptyString;
111 m_bIsInLayer =
false;
114 m_WaypointArrivalRadius = g_n_arrival_circle_radius;
116 m_bShowWaypointRangeRings = (bool)g_iWaypointRangeRingsNumber;
118 m_iWaypointRangeRingsNumber = g_iWaypointRangeRingsNumber;
119 m_fWaypointRangeRingsStep = g_fWaypointRangeRingsStep;
120 m_iWaypointRangeRingsStepUnits = g_iWaypointRangeRingsStepUnits;
121 m_wxcWaypointRangeRingsColour = g_colourWaypointRangeRingsColour;
122 m_ScaMin = g_iWpt_ScaMin;
124 b_UseScamin = g_bUseWptScaMin;
127 m_pos_on_screen =
false;
129 m_bDrawDragHandle =
false;
130 m_dragIconTexture = 0;
131 m_draggingOffsetx = m_draggingOffsety = 0;
138 m_MarkName = orig->GetName();
141 m_seg_len = orig->m_seg_len;
142 m_seg_vmg = orig->m_seg_vmg;
144 m_seg_etd = orig->m_seg_etd;
145 m_manual_etd =
false;
147 m_bDynamicName = orig->m_bDynamicName;
148 m_bPtIsSelected = orig->m_bPtIsSelected;
149 m_bRPIsBeingEdited = orig->m_bRPIsBeingEdited;
150 m_bIsActive = orig->m_bIsActive;
151 m_bBlink = orig->m_bBlink;
152 m_bIsInRoute = orig->m_bIsInRoute;
153 m_CreateTimeX = orig->m_CreateTimeX;
154 m_bIsolatedMark = orig->m_bIsolatedMark;
155 m_bShowName = orig->m_bShowName;
156 SetShared(orig->IsShared());
157 m_bIsVisible = orig->m_bIsVisible;
158 m_bIsListed = orig->m_bIsListed;
159 CurrentRect_in_DC = orig->CurrentRect_in_DC;
160 m_NameLocationOffsetX = orig->m_NameLocationOffsetX;
161 m_NameLocationOffsetY = orig->m_NameLocationOffsetY;
162 m_pMarkFont = orig->m_pMarkFont;
163 m_MarkDescription = orig->m_MarkDescription;
164 m_btemp = orig->m_btemp;
165 m_ScaMin = orig->m_ScaMin;
166 m_ScaMax = orig->m_ScaMax;
167 m_HyperlinkList =
new HyperlinkList;
168 m_IconName = orig->m_IconName;
169 m_TideStation = orig->m_TideStation;
170 SetPlannedSpeed(orig->GetPlannedSpeed());
173 m_bIsInLayer = orig->m_bIsInLayer;
174 m_GUID = pWayPointMan->CreateGUID(
this);
177 m_ManagerNode = NULL;
179 m_WaypointArrivalRadius = orig->GetWaypointArrivalRadius();
180 m_bShowWaypointRangeRings = orig->m_bShowWaypointRangeRings;
181 m_iWaypointRangeRingsNumber = orig->m_iWaypointRangeRingsNumber;
182 m_fWaypointRangeRingsStep = orig->m_fWaypointRangeRingsStep;
183 m_iWaypointRangeRingsStepUnits = orig->m_iWaypointRangeRingsStepUnits;
184 m_wxcWaypointRangeRingsColour = orig->m_wxcWaypointRangeRingsColour;
185 m_ScaMin = orig->m_ScaMin;
186 m_ScaMax = orig->m_ScaMax;
187 b_UseScamin = orig->b_UseScamin;
189 m_bDrawDragHandle =
false;
190 m_dragIconTexture = 0;
191 m_draggingOffsetx = m_draggingOffsety = 0;
194RoutePoint::RoutePoint(
double lat,
double lon,
const wxString &icon_ident,
195 const wxString &name,
const wxString &pGUID,
204 else if (m_lon > 180.)
211 m_seg_etd = wxInvalidDateTime;
212 m_manual_etd =
false;
214 m_bDynamicName =
false;
215 m_bPtIsSelected =
false;
216 m_bRPIsBeingEdited =
false;
219 m_bIsInRoute =
false;
220 m_CreateTimeX = wxDateTime::Now();
221 m_bIsolatedMark =
false;
226 CurrentRect_in_DC = wxRect(0, 0, 0, 0);
227 m_NameLocationOffsetX = -10;
228 m_NameLocationOffsetY = 8;
231 m_bPreScaled =
false;
234 m_ManagerNode = NULL;
235 m_IconScaleFactor = 1.0;
236 m_ScaMin = MAX_INT_VAL;
238 m_HyperlinkList =
new HyperlinkList;
240 if (!pGUID.IsEmpty())
243 m_GUID = pWayPointMan->CreateGUID(
this);
246 m_IconName = icon_ident;
254 if (bAddToList && NULL != pWayPointMan) pWayPointMan->AddRoutePoint(
this);
256 m_bIsInLayer = g_bIsNewLayer;
258 m_LayerID = g_LayerIdx;
263 SetWaypointArrivalRadius(g_n_arrival_circle_radius);
265 m_bShowWaypointRangeRings = (bool)g_iWaypointRangeRingsNumber;
267 m_iWaypointRangeRingsNumber = g_iWaypointRangeRingsNumber;
268 m_fWaypointRangeRingsStep = g_fWaypointRangeRingsStep;
269 m_iWaypointRangeRingsStepUnits = g_iWaypointRangeRingsStepUnits;
270 m_wxcWaypointRangeRingsColour = g_colourWaypointRangeRingsColour;
271 m_ScaMin = g_iWpt_ScaMin;
273 b_UseScamin = g_bUseWptScaMin;
275 m_bDrawDragHandle =
false;
276 m_dragIconTexture = 0;
277 m_draggingOffsetx = m_draggingOffsety = 0;
282RoutePoint::~RoutePoint() {
284 if (NULL != pWayPointMan) pWayPointMan->RemoveRoutePoint(
this);
286 if (m_HyperlinkList) {
287 m_HyperlinkList->DeleteContents(
true);
288 delete m_HyperlinkList;
291 if (m_dragIconTexture > 0) glDeleteTextures(1, &m_dragIconTexture);
295wxPoint2DDouble RoutePoint::GetDragHandlePoint(
ChartCanvas *canvas) {
296 if (!m_bDrawDragHandle)
297 return wxPoint2DDouble(m_lon, m_lat);
299 return computeDragHandlePoint(canvas);
303wxPoint2DDouble RoutePoint::computeDragHandlePoint(
ChartCanvas *canvas) {
305 canvas->GetCanvasPointPix(m_lat, m_lon, &r);
307 canvas->GetCanvasPixPoint(r.x + m_drag_icon_offset, r.y + m_drag_icon_offset,
311 m_dragHandleLat = lat;
312 m_dragHandleLon = lon;
314 return wxPoint2DDouble(lon, lat);
317void RoutePoint::SetPointFromDraghandlePoint(
ChartCanvas *canvas,
double lat,
320 canvas->GetCanvasPointPix(lat, lon, &r);
322 canvas->GetCanvasPixPoint(r.x - m_drag_icon_offset, r.y - m_drag_icon_offset,
328void RoutePoint::SetPointFromDraghandlePoint(
ChartCanvas *canvas,
int x,
331 canvas->GetCanvasPixPoint(x - m_drag_icon_offset - m_draggingOffsetx,
332 y - m_drag_icon_offset - m_draggingOffsety, tlat,
338void RoutePoint::PresetDragOffset(
ChartCanvas *canvas,
int x,
int y) {
340 canvas->GetCanvasPointPix(m_lat, m_lon, &r);
342 m_draggingOffsetx = x - (r.x + m_drag_icon_offset);
343 m_draggingOffsety = y - (r.y + m_drag_icon_offset);
346void RoutePoint::EnableDragHandle(
bool bEnable) {
347 m_bDrawDragHandle = bEnable;
349 if (!m_dragIcon.IsOk()) {
352 int bm_size = g_Platform->GetDisplayDPmm() * 9;
355 wxString UserIconPath = g_Platform->GetSharedDataDir() + _T(
"uidata") +
356 wxFileName::GetPathSeparator();
359 LoadSVGIcon(UserIconPath + _T(
"DragHandle.svg"), bm_size, bm_size);
361 m_dragIcon = wxBitmap(iconSVG);
363 m_dragIcon = *m_pbmIcon;
368 if (m_dragIconTexture == 0) {
369 glGenTextures(1, &m_dragIconTexture);
370 glBindTexture(GL_TEXTURE_2D, m_dragIconTexture);
372 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
376 wxImage image = iconSVG;
377 int w = image.GetWidth(), h = image.GetHeight();
379 m_dragIconTextureWidth = NextPow2(w);
380 m_dragIconTextureHeight = NextPow2(h);
382 unsigned char *d = image.GetData();
383 unsigned char *a = image.GetAlpha();
385 unsigned char mr, mg, mb;
386 image.GetOrFindMaskColour(&mr, &mg, &mb);
388 unsigned char *e =
new unsigned char[4 * w * h];
390 for (
int y = 0; y < h; y++)
391 for (
int x = 0; x < w; x++) {
392 unsigned char r, g, b;
393 int off = (y * image.GetWidth() + x);
402 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
406 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_dragIconTextureWidth,
407 m_dragIconTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
409 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
417 if (iconSVG.IsOk()) {
418 m_drag_line_length_man = bm_size;
419 m_drag_icon_offset = bm_size;
421 m_drag_line_length_man = 64;
422 m_drag_icon_offset = 64;
428wxDateTime RoutePoint::GetCreateTime() {
429 if (!m_CreateTimeX.IsValid()) {
430 if (m_timestring.Len()) ParseGPXDateTime(m_CreateTimeX, m_timestring);
432 return m_CreateTimeX;
435void RoutePoint::SetCreateTime(wxDateTime dt) { m_CreateTimeX = dt; }
437void RoutePoint::SetName(
const wxString &name) {
439 if (m_iTextTexture) {
440 glDeleteTextures(1, &m_iTextTexture);
445 CalculateNameExtents();
448void RoutePoint::CalculateNameExtents(
void) {
454 dc.GetTextExtent(m_MarkName, &w, &h, NULL, NULL, m_pMarkFont);
455 m_NameExtents = wxSize(w, h);
457 dc.SetFont(*m_pMarkFont);
458 m_NameExtents = dc.GetMultiLineTextExtent(m_MarkName);
461 m_NameExtents = wxSize(0, 0);
464void RoutePoint::ReLoadIcon(
void) {
465 if (!pWayPointMan)
return;
466 bool icon_exists = pWayPointMan->DoesIconExist(m_IconName);
468 wxString iconUse = m_IconName;
472 wxString tentative_icon = m_IconName.Lower();
473 if (pWayPointMan->DoesIconExist(tentative_icon)) {
475 m_IconName = tentative_icon;
476 iconUse = m_IconName;
481 if (!pWayPointMan->DoesIconExist(_T(
"tempsub"))) {
484 wxBitmap bmp = style->GetIcon(_T(
"circle"));
486 pWayPointMan->ProcessIcon(bmp, _T(
"tempsub"), _T(
"tempsub"));
489 iconUse = _T(
"tempsub");
493 m_pbmIcon = pWayPointMan->GetIconBitmap(iconUse);
494 m_bPreScaled = pWayPointMan->GetIconPrescaled(iconUse);
497 m_wpBBox_view_scale_ppm = -1;
502 m_IconScaleFactor = -1;
506bool RoutePoint::IsVisibleSelectable(
ChartCanvas *canvas,
bool boverrideViz) {
516 if (g_bOverruleScaMin)
518 else if (canvas->GetScaleValue() >= (
double)(m_ScaMin + 1))
524int RoutePoint::GetIconImageIndex() {
527 wxArrayPtrVoid *proute_array = g_pRouteMan->GetRouteArrayContaining(
this);
530 bool brp_viz =
false;
532 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
534 if (pr->IsVisible()) {
542 return (pWayPointMan->GetFIconImageListIndex(GetIconBitmap()));
545 return (pWayPointMan->GetIconImageListIndex(GetIconBitmap()));
547 return (pWayPointMan->GetXIconImageListIndex(GetIconBitmap()));
553 return (pWayPointMan->GetIconImageListIndex(GetIconBitmap()));
555 return (pWayPointMan->GetXIconImageListIndex(GetIconBitmap()));
559bool RoutePoint::IsSharedInVisibleRoute() {
562 wxArrayPtrVoid *proute_array = g_pRouteMan->GetRouteArrayContaining(
this);
565 bool brp_viz =
false;
567 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
569 if (pr->IsVisible()) {
582 bool boverride_viz) {
586 canvas->GetCanvasPointPix(m_lat, m_lon, &r);
589 if (NULL != rpn) *rpn = r;
596 if (!IsVisibleSelectable(canvas, boverride_viz))
return;
599 if (m_IconName == _T(
"empty") && !m_bShowName && !m_bPtIsSelected)
return;
603 pen = g_pRouteMan->GetActiveRoutePointPen();
605 pen = g_pRouteMan->GetRoutePointPen();
609 if ((m_bIsActive) && (m_IconName != _T(
"mob")))
610 pbm = pWayPointMan->GetIconBitmap(_T (
"activepoint" ));
614 wxBitmap *pbms = NULL;
615 if ((g_MarkScaleFactorExp > 1.0) && !m_bPreScaled) {
616 if (m_IconScaleFactor != g_MarkScaleFactorExp) {
617 wxImage scaled_image = pbm->ConvertToImage();
618 int new_width = pbm->GetWidth() * g_MarkScaleFactorExp;
619 int new_height = pbm->GetHeight() * g_MarkScaleFactorExp;
620 m_ScaledBMP = wxBitmap(
621 scaled_image.Scale(new_width, new_height, wxIMAGE_QUALITY_HIGH));
623 m_IconScaleFactor = g_MarkScaleFactorExp;
625 if (m_ScaledBMP.IsOk()) pbm = &m_ScaledBMP;
628 int sx2 = pbm->GetWidth() / 2;
629 int sy2 = pbm->GetHeight() / 2;
632 wxRect r1(r.x - sx2, r.y - sy2, sx2 * 2, sy2 * 2);
635 if (0 == m_pMarkFont) {
636 m_pMarkFont = FontMgr::Get().GetFont(_(
"Marks"));
637 m_FontColor = FontMgr::Get().GetFontColor(_(
"Marks"));
638 CalculateNameExtents();
642 wxRect r2(r.x + m_NameLocationOffsetX, r.y + m_NameLocationOffsetY,
643 m_NameExtents.x, m_NameExtents.y);
653 hilitebox.Inflate(20);
656 hilitebox.Inflate(4);
660 wxColour hi_colour = pen->GetColour();
661 unsigned char transparency = 100;
662 if (m_bRPIsBeingEdited) {
663 hi_colour = GetGlobalColor(_T (
"YELO1" ));
668 if (m_bPtIsSelected || m_bRPIsBeingEdited) {
669 AlphaBlending(dc, r.x + hilitebox.x, r.y + hilitebox.y, hilitebox.width,
670 hilitebox.height, radius, hi_colour, transparency);
673 bool bDrawHL =
false;
675 if (m_bBlink && (gFrame->nBlinkerTick & 1)) bDrawHL =
true;
677 if ((!bDrawHL) && (NULL != m_pbmIcon)) {
678 dc.DrawBitmap(*pbm, r.x - sx2, r.y - sy2,
true);
681 dc.CalcBoundingBox(r.x - sx2, r.y - sy2);
682 dc.CalcBoundingBox(r.x + sx2, r.y + sy2);
687 dc.SetFont(*m_pMarkFont);
688 dc.SetTextForeground(m_FontColor);
690 dc.DrawText(m_MarkName, r.x + m_NameLocationOffsetX,
691 r.y + m_NameLocationOffsetY);
696 if (m_iWaypointRangeRingsNumber && m_bShowWaypointRangeRings) {
697 double factor = 1.00;
698 if (m_iWaypointRangeRingsStepUnits == 1)
701 factor *= m_fWaypointRangeRingsStep;
705 ll_gc_ll(m_lat, m_lon, 0, factor, &tlat, &tlon);
706 canvas->GetCanvasPointPix(tlat, tlon, &r1);
709 sqrt(pow((
double)(r.x - r1.x), 2) + pow((
double)(r.y - r1.y), 2));
710 int pix_radius = (int)lpp;
712 wxPen ppPen1(m_wxcWaypointRangeRingsColour, 2);
713 wxBrush saveBrush = dc.GetBrush();
714 wxPen savePen = dc.GetPen();
717 wxBrush(m_wxcWaypointRangeRingsColour, wxBRUSHSTYLE_TRANSPARENT));
719 for (
int i = 1; i <= m_iWaypointRangeRingsNumber; i++)
720 dc.StrokeCircle(r.x, r.y, i * pix_radius);
722 dc.SetBrush(saveBrush);
727 CurrentRect_in_DC.x = r.x + hilitebox.x;
728 CurrentRect_in_DC.y = r.y + hilitebox.y;
729 CurrentRect_in_DC.width = hilitebox.width;
730 CurrentRect_in_DC.height = hilitebox.height;
733 g_blink_rect = CurrentRect_in_DC;
740 bool use_cached_screen_coords,
bool bVizOverride) {
741 if (!IsVisibleSelectable(canvas, bVizOverride))
return;
744 if (m_IconName == _T(
"empty") && !m_bShowName && !m_bPtIsSelected)
return;
746 if (m_wpBBox.GetValid() && vp.view_scale_ppm == m_wpBBox_view_scale_ppm &&
747 vp.rotation == m_wpBBox_rotation) {
749 LLBBox vpBBox = vp.GetBBox();
750 if (vpBBox.IntersectOut(m_wpBBox)) {
752 if (m_bShowWaypointRangeRings && (m_iWaypointRangeRingsNumber > 0)) {
753 double factor = 1.00;
754 if (m_iWaypointRangeRingsStepUnits == 1)
757 double radius = factor * m_iWaypointRangeRingsNumber *
758 m_fWaypointRangeRingsStep / 60.;
760 LLBBox radar_box = m_wpBBox;
761 radar_box.EnLarge(radius * 2);
762 if (vpBBox.IntersectOut(radar_box)) {
772 unsigned char transparency = 150;
774 if (use_cached_screen_coords && m_pos_on_screen)
775 r.x = m_screen_pos.m_x, r.y = m_screen_pos.m_y;
777 canvas->GetCanvasPointPix(m_lat, m_lon, &r);
779 if (r.x == INVALID_COORD)
return;
783 if ((m_bIsActive) && (m_IconName != _T(
"mob")))
784 pbm = pWayPointMan->GetIconBitmap(_T (
"activepoint" ));
789 if (!pbm->IsOk())
return;
791 int sx2 = pbm->GetWidth() / 2;
792 int sy2 = pbm->GetHeight() / 2;
795 wxRect r1(r.x - sx2, r.y - sy2, sx2 * 2, sy2 * 2);
800 m_pMarkFont = FontMgr::Get().GetFont(_(
"Marks"));
801 m_FontColor = FontMgr::Get().GetFontColor(_(
"Marks"));
802 if (m_iTextTexture) {
803 glDeleteTextures(1, &m_iTextTexture);
807 CalculateNameExtents();
811 wxRect r2(r.x + m_NameLocationOffsetX, r.y + m_NameLocationOffsetY,
812 m_NameExtents.x, m_NameExtents.y);
822 hilitebox.x *= g_MarkScaleFactorExp;
823 hilitebox.y *= g_MarkScaleFactorExp;
824 hilitebox.width *= g_MarkScaleFactorExp;
825 hilitebox.height *= g_MarkScaleFactorExp;
830 hilitebox.Inflate(20);
833 hilitebox.Inflate(4);
838 if (!m_wpBBox.GetValid() || vp.view_scale_ppm != m_wpBBox_view_scale_ppm ||
839 vp.rotation != m_wpBBox_rotation) {
840 double lat1, lon1, lat2, lon2;
841 canvas->GetCanvasPixPoint(r.x + hilitebox.x,
842 r.y + hilitebox.y + hilitebox.height, lat1, lon1);
843 canvas->GetCanvasPixPoint(r.x + hilitebox.x + hilitebox.width,
844 r.y + hilitebox.y, lat2, lon2);
847 m_wpBBox.Set(lat1, lon1, lat2, lon2 + 360);
849 m_wpBBox.Set(lat1, lon1, lat2, lon2);
851 m_wpBBox_view_scale_ppm = vp.view_scale_ppm;
852 m_wpBBox_rotation = vp.rotation;
859 if (m_bPtIsSelected) {
862 wxPen *pen = g_pRouteMan->GetActiveRoutePointPen();
863 hi_colour = pen->GetColour();
865 hi_colour = GetGlobalColor(_T (
"YELO1" ));
868 AlphaBlending(dc, r.x + hilitebox.x, r.y + hilitebox.y, hilitebox.width,
869 hilitebox.height, radius, hi_colour, transparency);
872 bool bDrawHL =
false;
874 if (m_bBlink && (gFrame->nBlinkerTick & 1)) bDrawHL =
true;
876 if ((!bDrawHL) && (NULL != m_pbmIcon)) {
878 unsigned int IconTexture = pWayPointMan->GetIconTexture(pbm, glw, glh);
880 glBindTexture(GL_TEXTURE_2D, IconTexture);
882 glEnable(GL_TEXTURE_2D);
885 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
886 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
888 int w = r1.width, h = r1.height;
892 scale = g_MarkScaleFactorExp;
895 float ws = r1.width *
scale;
896 float hs = r1.height *
scale;
897 float xs = r.x - ws / 2.;
898 float ys = r.y - hs / 2.;
899 float u = (float)w / glw, v = (
float)h / glh;
901#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
921 coords[6] = xs, coords[7] = ys + hs;
923 glChartCanvas::RenderSingleTexture(dc, coords, uv, &vp, 0, 0, 0);
926 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
934 glVertex2f(xs + ws, ys);
936 glVertex2f(xs + ws, ys + hs);
938 glVertex2f(xs, ys + hs);
944 glDisable(GL_TEXTURE_2D);
947 if (m_bShowName && m_pMarkFont) {
948 int w = m_NameExtents.x, h = m_NameExtents.y;
949 if (!m_iTextTexture && w && h) {
953 dc.SelectObject(tbm);
954 dc.SetBackground(wxBrush(*wxBLACK));
956 dc.SetFont(*m_pMarkFont);
957 dc.SetTextForeground(*wxWHITE);
958 dc.DrawText(m_MarkName, 0, 0);
959 dc.SelectObject(wxNullBitmap);
962 wxImage image = tbm.ConvertToImage();
963 unsigned char *d = image.GetData();
964 unsigned char *e =
new unsigned char[w * h];
966 for (
int p = 0; p < w * h; p++) e[p] = d[3 * p + 0];
970 glGenTextures(1, &m_iTextTexture);
971 glBindTexture(GL_TEXTURE_2D, m_iTextTexture);
973 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
974 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
976 m_iTextTextureWidth = NextPow2(w);
977 m_iTextTextureHeight = NextPow2(h);
978 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_iTextTextureWidth,
979 m_iTextTextureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
980 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_ALPHA, GL_UNSIGNED_BYTE,
985 sdc.SetFont(*m_pMarkFont);
986 sdc.GetTextExtent(m_MarkName, &w, &h, NULL, NULL, m_pMarkFont);
989 wxBitmap bmp( w, h );
991 temp_dc.SelectObject( bmp );
994 temp_dc.SetBackground( wxBrush( wxColour( 0, 0, 0 ) ) );
998 temp_dc.SetFont( *m_pMarkFont );
999 temp_dc.SetTextForeground( wxColour( 255, 255, 255 ) );
1000 temp_dc.DrawText( m_MarkName, 0, 0 );
1001 temp_dc.SelectObject( wxNullBitmap );
1005 wxImage image = bmp.ConvertToImage();
1007 unsigned char *data =
new unsigned char[w * h * 4];
1008 unsigned char *im = image.GetData();
1012 unsigned int r = m_FontColor.Red();
1013 unsigned int g = m_FontColor.Green();
1014 unsigned int b = m_FontColor.Blue();
1015 for(
int i = 0; i < h; i++ ){
1016 for(
int j=0 ; j < w ; j++){
1017 unsigned int index = ((i*w) + j) * 4;
1021 data[index+3] = im[((i*w) + j) * 3];
1026 glGenTextures(1, &m_iTextTexture);
1028 glBindTexture(GL_TEXTURE_2D, m_iTextTexture);
1030 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1031 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1033 m_iTextTextureWidth = NextPow2(w);
1034 m_iTextTextureHeight = NextPow2(h);
1035 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_iTextTextureWidth, m_iTextTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1036 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
1038 glEnable(GL_TEXTURE_2D);
1040 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1045 if (m_iTextTexture) {
1047 glBindTexture(GL_TEXTURE_2D, m_iTextTexture);
1049 glEnable(GL_TEXTURE_2D);
1052 int x = r.x + m_NameLocationOffsetX, y = r.y + m_NameLocationOffsetY;
1053 float u = (float)w / m_iTextTextureWidth,
1054 v = (
float)h / m_iTextTextureHeight;
1055#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1056 glColor3ub(255, 255, 255);
1062 glVertex2f(x + w, y);
1064 glVertex2f(x + w, y + h);
1066 glVertex2f(x, y + h);
1089 coords[6] = x, coords[7] = y + h;
1091 glChartCanvas::RenderSingleTexture(dc, coords, uv, &vp, 0, 0, 0);
1094 glDisable(GL_BLEND);
1095 glDisable(GL_TEXTURE_2D);
1100 if (m_iWaypointRangeRingsNumber && m_bShowWaypointRangeRings) {
1101 double factor = 1.00;
1102 if (m_iWaypointRangeRingsStepUnits == 1)
1105 factor *= m_fWaypointRangeRingsStep;
1109 ll_gc_ll(m_lat, m_lon, 0, factor, &tlat, &tlon);
1110 canvas->GetCanvasPointPix(tlat, tlon, &r1);
1113 sqrt(pow((
double)(r.x - r1.x), 2) + pow((
double)(r.y - r1.y), 2));
1114 int pix_radius = (int)lpp;
1116 extern wxColor GetDimColor(wxColor c);
1117 wxColor ring_dim_color = GetDimColor(m_wxcWaypointRangeRingsColour);
1119 double platform_pen_width = wxRound(
1120 wxMax(1.0, g_Platform->GetDisplayDPmm() /
1122 wxPen ppPen1(ring_dim_color, platform_pen_width);
1123 wxBrush saveBrush = dc.GetBrush();
1124 wxPen savePen = dc.GetPen();
1126 dc.SetBrush(wxBrush(ring_dim_color, wxBRUSHSTYLE_TRANSPARENT));
1128 for (
int i = 1; i <= m_iWaypointRangeRingsNumber; i++)
1129 dc.StrokeCircle(r.x, r.y, i * pix_radius);
1131 dc.SetBrush(saveBrush);
1135 if (m_bDrawDragHandle) {
1137 double platform_pen_width = wxRound(
1138 wxMax(1.0, g_Platform->GetDisplayDPmm() /
1141 wxColor dh_color = GetGlobalColor(_T (
"YELO1" ));
1142 wxPen ppPen1(dh_color, 3 * platform_pen_width);
1144 dc.DrawLine(r.x + hilitebox.width / 4, r.y + hilitebox.height / 4,
1145 r.x + m_drag_line_length_man, r.y + m_drag_line_length_man);
1147 dh_color = wxColor(0, 0, 0);
1148 wxPen ppPen2(dh_color, platform_pen_width);
1150 dc.DrawLine(r.x + hilitebox.width / 4, r.y + hilitebox.height / 4,
1151 r.x + m_drag_line_length_man, r.y + m_drag_line_length_man);
1154 glBindTexture(GL_TEXTURE_2D, m_dragIconTexture);
1156 glEnable(GL_TEXTURE_2D);
1159 int x = r.x + m_drag_icon_offset, y = r.y + m_drag_icon_offset,
1160 w = m_dragIcon.GetWidth(), h = m_dragIcon.GetHeight();
1164 float ws = w *
scale;
1165 float hs = h *
scale;
1166 float xs = x - ws / 2.;
1167 float ys = y - hs / 2.;
1168 float u = (float)w / m_dragIconTextureWidth,
1169 v = (
float)h / m_dragIconTextureWidth;
1171#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1172 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1183 glVertex2f(xs + ws, ys);
1185 glVertex2f(xs + ws, ys + hs);
1187 glVertex2f(xs, ys + hs);
1206 coords[2] = xs + ws;
1208 coords[4] = xs + ws;
1209 coords[5] = ys + hs;
1210 coords[6] = xs, coords[7] = ys + hs;
1212 glChartCanvas::RenderSingleTexture(dc, coords, uv, &vp, 0, 0, 0);
1215 glDisable(GL_BLEND);
1216 glDisable(GL_TEXTURE_2D);
1220 g_blink_rect = CurrentRect_in_DC;
1223 CurrentRect_in_DC.x = r.x + hilitebox.x;
1224 CurrentRect_in_DC.y = r.y + hilitebox.y;
1225 CurrentRect_in_DC.width = hilitebox.width;
1226 CurrentRect_in_DC.height = hilitebox.height;
1229 g_blink_rect = CurrentRect_in_DC;
1233void RoutePoint::SetPosition(
double lat,
double lon) {
1238void RoutePoint::CalculateDCRect(wxDC &dc,
ChartCanvas *canvas, wxRect *prect) {
1239 dc.ResetBoundingBox();
1240 dc.DestroyClippingRegion();
1244 Draw(odc, canvas, NULL);
1247 prect->x = dc.MinX() - 1;
1248 prect->y = dc.MinY() - 1;
1249 prect->width = dc.MaxX() - dc.MinX() + 2;
1250 prect->height = dc.MaxY() - dc.MinY() + 2;
1253bool RoutePoint::IsSame(
RoutePoint *pOtherRP) {
1254 bool IsSame =
false;
1256 if (this->m_MarkName == pOtherRP->m_MarkName) {
1257 if (fabs(this->m_lat - pOtherRP->m_lat) < 1.e-6 &&
1258 fabs(this->m_lon - pOtherRP->m_lon) < 1.e-6)
1264bool RoutePoint::SendToGPS(
const wxString &com_name,
SendToGpsDlg *dialog) {
1266 if (g_pMUX) result = g_pMUX->SendWaypointToGPS(
this, com_name, dialog);
1270 msg = _(
"Waypoint(s) Transmitted.");
1272 if (result == ERR_GARMIN_INITIALIZE)
1273 msg = _(
"Error on Waypoint Upload. Garmin GPS not connected");
1275 msg = _(
"Error on Waypoint Upload. Please check logfiles...");
1278 OCPNMessageBox(NULL, msg, _(
"OpenCPN Info"), wxOK | wxICON_INFORMATION);
1280 return (result == 0);
1283double RoutePoint::GetWaypointArrivalRadius() {
1284 if ((m_WaypointArrivalRadius >= 0) && (m_WaypointArrivalRadius < 0.001)) {
1285 SetWaypointArrivalRadius(g_n_arrival_circle_radius);
1286 return m_WaypointArrivalRadius;
1288 return m_WaypointArrivalRadius;
1291int RoutePoint::GetWaypointRangeRingsNumber() {
1292 if (m_iWaypointRangeRingsNumber == -1)
1293 return g_iWaypointRangeRingsNumber;
1295 return m_iWaypointRangeRingsNumber;
1298float RoutePoint::GetWaypointRangeRingsStep() {
1299 if (m_fWaypointRangeRingsStep == -1)
1300 return g_fWaypointRangeRingsStep;
1302 return m_fWaypointRangeRingsStep;
1305int RoutePoint::GetWaypointRangeRingsStepUnits() {
1306 if (m_iWaypointRangeRingsStepUnits == -1)
1307 return g_iWaypointRangeRingsStepUnits;
1309 return m_iWaypointRangeRingsStepUnits;
1312wxColour RoutePoint::GetWaypointRangeRingsColour(
void) {
1313 if (m_wxcWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX) ==
1315 return g_colourWaypointRangeRingsColour;
1317 return m_wxcWaypointRangeRingsColour;
1320void RoutePoint::SetScaMin(
long val) {
1321 if (val < SCAMIN_MIN)
1324 if (val < (
long)m_ScaMax * 5) val = (long)m_ScaMax * 5;
1327void RoutePoint::SetScaMin(wxString str) {
1329 if (!str.ToLong(&val)) val = MAX_INT_VAL;
1333void RoutePoint::SetScaMax(
long val) {
1334 if (val > (
int)m_ScaMin / 5)
1335 m_ScaMax = (int)m_ScaMin /
1338void RoutePoint::SetScaMax(wxString str) {
1340 if (!str.ToLong(&val)) val = 0;
1344void RoutePoint::ShowScaleWarningMessage(
ChartCanvas *canvas) {
1345 wxString strA = _(
"The ScaMin value for new waypoints is set to");
1346 wxString strB = _(
"but current chartscale is");
1348 _(
"Therefore the new waypoint will not be visible at this zoom level.");
1350 wxString::Format(_T(
"%s %li,\n %s %.0f.\n%s"), strA, GetScaMin(), strB,
1351 canvas->GetScaleValue(), strC);
1352 OCPNMessageBox(canvas, MessStr);
1355void RoutePoint::SetPlannedSpeed(
double spd) {
1356 if (spd >= 0.0 && spd <= 1000.0) m_PlannedSpeed = spd;
1359double RoutePoint::GetPlannedSpeed() {
1360 if (m_PlannedSpeed < 0.0001 &&
1361 m_MarkDescription.Find(_T(
"VMG=")) != wxNOT_FOUND) {
1365 (m_MarkDescription.Mid(m_MarkDescription.Find(_T(
"VMG=")) + 4))
1368 if (!s_vmg.ToDouble(&vmg)) {
1369 m_MarkDescription.Replace(_T(
"VMG=") + s_vmg +
";", wxEmptyString);
1370 SetPlannedSpeed(vmg);
1373 return m_PlannedSpeed;
1376wxDateTime RoutePoint::GetETD() {
1377 if (m_seg_etd.IsValid()) {
1378 if (!GetETA().IsValid() || m_seg_etd > GetETA()) {
1384 if (m_MarkDescription.Find(_T(
"ETD=")) != wxNOT_FOUND) {
1385 wxDateTime etd = wxInvalidDateTime;
1387 (m_MarkDescription.Mid(m_MarkDescription.Find(_T(
"ETD=")) + 4))
1389 const wxChar *parse_return = etd.ParseDateTime(s_etd);
1391 wxString tz(parse_return);
1393 if (tz.Find(_T(
"UT")) != wxNOT_FOUND) {
1396 if (tz.Find(_T(
"LMT")) != wxNOT_FOUND) {
1398 long lmt_offset = (long)((m_lon * 3600.) / 15.);
1399 wxTimeSpan lmt(0, 0, (
int)lmt_offset, 0);
1402 m_seg_etd = etd.ToUTC();
1405 if (etd.IsValid() && (!GetETA().IsValid() || etd > GetETA())) {
1406 m_MarkDescription.Replace(s_etd, wxEmptyString);
1415 return wxInvalidDateTime;
1418wxDateTime RoutePoint::GetManualETD() {
1419 if (m_manual_etd && m_seg_etd.IsValid()) {
1422 return wxInvalidDateTime;
1425wxDateTime RoutePoint::GetETA() {
1426 if (m_seg_eta.IsValid()) {
1429 return wxInvalidDateTime;
1432wxString RoutePoint::GetETE() {
1433 if (m_seg_ete != 0) {
1434 return formatTimeDelta(m_seg_ete);
1436 return wxEmptyString;
1439void RoutePoint::SetETE(wxLongLong secs) { m_seg_ete = secs; }
1441void RoutePoint::SetETD(
const wxDateTime &etd) {
1443 m_manual_etd = TRUE;
1446bool RoutePoint::SetETD(
const wxString &ts) {
1448 m_seg_etd = wxInvalidDateTime;
1449 m_manual_etd =
false;
1453 wxString::const_iterator end;
1454 if (tmp.ParseISOCombined(ts)) {
1457 }
else if (tmp.ParseDateTime(ts, &end)) {
Route "Send to GPS..." Dialog Definition.