35#ifndef __OCPN__ANDROID__
40#include "GL/gl_private.h"
46float g_piGLMinSymbolLineWidth = 0.9;
48void WMMLogMessage1(wxString s) { wxLogMessage(_T(
"WMM: ") + s); }
49extern "C" void WMMLogMessage(
const char *s) {
50 WMMLogMessage1(wxString::FromAscii(s));
61extern "C" DECL_EXP
void destroy_pi(
opencpn_plugin *p) {
delete p; }
76#include <N2kMessages.h>
78void WmmUIDialog::EnablePlotChanged(wxCommandEvent &event) {
79 if (m_cbEnablePlot->GetValue()) m_wmm_pi.RecomputePlot();
80 m_wmm_pi.SetShowPlot(m_cbEnablePlot->GetValue());
84void WmmUIDialog::PlotSettings(wxCommandEvent &event) {
88void WmmPlotSettingsDialog::About(wxCommandEvent &event) {
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\
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."));
106 wxMessageDialog dlg(
this, msg0, _(
"WMM Plugin"), wxOK);
117wmm_pi::wmm_pi(
void *ppimgr)
120 m_DeclinationMap(DECLINATION_PLOT, MagneticModel, TimedMagneticModel,
122 m_InclinationMap(INCLINATION_PLOT, MagneticModel, TimedMagneticModel,
124 m_FieldStrengthMap(FIELD_STRENGTH_PLOT, MagneticModel, TimedMagneticModel,
126 m_bComputingPlot(false) {
140 MagneticModel = NULL;
141 TimedMagneticModel = NULL;
143 ::wxDisplaySize(&m_display_width, &m_display_height);
155#ifdef __OCPN__ANDROID__
157 m_bShowPlotOptions =
false;
163 m_LastVal = wxEmptyString;
170 wxFileName::GetPathSeparator() + _T(
"wmm_pi") +
171 wxFileName::GetPathSeparator() + _T(
"data") +
172 wxFileName::GetPathSeparator();
177 int NumTerms, epochs = 1, nMax = 0;
178 wxString cof_filename = m_shareLocn +
"WMM.COF";
180 if (!MAG_robustReadMagModels(
181 const_cast<char *
>((
const char *)cof_filename.mb_str()),
183 WMMLogMessage1(_T(
"initialization error"));
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;
193 NumTerms = ((nMax + 1) * (nMax + 2) / 2);
195 TimedMagneticModel = MAG_AllocateModelMemory(
198 for (
int i = 0; i < epochs; i++) {
199 if (MagneticModels[i] == NULL || TimedMagneticModel == NULL) {
200 WMMLogMessage1(_T(
"initialization error MAG_Error(2)"));
205 MagneticModel = MagneticModels[0];
207 MAG_SetDefaults(&Ellip, &Geoid);
211 Geoid.GeoidHeightBuffer = GeoidHeightBuffer;
212 Geoid.Geoid_Initialized = 1;
216 bool found_handle =
false;
219 if (attributes.find(
"protocol") == attributes.end())
continue;
221 wxString::Format(
"handle proto %s", attributes.at(
"protocol")));
222 if (attributes.at(
"protocol") ==
"nmea2000") {
223 m_handleN2k = handle;
229 WMMLogMessage1(
"nmea2000 handle not found");
231 std::vector<int> pgn_list = {127258};
241 m_leftclick_tool_id =
243 _T(
""), NULL, WMM_TOOL_POSITION, 0,
this);
258 if (NULL != m_pWmmDialog) {
259 wxPoint p = m_pWmmDialog->GetPosition();
263 m_pWmmDialog->Close();
269 MAG_FreeMagneticModelMemory(MagneticModel);
271 if (TimedMagneticModel) {
272 MAG_FreeMagneticModelMemory(TimedMagneticModel);
285 if (m_oDC)
delete m_oDC;
303 return _(
"World Magnetic Model PlugIn for OpenCPN");
308 "World Magnetic Model PlugIn for OpenCPN\n\
309Implements the NOAA World Magnetic Model\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.");
321 if (NULL == m_pWmmDialog)
return;
325void wmm_pi::SetIconType() {
326 if (m_bShowLiveIcon) {
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");
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);
346 m_pWmmDialog->sbScursor->Show(m_pWmmDialog->gScursor,
true,
true);
347 m_pWmmDialog->sbSboat->Show(m_pWmmDialog->gSboat,
true,
true);
350 m_pWmmDialog->m_cbEnablePlot->Show(m_bShowPlotOptions);
351 m_pWmmDialog->m_bPlotSettings->Show(m_bShowPlotOptions);
353 if (!m_bShowAtCursor) {
354 m_pWmmDialog->bSframe->Hide(m_pWmmDialog->sbScursor,
true);
356 m_pWmmDialog->bSframe->Show(m_pWmmDialog->sbScursor,
true,
true);
357 if (m_iViewType == 1)
358 m_pWmmDialog->sbScursor->Hide(m_pWmmDialog->gScursor,
true);
369 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
372 pConf->SetPath(_T(
"/Settings"));
373 pConf->Read(_T(
"OpenGL"), &gl,
false);
376 if (!(gl && wxPlatformInfo::Get().GetOSMajorVersion() == 5 &&
377 wxPlatformInfo::Get().GetOSMinorVersion() == 1))
379 if (m_pWmmDialog->CanSetTransparent())
380 m_pWmmDialog->SetTransparent(m_iOpacity);
384 if (!m_buseable)
return;
385 if (NULL == m_pWmmDialog) {
386 m_pWmmDialog =
new WmmUIDialog(*
this, m_parent_window);
388 m_pWmmDialog->SetFont(*pFont);
390 m_pWmmDialog->Move(wxPoint(m_wmm_dialog_x, m_wmm_dialog_y));
396 m_pWmmDialog->Show(!m_pWmmDialog->IsShown());
397 m_pWmmDialog->Layout();
399 if (m_pWmmDialog->IsShown())
404 wxPoint p = m_pWmmDialog->GetPosition();
405 m_pWmmDialog->Move(0, 0);
406 m_pWmmDialog->Move(p);
408#ifdef __OCPN__ANDROID__
409 m_pWmmDialog->CentreOnScreen();
410 m_pWmmDialog->Move(-1, 0);
415 if (!m_bShowPlot)
return;
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));
423 if (!m_bShowPlot)
return true;
430 RenderOverlayBoth(m_oDC, vp);
436 if (!m_bShowPlot)
return true;
442#ifndef USE_ANDROID_GLES2
443 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
445 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
447 g_piGLMinSymbolLineWidth = wxMax(parms[0], 1);
455#ifndef USE_ANDROID_GLES2
456 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LINE_BIT | GL_ENABLE_BIT |
457 GL_POLYGON_BIT | GL_HINT_BIT);
459 glEnable(GL_LINE_SMOOTH);
461 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
462 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
465 RenderOverlayBoth(m_oDC, vp);
467#ifndef USE_ANDROID_GLES2
474void wmm_pi::RecomputePlot() {
475 if (m_bCachedPlotOk)
return;
477 if (m_bComputingPlot)
return;
478 m_bComputingPlot =
true;
480 if (!m_DeclinationMap.Recompute(m_MapDate) ||
481 !m_InclinationMap.Recompute(m_MapDate) ||
482 !m_FieldStrengthMap.Recompute(m_MapDate)) {
484 if (m_pWmmDialog) m_pWmmDialog->m_cbEnablePlot->SetValue(
false);
486 m_bCachedPlotOk =
true;
488 m_bComputingPlot =
false;
492 if (!m_pWmmDialog)
return;
494 if (!m_bShowAtCursor)
496 if (lat < -90 || lat > 90 || lon < -180 || lon > 180 ||
497 NULL == m_pWmmDialog || !m_pWmmDialog->IsShown())
500 m_pWmmDialog->m_tbD->SetValue(_(
"Error, see log."));
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();
510 wxDateTime::GetCurrentMonth() + 1;
511 UserDate.Day = wxDateTime::Now().GetDay();
513 MAG_DateToYear(&UserDate, err);
514 MAG_GeodeticToSpherical(
515 Ellip, CoordGeodetic,
518 MAG_TimelyModifyMagneticModel(
519 UserDate, MagneticModel,
522 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel,
523 &GeoMagneticElements);
525 MAG_CalculateGridVariation(CoordGeodetic, &GeoMagneticElements);
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));
544 m_cursorVariation = GeoMagneticElements;
545 SendCursorVariation();
552 CoordGeodetic.lambda = pfix.
Lon;
553 CoordGeodetic.phi = pfix.
Lat;
554 CoordGeodetic.HeightAboveEllipsoid = 0;
555 CoordGeodetic.UseGeoid = 0;
556 UserDate.Year = wxDateTime::GetCurrentYear();
558 wxDateTime::GetCurrentMonth() + 1;
559 UserDate.Day = wxDateTime::Now().GetDay();
561 MAG_DateToYear(&UserDate, err);
562 MAG_GeodeticToSpherical(
563 Ellip, CoordGeodetic,
566 MAG_TimelyModifyMagneticModel(
567 UserDate, MagneticModel,
570 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel,
571 &GeoMagneticElements);
573 MAG_CalculateGridVariation(CoordGeodetic, &GeoMagneticElements);
577 m_boatVariation = GeoMagneticElements;
580 wxString NewVal = wxString::Format(_T(
"%.1f"), GeoMagneticElements.Decl);
588 if (m_bShowIcon && m_bShowLiveIcon &&
589 ((m_LastVal != NewVal) || (
scale != m_scale))) {
592 int w = _img_wmm_live->GetWidth() *
scale;
593 int h = _img_wmm_live->GetHeight() *
scale;
601 icon = wxBitmap(_img_wmm_live->GetWidth(), _img_wmm_live->GetHeight());
602 dc.SelectObject(icon);
603 dc.DrawBitmap(*_img_wmm_live, 0, 0,
true);
605 icon = wxBitmap(w, h);
606 dc.SelectObject(icon);
608 dc.SetBackground(*wxTRANSPARENT_BRUSH);
611 dc.DrawBitmap(live, 0, 0,
true);
615 GetGlobalColor(_T(
"CHWHT"), &cf);
616 dc.SetTextForeground(cf);
617 if (pFontSmall->IsOk()) {
619 int point_size = wxMax(10, 10 *
scale);
620 pFontSmall->SetPointSize(point_size);
626 sdc.GetTextExtent(NewVal, &w, NULL, NULL, NULL, pFontSmall);
628 while ((w > (icon.GetWidth() * 8 / 10)) && (point_size >= 8)) {
630 pFontSmall->SetPointSize(point_size);
631 sdc.GetTextExtent(NewVal, &w, NULL, NULL, NULL, pFontSmall);
634 dc.SetFont(*pFontSmall);
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);
645 wxImage imo = live.ConvertToImage();
646 wxImage im = icon.ConvertToImage();
648 if (!imo.HasAlpha()) imo.InitAlpha();
649 if (!im.HasAlpha()) im.InitAlpha();
651 unsigned char *alive = imo.GetAlpha();
652 unsigned char *target = im.GetAlpha();
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];
666 if (NULL == m_pWmmDialog || !m_pWmmDialog->IsShown())
return;
668 m_pWmmDialog->m_tbD->SetValue(_(
"Error, see log."));
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));
689void wmm_pi::SetPluginMessage(wxString &message_id, wxString &message_body) {
690 if (message_id == _T(
"WMM_VARIATION_REQUEST")) {
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")) {
702 }
else if (message_id == _T(
"WMM_VARIATION_CURSOR_REQUEST")) {
703 SendCursorVariation();
707void wmm_pi::SendVariationAt(
double lat,
double lon,
int year,
int month,
712 v[_T(
"Year")] = year;
713 v[_T(
"Month")] = month;
715 CoordGeodetic.lambda = lon;
716 CoordGeodetic.phi = lat;
717 CoordGeodetic.HeightAboveEllipsoid = 0;
718 CoordGeodetic.UseGeoid = 0;
719 UserDate.Year = year;
720 UserDate.Month = month;
723 MAG_DateToYear(&UserDate, err);
724 MAG_GeodeticToSpherical(
725 Ellip, CoordGeodetic,
728 MAG_TimelyModifyMagneticModel(
729 UserDate, MagneticModel,
732 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel,
733 &GeoMagneticElements);
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;
758void wmm_pi::SendBoatVariation() {
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;
781 SendBoatVarHVD(m_boatVariation.Decl);
782 SendPGN127258(m_boatVariation.Decl);
785void wmm_pi::SendCursorVariation() {
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;
809wxString wmm_pi::AngleToText(
double angle) {
810 int deg = (int)fabs(angle);
811 int min = (fabs(angle) - deg) * 60;
813 return wxString::Format(_T(
"%u%c%u' W"), deg, 0x00B0, min);
815 return wxString::Format(_T(
"%u%c%u' E"), deg, 0x00B0, min);
818bool wmm_pi::LoadConfig(
void) {
819 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
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);
830 m_wmm_dialog_x = pConf->Read(_T (
"DialogPosX" ), 20L);
831 m_wmm_dialog_y = pConf->Read(_T (
"DialogPosY" ), 20L);
833 if ((m_wmm_dialog_x < 0) || (m_wmm_dialog_x > m_display_width))
835 if ((m_wmm_dialog_y < 0) || (m_wmm_dialog_y > m_display_height))
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,
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);
853 m_MapDate = wxDateTime::Now();
855 m_bCachedPlotOk =
false;
857 pConf->SetPath(_T (
"/Directories" ));
858 wxString s = wxFileName::GetPathSeparator();
860 _T(
"wmm_pi") + s + _T(
"data") + s;
868bool wmm_pi::SaveConfig(
void) {
869 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
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);
880 pConf->Write(_T (
"DialogPosX" ), m_wmm_dialog_x);
881 pConf->Write(_T (
"DialogPosY" ), m_wmm_dialog_y);
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);
893 pConf->SetPath(_T (
"/Directories" ));
894 pConf->Write(_T (
"WMMDataLocation" ), m_wmm_dir);
904 wxPoint(m_wmm_dialog_x, m_wmm_dialog_y), wxDefaultSize,
905 wxDEFAULT_DIALOG_STYLE);
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);
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();
934 dialog->SetFont(*pFont);
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);
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);
962 m_bCachedPlotOk =
false;
963 if (m_pWmmDialog->m_cbEnablePlot->GetValue()) RecomputePlot();
973void wmm_pi::SendBoatVarHVD(
double d_var) {
978 wxString s_dir = d_var >= 0 ?
"E" :
"W";
980 wxString S =
"$WMHVD";
982 S.Append(wxString::Format(
"%.1f", d_var));
986 S.Append(wxString::Format(
"%02X", ComputeChecksum(S)));
992void wmm_pi::SendPGN127258(
double d_var) {
994 double var_rad = d_var * (M_PI / 180.0);
996 time_t now = time(
nullptr);
997 int days_since_epoch = now / (60 * 60 * 24);
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));
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);
1012 return (calculated_checksum);
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.
Base class for OpenCPN plugins.
void OnToolbarToolCallback(int id)
Handles toolbar tool clicks.
int GetAPIVersionMajor()
Returns the major version number of the plugin API that this plugin supports.
wxString GetCommonName()
Get the plugin's common (short) name.
void SetColorScheme(PI_ColorScheme cs)
Updates plugin color scheme.
int GetToolbarToolCount(void)
Returns the number of toolbar tools this plugin provides.
void SetPositionFix(PlugIn_Position_Fix &pfix)
Updates plugin with current position fix data at regular intervals.
bool DeInit(void)
Clean up plugin resources.
void ShowPreferencesDialog(wxWindow *parent)
Shows the plugin preferences dialog.
void SetCursorLatLon(double lat, double lon)
Receives cursor lat/lon position updates.
int Init(void)
Initialize the plugin and declare its capabilities.
wxString GetShortDescription()
Get a brief description of the plugin.
int GetPlugInVersionMinor()
Returns the minor version number of the plugin itself.
wxString GetLongDescription()
Get detailed plugin information.
wxBitmap * GetPlugInBitmap()
Get the plugin's icon bitmap.
int GetAPIVersionMinor()
Returns the minor version number of the plugin API that this plugin supports.
int GetPlugInVersionMajor()
Returns the major version number of the plugin itself.
bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in OpenGL mode for single canvas.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
double AsDouble() const
Return the stored value as a double.
int AsInt() const
Return the stored value as an integer.
The JSON document writer.
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.
#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.
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...