25#include <wx/datetime.h>
26#include <wx/dcscreen.h>
27#include <wx/dynarray.h>
30#include <wx/tokenzr.h>
33#include "base_platform.h"
36#include "glChartCanvas.h"
37#include "navutil_base.h"
40#include "route_point.h"
42#include "wx28compat.h"
44#include <wx/listimpl.cpp>
48extern bool g_bIsNewLayer;
51extern 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;
58extern float g_ChartScaleFactorExp;
59extern int g_iWpt_ScaMin;
60extern bool g_bUseWptScaMin;
61extern bool g_bOverruleScaMin;
63WX_DEFINE_LIST(RoutePointList);
65RoutePoint::RoutePoint() {
72 m_seg_etd = wxInvalidDateTime;
75 m_seg_eta = wxInvalidDateTime;
76 m_bDynamicName =
false;
77 m_bPtIsSelected =
false;
78 m_bRPIsBeingEdited =
false;
82 m_CreateTimeX = wxDateTime::Now();
83 m_bIsolatedMark =
false;
88 CurrentRect_in_DC = wxRect(0, 0, 0, 0);
89 m_NameLocationOffsetX = -10;
90 m_NameLocationOffsetY = 8;
98 m_HyperlinkList =
new HyperlinkList;
100 m_GUID = pWayPointMan->CreateGUID(
this);
102 m_IconName = wxEmptyString;
104 m_MarkName = wxEmptyString;
106 m_bIsInLayer =
false;
109 m_WaypointArrivalRadius = g_n_arrival_circle_radius;
111 m_bShowWaypointRangeRings = (bool)g_iWaypointRangeRingsNumber;
113 m_iWaypointRangeRingsNumber = g_iWaypointRangeRingsNumber;
114 m_fWaypointRangeRingsStep = g_fWaypointRangeRingsStep;
115 m_iWaypointRangeRingsStepUnits = g_iWaypointRangeRingsStepUnits;
116 m_wxcWaypointRangeRingsColour = g_colourWaypointRangeRingsColour;
117 m_ScaMin = g_iWpt_ScaMin;
119 b_UseScamin = g_bUseWptScaMin;
122 m_pos_on_screen =
false;
124 m_bDrawDragHandle =
false;
125 m_dragIconTexture = 0;
126 m_draggingOffsetx = m_draggingOffsety = 0;
129 m_IconIsDirty =
true;
134 m_MarkName = orig->GetName();
137 m_seg_len = orig->m_seg_len;
138 m_seg_vmg = orig->m_seg_vmg;
140 m_seg_etd = orig->m_seg_etd;
141 m_manual_etd =
false;
143 m_bDynamicName = orig->m_bDynamicName;
144 m_bPtIsSelected = orig->m_bPtIsSelected;
145 m_bRPIsBeingEdited = orig->m_bRPIsBeingEdited;
146 m_bIsActive = orig->m_bIsActive;
147 m_bBlink = orig->m_bBlink;
148 m_bIsInRoute = orig->m_bIsInRoute;
149 m_CreateTimeX = orig->m_CreateTimeX;
150 m_bIsolatedMark = orig->m_bIsolatedMark;
151 m_bShowName = orig->m_bShowName;
152 SetShared(orig->IsShared());
153 m_bIsVisible = orig->m_bIsVisible;
154 m_bIsListed = orig->m_bIsListed;
155 CurrentRect_in_DC = orig->CurrentRect_in_DC;
156 m_NameLocationOffsetX = orig->m_NameLocationOffsetX;
157 m_NameLocationOffsetY = orig->m_NameLocationOffsetY;
158 m_pMarkFont = orig->m_pMarkFont;
159 m_MarkDescription = orig->m_MarkDescription;
160 m_btemp = orig->m_btemp;
161 m_ScaMin = orig->m_ScaMin;
162 m_ScaMax = orig->m_ScaMax;
163 m_HyperlinkList =
new HyperlinkList;
164 m_IconName = orig->m_IconName;
165 m_TideStation = orig->m_TideStation;
166 SetPlannedSpeed(orig->GetPlannedSpeed());
168 m_bIsInLayer = orig->m_bIsInLayer;
169 m_GUID = pWayPointMan->CreateGUID(
this);
172 m_ManagerNode = NULL;
174 m_WaypointArrivalRadius = orig->GetWaypointArrivalRadius();
175 m_bShowWaypointRangeRings = orig->m_bShowWaypointRangeRings;
176 m_iWaypointRangeRingsNumber = orig->m_iWaypointRangeRingsNumber;
177 m_fWaypointRangeRingsStep = orig->m_fWaypointRangeRingsStep;
178 m_iWaypointRangeRingsStepUnits = orig->m_iWaypointRangeRingsStepUnits;
179 m_wxcWaypointRangeRingsColour = orig->m_wxcWaypointRangeRingsColour;
180 m_ScaMin = orig->m_ScaMin;
181 m_ScaMax = orig->m_ScaMax;
182 b_UseScamin = orig->b_UseScamin;
183 m_IconIsDirty = orig->m_IconIsDirty;
185 m_bDrawDragHandle =
false;
186 m_dragIconTexture = 0;
187 m_draggingOffsetx = m_draggingOffsety = 0;
190RoutePoint::RoutePoint(
double lat,
double lon,
const wxString &icon_ident,
191 const wxString &name,
const wxString &pGUID,
200 else if (m_lon > 180.)
207 m_seg_etd = wxInvalidDateTime;
208 m_manual_etd =
false;
210 m_bDynamicName =
false;
211 m_bPtIsSelected =
false;
212 m_bRPIsBeingEdited =
false;
215 m_bIsInRoute =
false;
216 m_CreateTimeX = wxDateTime::Now();
217 m_bIsolatedMark =
false;
222 CurrentRect_in_DC = wxRect(0, 0, 0, 0);
223 m_NameLocationOffsetX = -10;
224 m_NameLocationOffsetY = 8;
227 m_bPreScaled =
false;
230 m_ManagerNode = NULL;
231 m_IconScaleFactor = 1.0;
232 m_ScaMin = MAX_INT_VAL;
234 m_HyperlinkList =
new HyperlinkList;
235 m_IconIsDirty =
true;
239 if (!pGUID.IsEmpty())
242 m_GUID = pWayPointMan->CreateGUID(
this);
245 m_IconName = icon_ident;
252 if (bAddToList && NULL != pWayPointMan) pWayPointMan->AddRoutePoint(
this);
254 m_bIsInLayer = g_bIsNewLayer;
256 m_LayerID = g_LayerIdx;
261 SetWaypointArrivalRadius(g_n_arrival_circle_radius);
263 m_bShowWaypointRangeRings = (bool)g_iWaypointRangeRingsNumber;
265 m_iWaypointRangeRingsNumber = g_iWaypointRangeRingsNumber;
266 m_fWaypointRangeRingsStep = g_fWaypointRangeRingsStep;
267 m_iWaypointRangeRingsStepUnits = g_iWaypointRangeRingsStepUnits;
268 m_wxcWaypointRangeRingsColour = g_colourWaypointRangeRingsColour;
269 m_ScaMin = g_iWpt_ScaMin;
271 b_UseScamin = g_bUseWptScaMin;
273 m_bDrawDragHandle =
false;
274 m_dragIconTexture = 0;
275 m_draggingOffsetx = m_draggingOffsety = 0;
280RoutePoint::~RoutePoint() {
282 if (NULL != pWayPointMan) pWayPointMan->RemoveRoutePoint(
this);
284 if (m_HyperlinkList) {
285 m_HyperlinkList->DeleteContents(
true);
286 delete m_HyperlinkList;
289 if (m_dragIconTexture > 0) glDeleteTextures(1, &m_dragIconTexture);
293wxDateTime RoutePoint::GetCreateTime() {
294 if (!m_CreateTimeX.IsValid()) {
295 if (m_timestring.Len()) ParseGPXDateTime(m_CreateTimeX, m_timestring);
297 return m_CreateTimeX;
300void RoutePoint::SetCreateTime(wxDateTime dt) { m_CreateTimeX = dt; }
302void RoutePoint::SetName(
const wxString &name) {
304 if (m_iTextTexture) {
305 glDeleteTextures(1, &m_iTextTexture);
310 CalculateNameExtents();
313void RoutePoint::CalculateNameExtents(
void) {
319 dc.GetTextExtent(m_MarkName, &w, &h, NULL, NULL, m_pMarkFont);
320 m_NameExtents = wxSize(w, h);
322 dc.SetFont(*m_pMarkFont);
323 m_NameExtents = dc.GetMultiLineTextExtent(m_MarkName);
326 m_NameExtents = wxSize(0, 0);
330bool RoutePoint::IsVisibleSelectable(
double scale_val,
bool boverrideViz) {
340 if (g_bOverruleScaMin)
342 else if (scale_val >= (
double)(m_ScaMin + 1))
348bool RoutePoint::IsSharedInVisibleRoute() {
351 wxArrayPtrVoid *proute_array = g_pRouteMan->GetRouteArrayContaining(
this);
354 bool brp_viz =
false;
356 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
358 if (pr->IsVisible()) {
370void RoutePoint::SetPosition(
double lat,
double lon) {
375bool RoutePoint::IsSame(
RoutePoint *pOtherRP) {
378 if (this->m_MarkName == pOtherRP->m_MarkName) {
379 if (fabs(this->m_lat - pOtherRP->m_lat) < 1.e-6 &&
380 fabs(this->m_lon - pOtherRP->m_lon) < 1.e-6)
386double RoutePoint::GetWaypointArrivalRadius() {
387 if ((m_WaypointArrivalRadius >= 0) && (m_WaypointArrivalRadius < 0.001)) {
388 SetWaypointArrivalRadius(g_n_arrival_circle_radius);
389 return m_WaypointArrivalRadius;
391 return m_WaypointArrivalRadius;
394int RoutePoint::GetWaypointRangeRingsNumber() {
395 if (m_iWaypointRangeRingsNumber == -1)
396 return g_iWaypointRangeRingsNumber;
398 return m_iWaypointRangeRingsNumber;
401float RoutePoint::GetWaypointRangeRingsStep() {
402 if (m_fWaypointRangeRingsStep == -1)
403 return g_fWaypointRangeRingsStep;
405 return m_fWaypointRangeRingsStep;
408int RoutePoint::GetWaypointRangeRingsStepUnits() {
409 if (m_iWaypointRangeRingsStepUnits == -1)
410 return g_iWaypointRangeRingsStepUnits;
412 return m_iWaypointRangeRingsStepUnits;
415wxColour RoutePoint::GetWaypointRangeRingsColour(
void) {
416 if (m_wxcWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX) ==
418 return g_colourWaypointRangeRingsColour;
420 return m_wxcWaypointRangeRingsColour;
423void RoutePoint::SetScaMin(
long val) {
424 if (val < SCAMIN_MIN)
427 if (val < (
long)m_ScaMax * 5) val = (long)m_ScaMax * 5;
430void RoutePoint::SetScaMin(wxString str) {
432 if (!str.ToLong(&val)) val = MAX_INT_VAL;
436void RoutePoint::SetScaMax(
long val) {
437 if (val > (
int)m_ScaMin / 5)
438 m_ScaMax = (int)m_ScaMin /
441void RoutePoint::SetScaMax(wxString str) {
443 if (!str.ToLong(&val)) val = 0;
447void RoutePoint::SetPlannedSpeed(
double spd) {
448 if (spd >= 0.0 && spd <= 1000.0) m_PlannedSpeed = spd;
451double RoutePoint::GetPlannedSpeed() {
452 if (m_PlannedSpeed < 0.0001 &&
453 m_MarkDescription.Find(_T(
"VMG=")) != wxNOT_FOUND) {
457 (m_MarkDescription.Mid(m_MarkDescription.Find(_T(
"VMG=")) + 4))
460 if (!s_vmg.ToDouble(&vmg)) {
461 m_MarkDescription.Replace(_T(
"VMG=") + s_vmg +
";", wxEmptyString);
462 SetPlannedSpeed(vmg);
465 return m_PlannedSpeed;
468wxDateTime RoutePoint::GetETD() {
469 if (m_seg_etd.IsValid()) {
470 if (!GetETA().IsValid() || m_seg_etd > GetETA()) {
476 if (m_MarkDescription.Find(_T(
"ETD=")) != wxNOT_FOUND) {
477 wxDateTime etd = wxInvalidDateTime;
479 (m_MarkDescription.Mid(m_MarkDescription.Find(_T(
"ETD=")) + 4))
481 const wxChar *parse_return = etd.ParseDateTime(s_etd);
483 wxString tz(parse_return);
485 if (tz.Find(_T(
"UT")) != wxNOT_FOUND) {
488 if (tz.Find(_T(
"LMT")) != wxNOT_FOUND) {
490 long lmt_offset = (long)((m_lon * 3600.) / 15.);
491 wxTimeSpan lmt(0, 0, (
int)lmt_offset, 0);
494 m_seg_etd = etd.ToUTC();
497 if (etd.IsValid() && (!GetETA().IsValid() || etd > GetETA())) {
498 m_MarkDescription.Replace(s_etd, wxEmptyString);
507 return wxInvalidDateTime;
510wxDateTime RoutePoint::GetManualETD() {
511 if (m_manual_etd && m_seg_etd.IsValid()) {
514 return wxInvalidDateTime;
517wxDateTime RoutePoint::GetETA() {
518 if (m_seg_eta.IsValid()) {
521 return wxInvalidDateTime;
524wxString RoutePoint::GetETE() {
525 if (m_seg_ete != 0) {
526 return formatTimeDelta(m_seg_ete);
528 return wxEmptyString;
531void RoutePoint::SetETE(wxLongLong secs) { m_seg_ete = secs; }
533void RoutePoint::SetETD(
const wxDateTime &etd) {
538bool RoutePoint::SetETD(
const wxString &ts) {
540 m_seg_etd = wxInvalidDateTime;
541 m_manual_etd =
false;
545 wxString::const_iterator end;
546 if (tmp.ParseISOCombined(ts)) {
549 }
else if (tmp.ParseDateTime(ts, &end)) {