OpenCPN Partial API docs
Loading...
Searching...
No Matches
wmm_pi.cpp
1/******************************************************************************
2 * $Id: wmm_pi.cpp,v 1.0 2011/02/26 01:54:37 nohal Exp $
3 *
4 * Project: OpenCPN
5 * Purpose: WMM Plugin
6 * Author: Pavel Kalian
7 *
8 ***************************************************************************
9 * Copyright (C) 2011-2019 by Pavel Kalian *
10 * $EMAIL$ *
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 * This program is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20 * GNU General Public License for more details. *
21 * *
22 * You should have received a copy of the GNU General Public License *
23 * along with this program; if not, write to the *
24 * Free Software Foundation, Inc., *
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
26 ***************************************************************************
27 */
28
29#include "wx/wxprec.h"
30
31#ifndef WX_PRECOMP
32#include "wx/wx.h"
33#endif // precompiled headers
34
35#ifndef __OCPN__ANDROID__
36#include <GL/gl.h>
37#include <GL/glu.h>
38#else
39#include "qopengl.h" // this gives us the qt runtime gles2.h
40#include "GL/gl_private.h"
41#include "qdebug.h"
42#endif
43
44#include "version.h"
45
46float g_piGLMinSymbolLineWidth = 0.9;
47
48void WMMLogMessage1(wxString s) { wxLogMessage(_T("WMM: ") + s); }
49extern "C" void WMMLogMessage(const char *s) {
50 WMMLogMessage1(wxString::FromAscii(s));
51}
52
53#include "wmm_pi.h"
54
55// the class factories, used to create and destroy instances of the PlugIn
56
57extern "C" DECL_EXP opencpn_plugin *create_pi(void *ppimgr) {
58 return new wmm_pi(ppimgr);
59}
60
61extern "C" DECL_EXP void destroy_pi(opencpn_plugin *p) { delete p; }
62
63wmm_pi *g_pi;
64
65bool g_compact;
66
67//---------------------------------------------------------------------------------------------------------
68//
69// WMM PlugIn Implementation
70//
71//---------------------------------------------------------------------------------------------------------
72
73#include "icons.h"
74#include <N2kMsg.h>
75#include <N2kTypes.h>
76#include <N2kMessages.h>
77
78void WmmUIDialog::EnablePlotChanged(wxCommandEvent &event) {
79 if (m_cbEnablePlot->GetValue()) m_wmm_pi.RecomputePlot();
80 m_wmm_pi.SetShowPlot(m_cbEnablePlot->GetValue());
81 RequestRefresh(m_wmm_pi.m_parent_window);
82}
83
84void WmmUIDialog::PlotSettings(wxCommandEvent &event) {
85 m_wmm_pi.ShowPlotSettings();
86}
87
88void WmmPlotSettingsDialog::About(wxCommandEvent &event) {
89 wxString msg0(
90 _("\n\
91World Magnetic Model Plotting allows users to cross reference the\
92 magnetic variation values printed on many raster charts.\n\n\
93Variation is the angle between true and magnetic north.\n\
94Inclination or dip, is the vertical angle of the magnetic field.\n\
95\t(+- 90 at the magnetic poles)\n\
96Field Strength is the magnetic field in nano tesla from\n\
97\t20000 to 66000\n\n\
98The plotted lines are similar to a topographic map. The \
99space between them can be adjusted; more space takes \
100less time to calculate.\n\n\
101The Step size and Pole accuracy sliders allow a trade off \
102for speed vs computation time.\n\n\
103The World Magnetic Model Plugin was written by Pavel Kalian \
104and extended by Sean D'Epagnier to support plotting."));
105
106 wxMessageDialog dlg(this, msg0, _("WMM Plugin"), wxOK);
107
108 dlg.ShowModal();
109}
110
111//---------------------------------------------------------------------------------------------------------
112//
113// PlugIn initialization and de-init
114//
115//---------------------------------------------------------------------------------------------------------
116
117wmm_pi::wmm_pi(void *ppimgr)
118 : opencpn_plugin_118(ppimgr),
119 m_bShowPlot(false),
120 m_DeclinationMap(DECLINATION_PLOT, MagneticModel, TimedMagneticModel,
121 &Ellip),
122 m_InclinationMap(INCLINATION_PLOT, MagneticModel, TimedMagneticModel,
123 &Ellip),
124 m_FieldStrengthMap(FIELD_STRENGTH_PLOT, MagneticModel, TimedMagneticModel,
125 &Ellip),
126 m_bComputingPlot(false) {
127 // Create the PlugIn icons
128 initialize_images();
129
130 g_pi = this;
131}
132
133int wmm_pi::Init(void) {
134 AddLocaleCatalog(PLUGIN_CATALOG_NAME);
135
136 // Set some default private member parameters
137 m_wmm_dialog_x = 0;
138 m_wmm_dialog_y = 0;
139
140 MagneticModel = NULL;
141 TimedMagneticModel = NULL;
142
143 ::wxDisplaySize(&m_display_width, &m_display_height);
144
145 // Get a pointer to the opencpn display canvas, to use as a parent for the
146 // POI Manager dialog
147 m_parent_window = GetOCPNCanvasWindow();
148
149 // Get a pointer to the opencpn configuration object
150 m_pconfig = GetOCPNConfigObject();
151
152 // And load the configuration items
153 LoadConfig();
154
155#ifdef __OCPN__ANDROID__
156 g_compact = true;
157 m_bShowPlotOptions = false;
158 m_iViewType = 1;
159#endif
160
161 m_buseable = true;
162
163 m_LastVal = wxEmptyString;
164
165 // pFontSmall = new wxFont( 10, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL,
166 // wxFONTWEIGHT_BOLD );
167 pFontSmall = OCPNGetFont(_("WMM_Live_Overlay"));
168
169 m_shareLocn = *GetpSharedDataLocation() + _T("plugins") +
170 wxFileName::GetPathSeparator() + _T("wmm_pi") +
171 wxFileName::GetPathSeparator() + _T("data") +
172 wxFileName::GetPathSeparator();
173
174 // WMM initialization
175
176 /* Memory allocation */
177 int NumTerms, epochs = 1, nMax = 0;
178 wxString cof_filename = m_shareLocn + "WMM.COF";
179
180 if (!MAG_robustReadMagModels(
181 const_cast<char *>((const char *)cof_filename.mb_str()),
182 (MAGtype_MagneticModel * (*)[]) & MagneticModels[0], 1)) {
183 WMMLogMessage1(_T("initialization error"));
184 m_buseable = false;
185 } else {
186 WMMLogMessage1(wxString::Format(_T("WMM model data loaded from file %s."),
187 cof_filename.c_str()));
188 for (int i = 0; i < epochs; i++) {
189 if (MagneticModels[i]->nMax > nMax) {
190 nMax = MagneticModels[i]->nMax;
191 }
192 }
193 NumTerms = ((nMax + 1) * (nMax + 2) / 2);
194
195 TimedMagneticModel = MAG_AllocateModelMemory(
196 NumTerms); /* For storing the time modified WMM Model parameters */
197
198 for (int i = 0; i < epochs; i++) {
199 if (MagneticModels[i] == NULL || TimedMagneticModel == NULL) {
200 WMMLogMessage1(_T("initialization error MAG_Error(2)"));
201 m_buseable = false;
202 }
203 }
204
205 MagneticModel = MagneticModels[0];
206
207 MAG_SetDefaults(&Ellip, &Geoid); /* Set default values and constants */
208 /* Check for Geographic Poles */
209
210 /* Set EGM96 Geoid parameters */
211 Geoid.GeoidHeightBuffer = GeoidHeightBuffer;
212 Geoid.Geoid_Initialized = 1;
213 /* Set EGM96 Geoid parameters END */
214 }
215
216 bool found_handle = false;
217 for (const auto &handle : GetActiveDrivers()) {
218 const auto &attributes = GetAttributes(handle);
219 if (attributes.find("protocol") == attributes.end()) continue;
220 WMMLogMessage1(
221 wxString::Format("handle proto %s", attributes.at("protocol")));
222 if (attributes.at("protocol") == "nmea2000") {
223 m_handleN2k = handle;
224 found_handle = true;
225 break;
226 }
227 }
228 if (!found_handle) {
229 WMMLogMessage1("nmea2000 handle not found");
230 }
231 std::vector<int> pgn_list = {127258};
232 CommDriverResult xx = RegisterTXPGNs(m_handleN2k, pgn_list);
233
234 int ret_flag =
235 (WANTS_OVERLAY_CALLBACK | WANTS_OPENGL_OVERLAY_CALLBACK |
238
239 if (m_bShowIcon) {
240 // This PlugIn needs a toolbar icon, so request its insertion
241 m_leftclick_tool_id =
242 InsertPlugInTool(_T(""), _img_wmm, _img_wmm, wxITEM_NORMAL, _("WMM"),
243 _T(""), NULL, WMM_TOOL_POSITION, 0, this);
244
245 SetIconType(); // SVGs allowed if not showing live icon
246
247 ret_flag |= INSTALLS_TOOLBAR_TOOL;
248 }
249
250 m_pWmmDialog = NULL;
251 m_oDC = NULL;
252
253 return ret_flag;
254}
255
256bool wmm_pi::DeInit(void) {
257 // Record the dialog position
258 if (NULL != m_pWmmDialog) {
259 wxPoint p = m_pWmmDialog->GetPosition();
260 SetWmmDialogX(p.x);
261 SetWmmDialogY(p.y);
262
263 m_pWmmDialog->Close();
264 delete m_pWmmDialog;
265 m_pWmmDialog = NULL;
266 }
267 SaveConfig();
268 if (MagneticModel) {
269 MAG_FreeMagneticModelMemory(MagneticModel);
270 }
271 if (TimedMagneticModel) {
272 MAG_FreeMagneticModelMemory(TimedMagneticModel);
273 }
274
275 RemovePlugInTool(m_leftclick_tool_id);
276
277 /*if (Geoid.GeoidHeightBuffer)
278 {
279 free(Geoid.GeoidHeightBuffer);
280 Geoid.GeoidHeightBuffer = NULL;
281 }*/
282
283 // delete pFontSmall;
284
285 if (m_oDC) delete m_oDC;
286
287 return true;
288}
289
290int wmm_pi::GetAPIVersionMajor() { return MY_API_VERSION_MAJOR; }
291
292int wmm_pi::GetAPIVersionMinor() { return MY_API_VERSION_MINOR; }
293
294int wmm_pi::GetPlugInVersionMajor() { return PLUGIN_VERSION_MAJOR; }
295
296int wmm_pi::GetPlugInVersionMinor() { return PLUGIN_VERSION_MINOR; }
297
298wxBitmap *wmm_pi::GetPlugInBitmap() { return _img_wmm_pi; }
299
300wxString wmm_pi::GetCommonName() { return _("WMM"); }
301
303 return _("World Magnetic Model PlugIn for OpenCPN");
304}
305
307 return _(
308 "World Magnetic Model PlugIn for OpenCPN\n\
309Implements the NOAA World Magnetic Model\n\
310More information:\n\
311https://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml\n\
312The bundled WMM2025 model is valid until late 2029.\n\
313After then, if new version of the plugin will not be released\n\
314in time, get a new WMM.COF from NOAA and place it to the\n\
315location you can find in the OpenCPN logfile.");
316}
317
318int wmm_pi::GetToolbarToolCount(void) { return 1; }
319
321 if (NULL == m_pWmmDialog) return;
322 DimeWindow(m_pWmmDialog);
323}
324
325void wmm_pi::SetIconType() {
326 if (m_bShowLiveIcon) {
327 SetToolbarToolBitmaps(m_leftclick_tool_id, _img_wmm, _img_wmm);
328 SetToolbarToolBitmapsSVG(m_leftclick_tool_id, _T(""), _T(""), _T(""));
329 m_LastVal.Empty();
330 } else {
331 wxString normalIcon = m_shareLocn + _T("wmm_pi.svg");
332 wxString toggledIcon = m_shareLocn + _T("wmm_pi.svg");
333 wxString rolloverIcon = m_shareLocn + _T("wmm_pi.svg");
334
335 SetToolbarToolBitmapsSVG(m_leftclick_tool_id, normalIcon, rolloverIcon,
336 toggledIcon);
337 }
338}
339
340void wmm_pi::RearrangeWindow() {
341 if (NULL == m_pWmmDialog) return;
342 if (m_iViewType == 1) {
343 m_pWmmDialog->sbScursor->Hide(m_pWmmDialog->gScursor, true);
344 m_pWmmDialog->sbSboat->Hide(m_pWmmDialog->gSboat, true);
345 } else {
346 m_pWmmDialog->sbScursor->Show(m_pWmmDialog->gScursor, true, true);
347 m_pWmmDialog->sbSboat->Show(m_pWmmDialog->gSboat, true, true);
348 }
349
350 m_pWmmDialog->m_cbEnablePlot->Show(m_bShowPlotOptions);
351 m_pWmmDialog->m_bPlotSettings->Show(m_bShowPlotOptions);
352
353 if (!m_bShowAtCursor) {
354 m_pWmmDialog->bSframe->Hide(m_pWmmDialog->sbScursor, true);
355 } else {
356 m_pWmmDialog->bSframe->Show(m_pWmmDialog->sbScursor, true, true);
357 if (m_iViewType == 1)
358 m_pWmmDialog->sbScursor->Hide(m_pWmmDialog->gScursor, true);
359 }
360
362
363 m_pWmmDialog->Fit();
364
365#ifdef __WXMSW__
366 // UGLY!!!!!!! On Windows XP the transparent window is not refreshed properly
367 // in OpenGL mode at least on the Atom powered netbooks, so we have to disable
368 // transparency.
369 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
370 bool gl = true;
371 if (pConf) {
372 pConf->SetPath(_T("/Settings"));
373 pConf->Read(_T("OpenGL"), &gl, false);
374 pConf = NULL;
375 }
376 if (!(gl && wxPlatformInfo::Get().GetOSMajorVersion() == 5 &&
377 wxPlatformInfo::Get().GetOSMinorVersion() == 1))
378#endif
379 if (m_pWmmDialog->CanSetTransparent())
380 m_pWmmDialog->SetTransparent(m_iOpacity);
381}
382
384 if (!m_buseable) return;
385 if (NULL == m_pWmmDialog) {
386 m_pWmmDialog = new WmmUIDialog(*this, m_parent_window);
387 wxFont *pFont = OCPNGetFont(_("Dialog"));
388 m_pWmmDialog->SetFont(*pFont);
389
390 m_pWmmDialog->Move(wxPoint(m_wmm_dialog_x, m_wmm_dialog_y));
391 }
392
393 RearrangeWindow();
394 /*m_pWmmDialog->SetMaxSize(m_pWmmDialog->GetSize());
395 m_pWmmDialog->SetMinSize(m_pWmmDialog->GetSize());*/
396 m_pWmmDialog->Show(!m_pWmmDialog->IsShown());
397 m_pWmmDialog->Layout(); // Some platforms need a re-Layout at this point
398 // (gtk, at least)
399 if (m_pWmmDialog->IsShown())
400 SendPluginMessage(_T("WMM_WINDOW_SHOWN"), wxEmptyString);
401 else
402 SendPluginMessage(_T("WMM_WINDOW_HIDDEN"), wxEmptyString);
403
404 wxPoint p = m_pWmmDialog->GetPosition();
405 m_pWmmDialog->Move(0, 0); // workaround for gtk autocentre dialog behavior
406 m_pWmmDialog->Move(p);
407
408#ifdef __OCPN__ANDROID__
409 m_pWmmDialog->CentreOnScreen();
410 m_pWmmDialog->Move(-1, 0);
411#endif
412}
413
414void wmm_pi::RenderOverlayBoth(pi_ocpnDC *dc, PlugIn_ViewPort *vp) {
415 if (!m_bShowPlot) return;
416
417 m_DeclinationMap.Plot(dc, vp, wxColour(255, 0, 90, 220));
418 m_InclinationMap.Plot(dc, vp, wxColour(60, 255, 30, 220));
419 m_FieldStrengthMap.Plot(dc, vp, wxColour(0, 60, 255, 220));
420}
421
422bool wmm_pi::RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp) {
423 if (!m_bShowPlot) return true;
424
425 if (!m_oDC) m_oDC = new pi_ocpnDC();
426
427 m_oDC->SetVP(vp);
428 m_oDC->SetDC(&dc);
429
430 RenderOverlayBoth(m_oDC, vp);
431
432 return true;
433}
434
435bool wmm_pi::RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp) {
436 if (!m_bShowPlot) return true;
437
438 if (!m_oDC) {
439#ifdef ocpnUSE_GL
440 // Set the minimum line width
441 GLint parms[2];
442#ifndef USE_ANDROID_GLES2
443 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
444#else
445 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
446#endif
447 g_piGLMinSymbolLineWidth = wxMax(parms[0], 1);
448#endif
449 m_oDC = new pi_ocpnDC();
450 }
451
452 m_oDC->SetVP(vp);
453 m_oDC->SetDC(NULL);
454
455#ifndef USE_ANDROID_GLES2
456 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LINE_BIT | GL_ENABLE_BIT |
457 GL_POLYGON_BIT | GL_HINT_BIT);
458
459 glEnable(GL_LINE_SMOOTH);
460 glEnable(GL_BLEND);
461 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
462 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
463#endif
464
465 RenderOverlayBoth(m_oDC, vp);
466
467#ifndef USE_ANDROID_GLES2
468 glPopAttrib();
469#endif
470
471 return true;
472}
473
474void wmm_pi::RecomputePlot() {
475 if (m_bCachedPlotOk) return;
476
477 if (m_bComputingPlot) return;
478 m_bComputingPlot = true;
479
480 if (!m_DeclinationMap.Recompute(m_MapDate) ||
481 !m_InclinationMap.Recompute(m_MapDate) ||
482 !m_FieldStrengthMap.Recompute(m_MapDate)) {
483 m_bShowPlot = false;
484 if (m_pWmmDialog) m_pWmmDialog->m_cbEnablePlot->SetValue(false);
485 } else
486 m_bCachedPlotOk = true;
487
488 m_bComputingPlot = false;
489}
490
491void wmm_pi::SetCursorLatLon(double lat, double lon) {
492 if (!m_pWmmDialog) return;
493
494 if (!m_bShowAtCursor)
495 return; // We don't want to waste CPU cycles that much...
496 if (lat < -90 || lat > 90 || lon < -180 || lon > 180 ||
497 NULL == m_pWmmDialog || !m_pWmmDialog->IsShown())
498 return;
499 if (!m_buseable) {
500 m_pWmmDialog->m_tbD->SetValue(_("Error, see log."));
501 return;
502 }
503 CoordGeodetic.lambda = lon;
504 CoordGeodetic.phi = lat;
505 CoordGeodetic.HeightAboveEllipsoid = 0;
506 CoordGeodetic.HeightAboveGeoid = 0;
507 CoordGeodetic.UseGeoid = 0;
508 UserDate.Year = wxDateTime::GetCurrentYear();
509 UserDate.Month =
510 wxDateTime::GetCurrentMonth() + 1; // WHY is it 0 based????????
511 UserDate.Day = wxDateTime::Now().GetDay();
512 char err[255];
513 MAG_DateToYear(&UserDate, err);
514 MAG_GeodeticToSpherical(
515 Ellip, CoordGeodetic,
516 &CoordSpherical); /*Convert from geodeitic to Spherical Equations: 17-18,
517 WMM Technical report*/
518 MAG_TimelyModifyMagneticModel(
519 UserDate, MagneticModel,
520 TimedMagneticModel); /* Time adjust the coefficients, Equation 19, WMM
521 Technical report */
522 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel,
523 &GeoMagneticElements); /* Computes the geoMagnetic field elements
524 and their time change*/
525 MAG_CalculateGridVariation(CoordGeodetic, &GeoMagneticElements);
526 // WMM_PrintUserData(GeoMagneticElements,CoordGeodetic, UserDate,
527 // TimedMagneticModel, &Geoid); /* Print the results */
528 m_pWmmDialog->m_tcF->SetValue(
529 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.F));
530 m_pWmmDialog->m_tcH->SetValue(
531 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.H));
532 m_pWmmDialog->m_tcX->SetValue(
533 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.X));
534 m_pWmmDialog->m_tcY->SetValue(
535 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.Y));
536 m_pWmmDialog->m_tcZ->SetValue(
537 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.Z));
538 m_pWmmDialog->m_tcD->SetValue(
539 wxString::Format(_T("%-5.1lf%c (%s)"), GeoMagneticElements.Decl, 0x00B0,
540 AngleToText(GeoMagneticElements.Decl).c_str()));
541 m_pWmmDialog->m_tcI->SetValue(
542 wxString::Format(_T("%-5.1lf%c"), GeoMagneticElements.Incl, 0x00B0));
543
544 m_cursorVariation = GeoMagneticElements;
545 SendCursorVariation();
546}
547
549 if (!m_buseable) {
550 return;
551 }
552 CoordGeodetic.lambda = pfix.Lon;
553 CoordGeodetic.phi = pfix.Lat;
554 CoordGeodetic.HeightAboveEllipsoid = 0;
555 CoordGeodetic.UseGeoid = 0;
556 UserDate.Year = wxDateTime::GetCurrentYear();
557 UserDate.Month =
558 wxDateTime::GetCurrentMonth() + 1; // WHY is it 0 based????????
559 UserDate.Day = wxDateTime::Now().GetDay();
560 char err[255];
561 MAG_DateToYear(&UserDate, err);
562 MAG_GeodeticToSpherical(
563 Ellip, CoordGeodetic,
564 &CoordSpherical); /*Convert from geodeitic to Spherical Equations: 17-18,
565 WMM Technical report*/
566 MAG_TimelyModifyMagneticModel(
567 UserDate, MagneticModel,
568 TimedMagneticModel); /* Time adjust the coefficients, Equation 19, WMM
569 Technical report */
570 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel,
571 &GeoMagneticElements); /* Computes the geoMagnetic field elements
572 and their time change*/
573 MAG_CalculateGridVariation(CoordGeodetic, &GeoMagneticElements);
574 // WMM_PrintUserData(GeoMagneticElements,CoordGeodetic, UserDate,
575 // TimedMagneticModel, &Geoid); /* Print the results */
576
577 m_boatVariation = GeoMagneticElements;
578 SendBoatVariation();
579
580 wxString NewVal = wxString::Format(_T("%.1f"), GeoMagneticElements.Decl);
582 scale = wxRound(scale * 4.0) / 4.0;
584
585 // scale =
586 // wxMax(1.0, scale); // Let the upstream processing handle minification.
587
588 if (m_bShowIcon && m_bShowLiveIcon &&
589 ((m_LastVal != NewVal) || (scale != m_scale))) {
590 m_scale = scale;
591 m_LastVal = NewVal;
592 int w = _img_wmm_live->GetWidth() * scale;
593 int h = _img_wmm_live->GetHeight() * scale;
594 wxMemoryDC dc;
595 wxBitmap icon;
596
597 // Is SVG available?
598 wxBitmap live =
599 GetBitmapFromSVGFile(m_shareLocn + _T("wmm_live.svg"), w, h);
600 if (!live.IsOk()) {
601 icon = wxBitmap(_img_wmm_live->GetWidth(), _img_wmm_live->GetHeight());
602 dc.SelectObject(icon);
603 dc.DrawBitmap(*_img_wmm_live, 0, 0, true);
604 } else {
605 icon = wxBitmap(w, h);
606 dc.SelectObject(icon);
607 wxColour col;
608 dc.SetBackground(*wxTRANSPARENT_BRUSH);
609 dc.Clear();
610
611 dc.DrawBitmap(live, 0, 0, true);
612 }
613
614 wxColour cf;
615 GetGlobalColor(_T("CHWHT"), &cf);
616 dc.SetTextForeground(cf);
617 if (pFontSmall->IsOk()) {
618 if (live.IsOk()) {
619 int point_size = wxMax(10, 10 * scale);
620 pFontSmall->SetPointSize(point_size);
621
622 // Validate and adjust the font size...
623 // No smaller than 8 pt.
624 int w;
625 wxScreenDC sdc;
626 sdc.GetTextExtent(NewVal, &w, NULL, NULL, NULL, pFontSmall);
627
628 while ((w > (icon.GetWidth() * 8 / 10)) && (point_size >= 8)) {
629 point_size--;
630 pFontSmall->SetPointSize(point_size);
631 sdc.GetTextExtent(NewVal, &w, NULL, NULL, NULL, pFontSmall);
632 }
633 }
634 dc.SetFont(*pFontSmall);
635 }
636 wxSize s = dc.GetTextExtent(NewVal);
637 dc.DrawText(NewVal, (icon.GetWidth() - s.GetWidth()) / 2,
638 (icon.GetHeight() - s.GetHeight()) / 2);
639 dc.SelectObject(wxNullBitmap);
640
641 if (live.IsOk()) {
642 // By using a DC to modify the bitmap, we have lost the original bitmap's
643 // alpha channel Recover it by copying from the original to the target,
644 // bit by bit
645 wxImage imo = live.ConvertToImage();
646 wxImage im = icon.ConvertToImage();
647
648 if (!imo.HasAlpha()) imo.InitAlpha();
649 if (!im.HasAlpha()) im.InitAlpha();
650
651 unsigned char *alive = imo.GetAlpha();
652 unsigned char *target = im.GetAlpha();
653
654 for (int i = 0; i < h; i++) {
655 for (int j = 0; j < w; j++) {
656 int index = (i * w) + j;
657 target[index] = alive[index];
658 }
659 }
660 icon = wxBitmap(im);
661 }
662
663 SetToolbarToolBitmaps(m_leftclick_tool_id, &icon, &icon);
664 }
665
666 if (NULL == m_pWmmDialog || !m_pWmmDialog->IsShown()) return;
667 if (!m_buseable) {
668 m_pWmmDialog->m_tbD->SetValue(_("Error, see log."));
669 return;
670 }
671 m_pWmmDialog->m_tbF->SetValue(
672 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.F));
673 m_pWmmDialog->m_tbH->SetValue(
674 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.H));
675 m_pWmmDialog->m_tbX->SetValue(
676 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.X));
677 m_pWmmDialog->m_tbY->SetValue(
678 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.Y));
679 m_pWmmDialog->m_tbZ->SetValue(
680 wxString::Format(_T("%-9.1lf nT"), GeoMagneticElements.Z));
681 m_pWmmDialog->m_tbD->SetValue(
682 wxString::Format(_T("%-5.1lf%c (%s)"), GeoMagneticElements.Decl, 0x00B0,
683 AngleToText(GeoMagneticElements.Decl).c_str()));
684 m_pWmmDialog->m_tbI->SetValue(
685 wxString::Format(_T("%-5.1lf%c"), GeoMagneticElements.Incl, 0x00B0));
686}
687
688// Demo implementation of response mechanism
689void wmm_pi::SetPluginMessage(wxString &message_id, wxString &message_body) {
690 if (message_id == _T("WMM_VARIATION_REQUEST")) {
691 wxJSONReader r;
692 wxJSONValue v;
693 r.Parse(message_body, &v);
694 double lat = v[_T("Lat")].AsDouble();
695 double lon = v[_T("Lon")].AsDouble();
696 int year = v[_T("Year")].AsInt();
697 int month = v[_T("Month")].AsInt();
698 int day = v[_T("Day")].AsInt();
699 SendVariationAt(lat, lon, year, month, day);
700 } else if (message_id == _T("WMM_VARIATION_BOAT_REQUEST")) {
701 SendBoatVariation();
702 } else if (message_id == _T("WMM_VARIATION_CURSOR_REQUEST")) {
703 SendCursorVariation();
704 }
705}
706
707void wmm_pi::SendVariationAt(double lat, double lon, int year, int month,
708 int day) {
709 wxJSONValue v;
710 v[_T("Lat")] = lat;
711 v[_T("Lon")] = lon;
712 v[_T("Year")] = year;
713 v[_T("Month")] = month;
714 v[_T("Day")] = day;
715 CoordGeodetic.lambda = lon;
716 CoordGeodetic.phi = lat;
717 CoordGeodetic.HeightAboveEllipsoid = 0;
718 CoordGeodetic.UseGeoid = 0;
719 UserDate.Year = year;
720 UserDate.Month = month;
721 UserDate.Day = day;
722 char err[255];
723 MAG_DateToYear(&UserDate, err);
724 MAG_GeodeticToSpherical(
725 Ellip, CoordGeodetic,
726 &CoordSpherical); /*Convert from geodeitic to Spherical Equations: 17-18,
727 WMM Technical report*/
728 MAG_TimelyModifyMagneticModel(
729 UserDate, MagneticModel,
730 TimedMagneticModel); /* Time adjust the coefficients, Equation 19, WMM
731 Technical report */
732 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel,
733 &GeoMagneticElements); /* Computes the geoMagnetic field elements
734 and their time change*/
735 MAG_CalculateGridVariation(CoordGeodetic, &GeoMagneticElements);
736 v[_T("Decl")] = GeoMagneticElements.Decl;
737 v[_T("Decldot")] = GeoMagneticElements.Decldot;
738 v[_T("F")] = GeoMagneticElements.F;
739 v[_T("Fdot")] = GeoMagneticElements.Fdot;
740 v[_T("GV")] = GeoMagneticElements.GV;
741 v[_T("GVdot")] = GeoMagneticElements.GVdot;
742 v[_T("H")] = GeoMagneticElements.H;
743 v[_T("Hdot")] = GeoMagneticElements.Hdot;
744 v[_T("Incl")] = GeoMagneticElements.Incl;
745 v[_T("Incldot")] = GeoMagneticElements.Incldot;
746 v[_T("X")] = GeoMagneticElements.X;
747 v[_T("Xdot")] = GeoMagneticElements.Xdot;
748 v[_T("Y")] = GeoMagneticElements.Y;
749 v[_T("Ydot")] = GeoMagneticElements.Ydot;
750 v[_T("Z")] = GeoMagneticElements.Z;
751 v[_T("Zdot")] = GeoMagneticElements.Zdot;
752 wxJSONWriter w;
753 wxString out;
754 w.Write(v, out);
755 SendPluginMessage(wxString(_T("WMM_VARIATION")), out);
756}
757
758void wmm_pi::SendBoatVariation() {
759 wxJSONValue v;
760 v[_T("Decl")] = m_boatVariation.Decl;
761 v[_T("Decldot")] = m_boatVariation.Decldot;
762 v[_T("F")] = m_boatVariation.F;
763 v[_T("Fdot")] = m_boatVariation.Fdot;
764 v[_T("GV")] = m_boatVariation.GV;
765 v[_T("GVdot")] = m_boatVariation.GVdot;
766 v[_T("H")] = m_boatVariation.H;
767 v[_T("Hdot")] = m_boatVariation.Hdot;
768 v[_T("Incl")] = m_boatVariation.Incl;
769 v[_T("Incldot")] = m_boatVariation.Incldot;
770 v[_T("X")] = m_boatVariation.X;
771 v[_T("Xdot")] = m_boatVariation.Xdot;
772 v[_T("Y")] = m_boatVariation.Y;
773 v[_T("Ydot")] = m_boatVariation.Ydot;
774 v[_T("Z")] = m_boatVariation.Z;
775 v[_T("Zdot")] = m_boatVariation.Zdot;
776 wxJSONWriter w;
777 wxString out;
778 w.Write(v, out);
779 SendPluginMessage(wxString(_T("WMM_VARIATION_BOAT")), out);
780 // Send boat variation as NMEA HVD for the Priority List.
781 SendBoatVarHVD(m_boatVariation.Decl);
782 SendPGN127258(m_boatVariation.Decl);
783}
784
785void wmm_pi::SendCursorVariation() {
786 wxJSONValue v;
787 v[_T("Decl")] = m_cursorVariation.Decl;
788 v[_T("Decldot")] = m_cursorVariation.Decldot;
789 v[_T("F")] = m_cursorVariation.F;
790 v[_T("Fdot")] = m_cursorVariation.Fdot;
791 v[_T("GV")] = m_cursorVariation.GV;
792 v[_T("GVdot")] = m_cursorVariation.GVdot;
793 v[_T("H")] = m_cursorVariation.H;
794 v[_T("Hdot")] = m_cursorVariation.Hdot;
795 v[_T("Incl")] = m_cursorVariation.Incl;
796 v[_T("Incldot")] = m_cursorVariation.Incldot;
797 v[_T("X")] = m_cursorVariation.X;
798 v[_T("Xdot")] = m_cursorVariation.Xdot;
799 v[_T("Y")] = m_cursorVariation.Y;
800 v[_T("Ydot")] = m_cursorVariation.Ydot;
801 v[_T("Z")] = m_cursorVariation.Z;
802 v[_T("Zdot")] = m_cursorVariation.Zdot;
803 wxJSONWriter w;
804 wxString out;
805 w.Write(v, out);
806 SendPluginMessage(wxString(_T("WMM_VARIATION_CURSOR")), out);
807}
808
809wxString wmm_pi::AngleToText(double angle) {
810 int deg = (int)fabs(angle);
811 int min = (fabs(angle) - deg) * 60;
812 if (angle < 0)
813 return wxString::Format(_T("%u%c%u' W"), deg, 0x00B0, min);
814 else
815 return wxString::Format(_T("%u%c%u' E"), deg, 0x00B0, min);
816}
817
818bool wmm_pi::LoadConfig(void) {
819 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
820
821 if (pConf) {
822 pConf->SetPath(_T( "/Settings/WMM" ));
823 pConf->Read(_T( "ViewType" ), &m_iViewType, 1);
824 pConf->Read(_T( "ShowPlotOptions" ), &m_bShowPlotOptions, 1);
825 pConf->Read(_T( "ShowAtCursor" ), &m_bShowAtCursor, 1);
826 pConf->Read(_T( "ShowLiveIcon" ), &m_bShowLiveIcon, 1);
827 pConf->Read(_T( "ShowIcon" ), &m_bShowIcon, 1);
828 pConf->Read(_T( "Opacity" ), &m_iOpacity, 255);
829
830 m_wmm_dialog_x = pConf->Read(_T ( "DialogPosX" ), 20L);
831 m_wmm_dialog_y = pConf->Read(_T ( "DialogPosY" ), 20L);
832
833 if ((m_wmm_dialog_x < 0) || (m_wmm_dialog_x > m_display_width))
834 m_wmm_dialog_x = 5;
835 if ((m_wmm_dialog_y < 0) || (m_wmm_dialog_y > m_display_height))
836 m_wmm_dialog_y = 5;
837
838 pConf->SetPath(_T( "/Settings/WMM/Plot" ));
839 pConf->Read(_T( "Declination" ), &m_DeclinationMap.m_bEnabled, 1);
840 pConf->Read(_T( "DeclinationSpacing" ), &m_DeclinationMap.m_Spacing, 10);
841 pConf->Read(_T( "Inclination" ), &m_InclinationMap.m_bEnabled, 0);
842 pConf->Read(_T( "InclinationSpacing" ), &m_InclinationMap.m_Spacing, 10);
843 pConf->Read(_T( "FieldStrength" ), &m_FieldStrengthMap.m_bEnabled, 0);
844 pConf->Read(_T( "FieldStrengthSpacing" ), &m_FieldStrengthMap.m_Spacing,
845 10000);
846
847 pConf->Read(_T( "StepSize" ), &m_MapStep, 6);
848 pConf->Read(_T( "PoleAccuracy" ), &m_MapPoleAccuracy, 2);
849 m_DeclinationMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
850 m_InclinationMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
851 m_FieldStrengthMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
852
853 m_MapDate = wxDateTime::Now(); /* always reset to current date */
854
855 m_bCachedPlotOk = false;
856
857 pConf->SetPath(_T ( "/Directories" ));
858 wxString s = wxFileName::GetPathSeparator();
859 wxString def = *GetpSharedDataLocation() + _T("plugins") + s +
860 _T("wmm_pi") + s + _T("data") + s;
861 // pConf->Read ( _T ( "WMMDataLocation" ), &m_wmm_dir, def);
862 m_wmm_dir = def;
863 return true;
864 } else
865 return false;
866}
867
868bool wmm_pi::SaveConfig(void) {
869 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
870
871 if (pConf) {
872 pConf->SetPath(_T ( "/Settings/WMM" ));
873 pConf->Write(_T ( "ViewType" ), m_iViewType);
874 pConf->Write(_T ( "ShowPlotOptions" ), m_bShowPlotOptions);
875 pConf->Write(_T ( "ShowAtCursor" ), m_bShowAtCursor);
876 pConf->Write(_T ( "ShowLiveIcon" ), m_bShowLiveIcon);
877 pConf->Write(_T ( "ShowIcon" ), m_bShowIcon);
878 pConf->Write(_T ( "Opacity" ), m_iOpacity);
879
880 pConf->Write(_T ( "DialogPosX" ), m_wmm_dialog_x);
881 pConf->Write(_T ( "DialogPosY" ), m_wmm_dialog_y);
882
883 pConf->SetPath(_T( "/Settings/WMM/Plot" ));
884 pConf->Write(_T( "Declination" ), m_DeclinationMap.m_bEnabled);
885 pConf->Write(_T( "DeclinationSpacing" ), m_DeclinationMap.m_Spacing);
886 pConf->Write(_T( "Inclination" ), m_InclinationMap.m_bEnabled);
887 pConf->Write(_T( "InclinationSpacing" ), m_InclinationMap.m_Spacing);
888 pConf->Write(_T( "FieldStrength" ), m_FieldStrengthMap.m_bEnabled);
889 pConf->Write(_T( "FieldStrengthSpacing" ), m_FieldStrengthMap.m_Spacing);
890 pConf->Write(_T( "StepSize" ), m_MapStep);
891 pConf->Write(_T( "PoleAccuracy" ), m_MapPoleAccuracy);
892
893 pConf->SetPath(_T ( "/Directories" ));
894 pConf->Write(_T ( "WMMDataLocation" ), m_wmm_dir);
895
896 return true;
897 } else
898 return false;
899}
900
901void wmm_pi::ShowPreferencesDialog(wxWindow *parent) {
902 WmmPrefsDialog *dialog =
903 new WmmPrefsDialog(parent, wxID_ANY, _("WMM Preferences"),
904 wxPoint(m_wmm_dialog_x, m_wmm_dialog_y), wxDefaultSize,
905 wxDEFAULT_DIALOG_STYLE);
906 dialog->Fit();
907
908 dialog->m_rbViewType->SetSelection(m_iViewType);
909 dialog->m_cbShowPlotOptions->SetValue(m_bShowPlotOptions);
910 dialog->m_cbShowAtCursor->SetValue(m_bShowAtCursor);
911 dialog->m_cbShowIcon->SetValue(m_bShowIcon);
912 dialog->m_cbLiveIcon->SetValue(m_bShowLiveIcon);
913 dialog->m_sOpacity->SetValue(m_iOpacity);
914
915 if (dialog->ShowModal() == wxID_OK) {
916 m_iViewType = dialog->m_rbViewType->GetSelection();
917 m_bShowPlotOptions = dialog->m_cbShowPlotOptions->GetValue();
918 m_bShowAtCursor = dialog->m_cbShowAtCursor->GetValue();
919 m_bShowLiveIcon = dialog->m_cbLiveIcon->GetValue();
920 m_bShowIcon = dialog->m_cbShowIcon->GetValue();
921 m_iOpacity = dialog->m_sOpacity->GetValue();
922
923 RearrangeWindow();
924 SetIconType();
925
926 SaveConfig();
927 }
928 delete dialog;
929}
930
932 WmmPlotSettingsDialog *dialog = new WmmPlotSettingsDialog(m_parent_window);
933 wxFont *pFont = OCPNGetFont(_("Dialog"));
934 dialog->SetFont(*pFont);
935
936 dialog->Fit();
937
938 dialog->m_cbDeclination->SetValue(m_DeclinationMap.m_bEnabled);
939 dialog->m_scDeclinationSpacing->SetValue(m_DeclinationMap.m_Spacing);
940 dialog->m_cbInclination->SetValue(m_InclinationMap.m_bEnabled);
941 dialog->m_scInclinationSpacing->SetValue(m_InclinationMap.m_Spacing);
942 dialog->m_cbFieldStrength->SetValue(m_FieldStrengthMap.m_bEnabled);
943 dialog->m_scFieldStrengthSpacing->SetValue(m_FieldStrengthMap.m_Spacing);
945 dialog->m_sStep->SetValue(m_MapStep);
946 dialog->m_sPoleAccuracy->SetValue(m_MapPoleAccuracy);
947
948 if (dialog->ShowModal() == wxID_OK) {
949 m_DeclinationMap.m_bEnabled = dialog->m_cbDeclination->GetValue();
950 m_DeclinationMap.m_Spacing = dialog->m_scDeclinationSpacing->GetValue();
951 m_InclinationMap.m_bEnabled = dialog->m_cbInclination->GetValue();
952 m_InclinationMap.m_Spacing = dialog->m_scInclinationSpacing->GetValue();
953 m_FieldStrengthMap.m_bEnabled = dialog->m_cbFieldStrength->GetValue();
954 m_FieldStrengthMap.m_Spacing = dialog->m_scFieldStrengthSpacing->GetValue();
956 m_MapStep = dialog->m_sStep->GetValue();
957 m_MapPoleAccuracy = dialog->m_sPoleAccuracy->GetValue();
958 m_DeclinationMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
959 m_InclinationMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
960 m_FieldStrengthMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
961
962 m_bCachedPlotOk = false;
963 if (m_pWmmDialog->m_cbEnablePlot->GetValue()) RecomputePlot();
964
965 RequestRefresh(m_parent_window);
966 RearrangeWindow();
967
968 SaveConfig();
969 }
970 delete dialog;
971}
972
973void wmm_pi::SendBoatVarHVD(double d_var) {
974 // We use the HVD NMEA sentence to send magnetic variation.
975 // The user can then select the desired variation
976 // via the priority of the source code. The not official Talker: WM
977 // is used to print source: WMM plugin in the Priority list.
978 wxString s_dir = d_var >= 0 ? "E" : "W";
979 d_var = fabs(d_var); // Make it positive for NMEA sentence
980 wxString S = "$WMHVD";
981 S.Append(","); // 1 Var degrees
982 S.Append(wxString::Format("%.1f", d_var));
983 S.Append(","); // 2 Var Dir
984 S.Append(s_dir); // E/W
985 S.Append("*");
986 S.Append(wxString::Format("%02X", ComputeChecksum(S)));
987 S += "\r\n";
988
990}
991
992void wmm_pi::SendPGN127258(double d_var) {
993 // Send Magnetic Variation as PGN 127258 Magnetic Variation
994 double var_rad = d_var * (M_PI / 180.0);
995 // Calculate the number of days since the Unix epoch
996 time_t now = time(nullptr);
997 int days_since_epoch = now / (60 * 60 * 24);
998 tN2kMsg msg127285;
999 SetN2kPGN127258(msg127285, 0xFF, tN2kMagneticVariation::N2kmagvar_WMM2025,
1000 days_since_epoch, var_rad);
1001 std::shared_ptr<std::vector<uint8_t>> payload(new std::vector<uint8_t>(
1002 msg127285.Data, msg127285.Data + msg127285.DataLen));
1003 WriteCommDriverN2K(m_handleN2k, 127258, 0xFF, 7, payload);
1004}
1005
1006unsigned char wmm_pi::ComputeChecksum(wxString sentence) const {
1007 unsigned char calculated_checksum = 0;
1008 for (wxString::const_iterator i = sentence.begin() + 1;
1009 i != sentence.end() && *i != '*'; ++i)
1010 calculated_checksum ^= static_cast<unsigned char>(*i);
1011
1012 return (calculated_checksum);
1013}
Basic position fix information.
double Lat
Latitude in decimal degrees.
double Lon
Longitude in decimal degrees.
Contains view parameters and status information for a chart display viewport.
Class WmmPrefsDialog.
Base class for OpenCPN plugins.
void OnToolbarToolCallback(int id)
Handles toolbar tool clicks.
Definition wmm_pi.cpp:383
int GetAPIVersionMajor()
Returns the major version number of the plugin API that this plugin supports.
Definition wmm_pi.cpp:290
void ShowPlotSettings()
Definition wmm_pi.cpp:931
wxString GetCommonName()
Get the plugin's common (short) name.
Definition wmm_pi.cpp:300
void SetColorScheme(PI_ColorScheme cs)
Updates plugin color scheme.
Definition wmm_pi.cpp:320
int GetToolbarToolCount(void)
Returns the number of toolbar tools this plugin provides.
Definition wmm_pi.cpp:318
void SetPositionFix(PlugIn_Position_Fix &pfix)
Updates plugin with current position fix data at regular intervals.
Definition wmm_pi.cpp:548
bool DeInit(void)
Clean up plugin resources.
Definition wmm_pi.cpp:256
void ShowPreferencesDialog(wxWindow *parent)
Shows the plugin preferences dialog.
Definition wmm_pi.cpp:901
void SetCursorLatLon(double lat, double lon)
Receives cursor lat/lon position updates.
Definition wmm_pi.cpp:491
int Init(void)
Initialize the plugin and declare its capabilities.
Definition wmm_pi.cpp:133
wxString GetShortDescription()
Get a brief description of the plugin.
Definition wmm_pi.cpp:302
int GetPlugInVersionMinor()
Returns the minor version number of the plugin itself.
Definition wmm_pi.cpp:296
wxString GetLongDescription()
Get detailed plugin information.
Definition wmm_pi.cpp:306
wxBitmap * GetPlugInBitmap()
Get the plugin's icon bitmap.
Definition wmm_pi.cpp:298
int GetAPIVersionMinor()
Returns the minor version number of the plugin API that this plugin supports.
Definition wmm_pi.cpp:292
int GetPlugInVersionMajor()
Returns the major version number of the plugin itself.
Definition wmm_pi.cpp:294
bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in OpenGL mode for single canvas.
Definition wmm_pi.cpp:435
The JSON parser.
Definition jsonreader.h:50
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
Definition jsonval.h:84
double AsDouble() const
Return the stored value as a double.
Definition jsonval.cpp:827
int AsInt() const
Return the stored value as an integer.
Definition jsonval.cpp:789
The JSON document writer.
Definition jsonwriter.h:50
void Write(const wxJSONValue &value, wxString &str)
Write the JSONvalue object to a JSON text.
CommDriverResult
Error return values
#define WANTS_NMEA_EVENTS
Receive decoded NMEA events with parsed data.
PI_ColorScheme
Color schemes for different lighting conditions.
#define WANTS_PREFERENCES
Plugin will add page(s) to global preferences dialog.
#define WANTS_CONFIG
Plugin requires persistent configuration storage.
#define WANTS_PLUGIN_MESSAGING
Enable message passing between plugins.
#define INSTALLS_TOOLBAR_TOOL
Plugin will add one or more toolbar buttons.
#define WANTS_CURSOR_LATLON
Receive updates when cursor moves over chart.
Definition ocpn_plugin.h:93
#define WANTS_TOOLBAR_CALLBACK
Receive notification when user left-clicks plugin's toolbar buttons.
#define WANTS_OVERLAY_CALLBACK
Receive callbacks to render custom overlay graphics on the chart.
Definition ocpn_plugin.h:89
void RemovePlugInTool(int tool_id)
Removes a tool from OpenCPN's toolbar.
wxWindow * GetOCPNCanvasWindow()
Gets OpenCPN's main canvas window.
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
wxFileConfig * GetOCPNConfigObject()
Gets OpenCPN's configuration object.
wxBitmap GetBitmapFromSVGFile(wxString filename, unsigned int width, unsigned int height)
Creates bitmap from SVG file.
int InsertPlugInTool(wxString label, wxBitmap *bitmap, wxBitmap *bmpRollover, wxItemKind kind, wxString shortHelp, wxString longHelp, wxObject *clientData, int position, int tool_sel, opencpn_plugin *pplugin)
Adds a tool to OpenCPN's toolbar.
void SetToolbarToolBitmaps(int item, wxBitmap *bitmap, wxBitmap *bmpRollover)
Updates toolbar tool bitmaps.
wxString * GetpSharedDataLocation()
Gets shared application data location.
void DimeWindow(wxWindow *win)
Applies system color scheme to window.
double GetOCPNGUIToolScaleFactor_PlugIn()
Gets current global GUI scaling factor.
void SetToolbarToolBitmapsSVG(int item, wxString SVGfile, wxString SVGfileRollover, wxString SVGfileToggled)
Updates SVG graphics for toolbar tool.
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.
void PushNMEABuffer(wxString buf)
Pushes NMEA sentence to the system.
void SendPluginMessage(wxString message_id, wxString message_body)
Sends message to other plugins.
void RequestRefresh(wxWindow *win)
Requests window refresh.
bool AddLocaleCatalog(wxString catalog)
Adds a locale catalog for translations.
CommDriverResult WriteCommDriverN2K(DriverHandle handle, int PGN, int destinationCANAddress, int priority, const std::shared_ptr< std::vector< uint8_t > > &payload)
Send a PGN message to an NMEA2000 address.
std::vector< DriverHandle > GetActiveDrivers()
Comm port plugin TX support methods
const std::unordered_map< std::string, std::string > GetAttributes(DriverHandle handle)
Query a specific driver for attributes.
CommDriverResult RegisterTXPGNs(DriverHandle handle, std::vector< int > &pgn_list)
Register PGNs that this application intends to transmit for some NMEA 2000 adapters like Actisense NG...