37#include "GL/gl_private.h"
43float g_piGLMinSymbolLineWidth = 0.9;
45void WMMLogMessage1(wxString s) { wxLogMessage(
"WMM: " + s); }
46extern "C" void WMMLogMessage(
const char *s) {
47 WMMLogMessage1(wxString::FromAscii(s));
53 return new WmmPi(ppimgr);
56extern "C" DECL_EXP
void destroy_pi(
opencpn_plugin *p) {
delete p; }
71#include <N2kMessages.h>
73void WmmUIDialog::EnablePlotChanged(wxCommandEvent &event) {
74 if (m_cbEnablePlot->GetValue()) m_wmm_pi.RecomputePlot();
75 m_wmm_pi.SetShowPlot(m_cbEnablePlot->GetValue());
79void WmmUIDialog::PlotSettings(wxCommandEvent &event) {
83void WmmPlotSettingsDialog::About(wxCommandEvent &event) {
86World Magnetic Model Plotting allows users to cross reference the\
87 magnetic variation values printed on many raster charts.\n\n\
88Variation is the angle between true and magnetic north.\n\
89Inclination or dip, is the vertical angle of the magnetic field.\n\
90\t(+- 90 at the magnetic poles)\n\
91Field Strength is the magnetic field in nano tesla from\n\
93The plotted lines are similar to a topographic map. The \
94space between them can be adjusted; more space takes \
95less time to calculate.\n\n\
96The Step size and Pole accuracy sliders allow a trade off \
97for speed vs computation time.\n\n\
98The World Magnetic Model Plugin was written by Pavel Kalian \
99and extended by Sean D'Epagnier to support plotting."));
101 wxMessageDialog dlg(
this, msg0, _(
"WMM Plugin"), wxOK);
112WmmPi::WmmPi(
void *ppimgr)
115 m_DeclinationMap(DECLINATION_PLOT, MagneticModel, TimedMagneticModel,
117 m_InclinationMap(INCLINATION_PLOT, MagneticModel, TimedMagneticModel,
119 m_FieldStrengthMap(FIELD_STRENGTH_PLOT, MagneticModel, TimedMagneticModel,
121 m_bComputingPlot(false) {
135 MagneticModel = NULL;
136 TimedMagneticModel = NULL;
138 ::wxDisplaySize(&m_display_width, &m_display_height);
152 m_bShowPlotOptions =
false;
158 m_LastVal = wxEmptyString;
165 wxFileName::GetPathSeparator() +
"wmm_pi" +
166 wxFileName::GetPathSeparator() +
"data" +
167 wxFileName::GetPathSeparator();
172 int NumTerms, epochs = 1, nMax = 0;
173 wxString cof_filename = m_shareLocn +
"WMM.COF";
175 if (!MAG_robustReadMagModels(
176 const_cast<char *
>((
const char *)cof_filename.mb_str()),
178 WMMLogMessage1(
"initialization error");
181 WMMLogMessage1(wxString::Format(
"WMM model data loaded from file %s.",
182 cof_filename.c_str()));
183 for (
int i = 0; i < epochs; i++) {
184 if (MagneticModels[i]->nMax > nMax) {
185 nMax = MagneticModels[i]->nMax;
188 NumTerms = ((nMax + 1) * (nMax + 2) / 2);
190 TimedMagneticModel = MAG_AllocateModelMemory(
193 for (
int i = 0; i < epochs; i++) {
194 if (MagneticModels[i] == NULL || TimedMagneticModel == NULL) {
195 WMMLogMessage1(
"initialization error MAG_Error(2)");
200 MagneticModel = MagneticModels[0];
202 MAG_SetDefaults(&Ellip, &Geoid);
206 Geoid.GeoidHeightBuffer = GeoidHeightBuffer;
207 Geoid.Geoid_Initialized = 1;
211 bool found_handle =
false;
214 if (attributes.find(
"protocol") == attributes.end())
continue;
216 wxString::Format(
"handle proto %s", attributes.at(
"protocol")));
217 if (attributes.at(
"protocol") ==
"nmea2000") {
218 m_handleN2k = handle;
224 WMMLogMessage1(
"nmea2000 handle not found");
226 std::vector<int> pgn_list = {127258};
236 m_leftclick_tool_id =
238 NULL, WMM_TOOL_POSITION, 0,
this);
253 if (NULL != m_pWmmDialog) {
254 wxPoint p = m_pWmmDialog->GetPosition();
258 m_pWmmDialog->Close();
264 MAG_FreeMagneticModelMemory(MagneticModel);
266 if (TimedMagneticModel) {
267 MAG_FreeMagneticModelMemory(TimedMagneticModel);
280 if (m_oDC)
delete m_oDC;
298 return _(
"World Magnetic Model PlugIn for OpenCPN");
303 "World Magnetic Model PlugIn for OpenCPN\n\
304Implements the NOAA World Magnetic Model\n\
306https://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml\n\
307The bundled WMM2025 model is valid until late 2029.\n\
308After then, if new version of the plugin will not be released\n\
309in time, get a new WMM.COF from NOAA and place it to the\n\
310location you can find in the OpenCPN logfile.");
316 if (NULL == m_pWmmDialog)
return;
320void WmmPi::SetIconType() {
321 if (m_bShowLiveIcon) {
326 wxString normalIcon = m_shareLocn +
"wmm_pi.svg";
327 wxString toggledIcon = m_shareLocn +
"wmm_pi.svg";
328 wxString rolloverIcon = m_shareLocn +
"wmm_pi.svg";
335void WmmPi::RearrangeWindow() {
336 if (NULL == m_pWmmDialog)
return;
337 if (m_iViewType == 1) {
338 m_pWmmDialog->sbScursor->Hide(m_pWmmDialog->gScursor,
true);
339 m_pWmmDialog->sbSboat->Hide(m_pWmmDialog->gSboat,
true);
341 m_pWmmDialog->sbScursor->Show(m_pWmmDialog->gScursor,
true,
true);
342 m_pWmmDialog->sbSboat->Show(m_pWmmDialog->gSboat,
true,
true);
345 m_pWmmDialog->m_cbEnablePlot->Show(m_bShowPlotOptions);
346 m_pWmmDialog->m_bPlotSettings->Show(m_bShowPlotOptions);
348 if (!m_bShowAtCursor) {
349 m_pWmmDialog->bSframe->Hide(m_pWmmDialog->sbScursor,
true);
351 m_pWmmDialog->bSframe->Show(m_pWmmDialog->sbScursor,
true,
true);
352 if (m_iViewType == 1)
353 m_pWmmDialog->sbScursor->Hide(m_pWmmDialog->gScursor,
true);
364 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
367 pConf->SetPath(
"/Settings");
368 pConf->Read(
"OpenGL", &gl,
false);
371 if (!(gl && wxPlatformInfo::Get().GetOSMajorVersion() == 5 &&
372 wxPlatformInfo::Get().GetOSMinorVersion() == 1))
374 if (m_pWmmDialog->CanSetTransparent())
375 m_pWmmDialog->SetTransparent(m_iOpacity);
379 if (!m_buseable)
return;
380 if (NULL == m_pWmmDialog) {
381 m_pWmmDialog =
new WmmUIDialog(*
this, m_parent_window);
383 m_pWmmDialog->SetFont(*pFont);
385 m_pWmmDialog->Move(wxPoint(m_wmm_dialog_x, m_wmm_dialog_y));
391 m_pWmmDialog->Show(!m_pWmmDialog->IsShown());
392 m_pWmmDialog->Layout();
394 if (m_pWmmDialog->IsShown())
399 wxPoint p = m_pWmmDialog->GetPosition();
400 m_pWmmDialog->Move(0, 0);
401 m_pWmmDialog->Move(p);
404 m_pWmmDialog->CentreOnScreen();
405 m_pWmmDialog->Move(-1, 0);
410 if (!m_bShowPlot)
return;
412 m_DeclinationMap.Plot(dc, vp, wxColour(255, 0, 90, 220));
413 m_InclinationMap.Plot(dc, vp, wxColour(60, 255, 30, 220));
414 m_FieldStrengthMap.Plot(dc, vp, wxColour(0, 60, 255, 220));
418 if (!m_bShowPlot)
return true;
425 RenderOverlayBoth(m_oDC, vp);
431 if (!m_bShowPlot)
return true;
437#ifndef USE_ANDROID_GLES2
438 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
440 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
442 g_piGLMinSymbolLineWidth = wxMax(parms[0], 1);
450#ifndef USE_ANDROID_GLES2
451 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LINE_BIT | GL_ENABLE_BIT |
452 GL_POLYGON_BIT | GL_HINT_BIT);
454 glEnable(GL_LINE_SMOOTH);
456 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
457 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
460 RenderOverlayBoth(m_oDC, vp);
462#ifndef USE_ANDROID_GLES2
469void WmmPi::RecomputePlot() {
470 if (m_bCachedPlotOk)
return;
472 if (m_bComputingPlot)
return;
473 m_bComputingPlot =
true;
475 if (!m_DeclinationMap.Recompute(m_MapDate) ||
476 !m_InclinationMap.Recompute(m_MapDate) ||
477 !m_FieldStrengthMap.Recompute(m_MapDate)) {
479 if (m_pWmmDialog) m_pWmmDialog->m_cbEnablePlot->SetValue(
false);
481 m_bCachedPlotOk =
true;
483 m_bComputingPlot =
false;
487 if (!m_pWmmDialog)
return;
489 if (!m_bShowAtCursor)
491 if (lat < -90 || lat > 90 || lon < -180 || lon > 180 ||
492 NULL == m_pWmmDialog || !m_pWmmDialog->IsShown())
495 m_pWmmDialog->m_tbD->SetValue(_(
"Error, see log."));
498 CoordGeodetic.lambda = lon;
499 CoordGeodetic.phi = lat;
500 CoordGeodetic.HeightAboveEllipsoid = 0;
501 CoordGeodetic.HeightAboveGeoid = 0;
502 CoordGeodetic.UseGeoid = 0;
503 UserDate.Year = wxDateTime::GetCurrentYear();
505 wxDateTime::GetCurrentMonth() + 1;
506 UserDate.Day = wxDateTime::Now().GetDay();
508 MAG_DateToYear(&UserDate, err);
509 MAG_GeodeticToSpherical(
510 Ellip, CoordGeodetic,
513 MAG_TimelyModifyMagneticModel(
514 UserDate, MagneticModel,
517 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel,
518 &GeoMagneticElements);
520 MAG_CalculateGridVariation(CoordGeodetic, &GeoMagneticElements);
523 m_pWmmDialog->m_tcF->SetValue(
524 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.F));
525 m_pWmmDialog->m_tcH->SetValue(
526 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.H));
527 m_pWmmDialog->m_tcX->SetValue(
528 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.X));
529 m_pWmmDialog->m_tcY->SetValue(
530 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.Y));
531 m_pWmmDialog->m_tcZ->SetValue(
532 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.Z));
533 m_pWmmDialog->m_tcD->SetValue(
534 wxString::Format(
"%-5.1lf%c (%s)", GeoMagneticElements.Decl, 0x00B0,
535 AngleToText(GeoMagneticElements.Decl).c_str()));
536 m_pWmmDialog->m_tcI->SetValue(
537 wxString::Format(
"%-5.1lf%c", GeoMagneticElements.Incl, 0x00B0));
539 m_cursorVariation = GeoMagneticElements;
540 SendCursorVariation();
547 CoordGeodetic.lambda = pfix.
Lon;
548 CoordGeodetic.phi = pfix.
Lat;
549 CoordGeodetic.HeightAboveEllipsoid = 0;
550 CoordGeodetic.UseGeoid = 0;
551 UserDate.Year = wxDateTime::GetCurrentYear();
553 wxDateTime::GetCurrentMonth() + 1;
554 UserDate.Day = wxDateTime::Now().GetDay();
556 MAG_DateToYear(&UserDate, err);
557 MAG_GeodeticToSpherical(
558 Ellip, CoordGeodetic,
561 MAG_TimelyModifyMagneticModel(
562 UserDate, MagneticModel,
565 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel,
566 &GeoMagneticElements);
568 MAG_CalculateGridVariation(CoordGeodetic, &GeoMagneticElements);
572 m_boatVariation = GeoMagneticElements;
575 wxString NewVal = wxString::Format(
"%.1f", GeoMagneticElements.Decl);
583 if (m_bShowIcon && m_bShowLiveIcon &&
584 ((m_LastVal != NewVal) || (
scale != m_scale))) {
587 int w = _img_wmm_live->GetWidth() *
scale;
588 int h = _img_wmm_live->GetHeight() *
scale;
595 icon = wxBitmap(_img_wmm_live->GetWidth(), _img_wmm_live->GetHeight());
596 dc.SelectObject(icon);
597 dc.DrawBitmap(*_img_wmm_live, 0, 0,
true);
599 icon = wxBitmap(w, h);
600 dc.SelectObject(icon);
602 dc.SetBackground(*wxTRANSPARENT_BRUSH);
605 dc.DrawBitmap(live, 0, 0,
true);
609 GetGlobalColor(
"CHWHT", &cf);
610 dc.SetTextForeground(cf);
611 if (pFontSmall->IsOk()) {
613 int point_size = wxMax(10, 10 *
scale);
614 pFontSmall->SetPointSize(point_size);
620 sdc.GetTextExtent(NewVal, &w, NULL, NULL, NULL, pFontSmall);
622 while ((w > (icon.GetWidth() * 8 / 10)) && (point_size >= 8)) {
624 pFontSmall->SetPointSize(point_size);
625 sdc.GetTextExtent(NewVal, &w, NULL, NULL, NULL, pFontSmall);
628 dc.SetFont(*pFontSmall);
630 wxSize s = dc.GetTextExtent(NewVal);
631 dc.DrawText(NewVal, (icon.GetWidth() - s.GetWidth()) / 2,
632 (icon.GetHeight() - s.GetHeight()) / 2);
633 dc.SelectObject(wxNullBitmap);
639 wxImage imo = live.ConvertToImage();
640 wxImage im = icon.ConvertToImage();
642 if (!imo.HasAlpha()) imo.InitAlpha();
643 if (!im.HasAlpha()) im.InitAlpha();
645 unsigned char *alive = imo.GetAlpha();
646 unsigned char *target = im.GetAlpha();
648 for (
int i = 0; i < h; i++) {
649 for (
int j = 0; j < w; j++) {
650 int index = (i * w) + j;
651 target[index] = alive[index];
660 if (NULL == m_pWmmDialog || !m_pWmmDialog->IsShown())
return;
662 m_pWmmDialog->m_tbD->SetValue(_(
"Error, see log."));
665 m_pWmmDialog->m_tbF->SetValue(
666 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.F));
667 m_pWmmDialog->m_tbH->SetValue(
668 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.H));
669 m_pWmmDialog->m_tbX->SetValue(
670 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.X));
671 m_pWmmDialog->m_tbY->SetValue(
672 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.Y));
673 m_pWmmDialog->m_tbZ->SetValue(
674 wxString::Format(
"%-9.1lf nT", GeoMagneticElements.Z));
675 m_pWmmDialog->m_tbD->SetValue(
676 wxString::Format(
"%-5.1lf%c (%s)", GeoMagneticElements.Decl, 0x00B0,
677 AngleToText(GeoMagneticElements.Decl).c_str()));
678 m_pWmmDialog->m_tbI->SetValue(
679 wxString::Format(
"%-5.1lf%c", GeoMagneticElements.Incl, 0x00B0));
683void WmmPi::SetPluginMessage(wxString &message_id, wxString &message_body) {
684 if (message_id ==
"WMM_VARIATION_REQUEST") {
687 r.
Parse(message_body, &v);
690 int year = v[
"Year"].
AsInt();
691 int month = v[
"Month"].
AsInt();
692 int day = v[
"Day"].
AsInt();
693 SendVariationAt(lat, lon, year, month, day);
694 }
else if (message_id ==
"WMM_VARIATION_BOAT_REQUEST") {
696 }
else if (message_id ==
"WMM_VARIATION_CURSOR_REQUEST") {
697 SendCursorVariation();
701void WmmPi::SendVariationAt(
double lat,
double lon,
int year,
int month,
709 CoordGeodetic.lambda = lon;
710 CoordGeodetic.phi = lat;
711 CoordGeodetic.HeightAboveEllipsoid = 0;
712 CoordGeodetic.UseGeoid = 0;
713 UserDate.Year = year;
714 UserDate.Month = month;
717 MAG_DateToYear(&UserDate, err);
718 MAG_GeodeticToSpherical(
719 Ellip, CoordGeodetic,
722 MAG_TimelyModifyMagneticModel(
723 UserDate, MagneticModel,
726 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel,
727 &GeoMagneticElements);
729 MAG_CalculateGridVariation(CoordGeodetic, &GeoMagneticElements);
730 v[
"Decl"] = GeoMagneticElements.Decl;
731 v[
"Decldot"] = GeoMagneticElements.Decldot;
732 v[
"F"] = GeoMagneticElements.F;
733 v[
"Fdot"] = GeoMagneticElements.Fdot;
734 v[
"GV"] = GeoMagneticElements.GV;
735 v[
"GVdot"] = GeoMagneticElements.GVdot;
736 v[
"H"] = GeoMagneticElements.H;
737 v[
"Hdot"] = GeoMagneticElements.Hdot;
738 v[
"Incl"] = GeoMagneticElements.Incl;
739 v[
"Incldot"] = GeoMagneticElements.Incldot;
740 v[
"X"] = GeoMagneticElements.X;
741 v[
"Xdot"] = GeoMagneticElements.Xdot;
742 v[
"Y"] = GeoMagneticElements.Y;
743 v[
"Ydot"] = GeoMagneticElements.Ydot;
744 v[
"Z"] = GeoMagneticElements.Z;
745 v[
"Zdot"] = GeoMagneticElements.Zdot;
752void WmmPi::SendBoatVariation() {
754 v[
"Decl"] = m_boatVariation.Decl;
755 v[
"Decldot"] = m_boatVariation.Decldot;
756 v[
"F"] = m_boatVariation.F;
757 v[
"Fdot"] = m_boatVariation.Fdot;
758 v[
"GV"] = m_boatVariation.GV;
759 v[
"GVdot"] = m_boatVariation.GVdot;
760 v[
"H"] = m_boatVariation.H;
761 v[
"Hdot"] = m_boatVariation.Hdot;
762 v[
"Incl"] = m_boatVariation.Incl;
763 v[
"Incldot"] = m_boatVariation.Incldot;
764 v[
"X"] = m_boatVariation.X;
765 v[
"Xdot"] = m_boatVariation.Xdot;
766 v[
"Y"] = m_boatVariation.Y;
767 v[
"Ydot"] = m_boatVariation.Ydot;
768 v[
"Z"] = m_boatVariation.Z;
769 v[
"Zdot"] = m_boatVariation.Zdot;
775 SendBoatVarHVD(m_boatVariation.Decl);
776 SendPGN127258(m_boatVariation.Decl);
779void WmmPi::SendCursorVariation() {
781 v[
"Decl"] = m_cursorVariation.Decl;
782 v[
"Decldot"] = m_cursorVariation.Decldot;
783 v[
"F"] = m_cursorVariation.F;
784 v[
"Fdot"] = m_cursorVariation.Fdot;
785 v[
"GV"] = m_cursorVariation.GV;
786 v[
"GVdot"] = m_cursorVariation.GVdot;
787 v[
"H"] = m_cursorVariation.H;
788 v[
"Hdot"] = m_cursorVariation.Hdot;
789 v[
"Incl"] = m_cursorVariation.Incl;
790 v[
"Incldot"] = m_cursorVariation.Incldot;
791 v[
"X"] = m_cursorVariation.X;
792 v[
"Xdot"] = m_cursorVariation.Xdot;
793 v[
"Y"] = m_cursorVariation.Y;
794 v[
"Ydot"] = m_cursorVariation.Ydot;
795 v[
"Z"] = m_cursorVariation.Z;
796 v[
"Zdot"] = m_cursorVariation.Zdot;
803wxString WmmPi::AngleToText(
double angle) {
804 int deg = (int)fabs(angle);
805 int min = (fabs(angle) - deg) * 60;
807 return wxString::Format(
"%u%c%u' W", deg, 0x00B0, min);
809 return wxString::Format(
"%u%c%u' E", deg, 0x00B0, min);
812bool WmmPi::LoadConfig(
void) {
813 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
816 pConf->SetPath(
"/Settings/WMM");
817 pConf->Read(
"ViewType", &m_iViewType, 1);
818 pConf->Read(
"ShowPlotOptions", &m_bShowPlotOptions, 1);
819 pConf->Read(
"ShowAtCursor", &m_bShowAtCursor, 1);
820 pConf->Read(
"ShowLiveIcon", &m_bShowLiveIcon, 1);
821 pConf->Read(
"ShowIcon", &m_bShowIcon, 1);
822 pConf->Read(
"Opacity", &m_iOpacity, 255);
824 m_wmm_dialog_x = pConf->Read(
"DialogPosX", 20L);
825 m_wmm_dialog_y = pConf->Read(
"DialogPosY", 20L);
827 if ((m_wmm_dialog_x < 0) || (m_wmm_dialog_x > m_display_width))
829 if ((m_wmm_dialog_y < 0) || (m_wmm_dialog_y > m_display_height))
832 pConf->SetPath(
"/Settings/WMM/Plot");
833 pConf->Read(
"Declination", &m_DeclinationMap.m_bEnabled, 1);
834 pConf->Read(
"DeclinationSpacing", &m_DeclinationMap.m_Spacing, 10);
835 pConf->Read(
"Inclination", &m_InclinationMap.m_bEnabled, 0);
836 pConf->Read(
"InclinationSpacing", &m_InclinationMap.m_Spacing, 10);
837 pConf->Read(
"FieldStrength", &m_FieldStrengthMap.m_bEnabled, 0);
838 pConf->Read(
"FieldStrengthSpacing", &m_FieldStrengthMap.m_Spacing, 10000);
840 pConf->Read(
"StepSize", &m_MapStep, 6);
841 pConf->Read(
"PoleAccuracy", &m_MapPoleAccuracy, 2);
842 m_DeclinationMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
843 m_InclinationMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
844 m_FieldStrengthMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
846 m_MapDate = wxDateTime::Now();
848 m_bCachedPlotOk =
false;
850 pConf->SetPath(
"/Directories");
851 wxString s = wxFileName::GetPathSeparator();
861bool WmmPi::SaveConfig(
void) {
862 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
865 pConf->SetPath(
"/Settings/WMM");
866 pConf->Write(
"ViewType", m_iViewType);
867 pConf->Write(
"ShowPlotOptions", m_bShowPlotOptions);
868 pConf->Write(
"ShowAtCursor", m_bShowAtCursor);
869 pConf->Write(
"ShowLiveIcon", m_bShowLiveIcon);
870 pConf->Write(
"ShowIcon", m_bShowIcon);
871 pConf->Write(
"Opacity", m_iOpacity);
873 pConf->Write(
"DialogPosX", m_wmm_dialog_x);
874 pConf->Write(
"DialogPosY", m_wmm_dialog_y);
876 pConf->SetPath(
"/Settings/WMM/Plot");
877 pConf->Write(
"Declination", m_DeclinationMap.m_bEnabled);
878 pConf->Write(
"DeclinationSpacing", m_DeclinationMap.m_Spacing);
879 pConf->Write(
"Inclination", m_InclinationMap.m_bEnabled);
880 pConf->Write(
"InclinationSpacing", m_InclinationMap.m_Spacing);
881 pConf->Write(
"FieldStrength", m_FieldStrengthMap.m_bEnabled);
882 pConf->Write(
"FieldStrengthSpacing", m_FieldStrengthMap.m_Spacing);
883 pConf->Write(
"StepSize", m_MapStep);
884 pConf->Write(
"PoleAccuracy", m_MapPoleAccuracy);
886 pConf->SetPath(
"/Directories");
887 pConf->Write(
"WMMDataLocation", m_wmm_dir);
897 wxPoint(m_wmm_dialog_x, m_wmm_dialog_y), wxDefaultSize,
898 wxDEFAULT_DIALOG_STYLE);
901 dialog->m_rbViewType->SetSelection(m_iViewType);
902 dialog->m_cbShowPlotOptions->SetValue(m_bShowPlotOptions);
903 dialog->m_cbShowAtCursor->SetValue(m_bShowAtCursor);
904 dialog->m_cbShowIcon->SetValue(m_bShowIcon);
905 dialog->m_cbLiveIcon->SetValue(m_bShowLiveIcon);
906 dialog->m_sOpacity->SetValue(m_iOpacity);
908 if (dialog->ShowModal() == wxID_OK) {
909 m_iViewType = dialog->m_rbViewType->GetSelection();
910 m_bShowPlotOptions = dialog->m_cbShowPlotOptions->GetValue();
911 m_bShowAtCursor = dialog->m_cbShowAtCursor->GetValue();
912 m_bShowLiveIcon = dialog->m_cbLiveIcon->GetValue();
913 m_bShowIcon = dialog->m_cbShowIcon->GetValue();
914 m_iOpacity = dialog->m_sOpacity->GetValue();
927 dialog->SetFont(*pFont);
931 dialog->m_cbDeclination->SetValue(m_DeclinationMap.m_bEnabled);
932 dialog->m_scDeclinationSpacing->SetValue(m_DeclinationMap.m_Spacing);
933 dialog->m_cbInclination->SetValue(m_InclinationMap.m_bEnabled);
934 dialog->m_scInclinationSpacing->SetValue(m_InclinationMap.m_Spacing);
935 dialog->m_cbFieldStrength->SetValue(m_FieldStrengthMap.m_bEnabled);
936 dialog->m_scFieldStrengthSpacing->SetValue(m_FieldStrengthMap.m_Spacing);
938 dialog->m_sStep->SetValue(m_MapStep);
939 dialog->m_sPoleAccuracy->SetValue(m_MapPoleAccuracy);
941 if (dialog->ShowModal() == wxID_OK) {
942 m_DeclinationMap.m_bEnabled = dialog->m_cbDeclination->GetValue();
943 m_DeclinationMap.m_Spacing = dialog->m_scDeclinationSpacing->GetValue();
944 m_InclinationMap.m_bEnabled = dialog->m_cbInclination->GetValue();
945 m_InclinationMap.m_Spacing = dialog->m_scInclinationSpacing->GetValue();
946 m_FieldStrengthMap.m_bEnabled = dialog->m_cbFieldStrength->GetValue();
947 m_FieldStrengthMap.m_Spacing = dialog->m_scFieldStrengthSpacing->GetValue();
949 m_MapStep = dialog->m_sStep->GetValue();
950 m_MapPoleAccuracy = dialog->m_sPoleAccuracy->GetValue();
951 m_DeclinationMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
952 m_InclinationMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
953 m_FieldStrengthMap.ConfigureAccuracy(m_MapStep, m_MapPoleAccuracy);
955 m_bCachedPlotOk =
false;
956 if (m_pWmmDialog->m_cbEnablePlot->GetValue()) RecomputePlot();
966void WmmPi::SendBoatVarHVD(
double d_var) {
971 wxString s_dir = d_var >= 0 ?
"E" :
"W";
973 wxString S =
"$WMHVD";
975 S.Append(wxString::Format(
"%.1f", d_var));
979 S.Append(wxString::Format(
"%02X", ComputeChecksum(S)));
985void WmmPi::SendPGN127258(
double d_var) {
987 double var_rad = d_var * (M_PI / 180.0);
989 time_t now = time(
nullptr);
990 int days_since_epoch = now / (60 * 60 * 24);
992 SetN2kPGN127258(msg127285, 0xFF, tN2kMagneticVariation::N2kmagvar_WMM2025,
993 days_since_epoch, var_rad);
994 std::shared_ptr<std::vector<uint8_t>> payload(
new std::vector<uint8_t>(
995 msg127285.Data, msg127285.Data + msg127285.DataLen));
999unsigned char WmmPi::ComputeChecksum(wxString sentence)
const {
1000 unsigned char calculated_checksum = 0;
1001 for (wxString::const_iterator i = sentence.begin() + 1;
1002 i != sentence.end() && *i !=
'*'; ++i)
1003 calculated_checksum ^=
static_cast<unsigned char>(*i);
1005 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.
int GetAPIVersionMinor() override
Returns the minor version number of the plugin API that this plugin supports.
wxString GetShortDescription() override
Get a brief description of the plugin.
int GetPlugInVersionMajor() override
Returns the major version number of the plugin itself.
wxString GetLongDescription() override
Get detailed plugin information.
bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp) override
Renders plugin overlay graphics in OpenGL mode for single canvas.
int Init() override
Initialize the plugin and declare its capabilities.
void ShowPreferencesDialog(wxWindow *parent) override
Shows the plugin preferences dialog.
void SetCursorLatLon(double lat, double lon) override
Receives cursor lat/lon position updates.
int GetAPIVersionMajor() override
Returns the major version number of the plugin API that this plugin supports.
bool DeInit() override
Clean up plugin resources.
void OnToolbarToolCallback(int id) override
Handles toolbar tool clicks.
void SetColorScheme(PI_ColorScheme cs) override
Updates plugin color scheme.
wxBitmap * GetPlugInBitmap() override
Get the plugin's icon bitmap.
int GetPlugInVersionMinor() override
Returns the minor version number of the plugin itself.
wxString GetCommonName() override
Get the plugin's common (short) name.
void SetPositionFix(PlugIn_Position_Fix &pfix) override
Updates plugin with current position fix data at regular intervals.
int GetToolbarToolCount() override
Returns the number of toolbar tools this plugin provides.
Base class for OpenCPN plugins.
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...