void EBL::MoveEndPoint( bool bUpdateEBL ) { ODPoint *pEndPoint = m_pODPointList->GetLast()->GetData(); ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); if(m_dLength == 0.) m_dLength = pEndPoint->m_seg_len; if(m_bRotateWithBoat) { MaintainWith(); } else { if(!m_bFixedEndPosition) PositionBearingDistanceMercator_Plugin(pStartPoint->m_lat, pStartPoint->m_lon, m_dEBLAngle, m_dLength, &pEndPoint->m_lat, &pEndPoint->m_lon); } if(m_bVRM) pStartPoint->SetODPointRangeRingsStep( m_dLength / pStartPoint->GetODPointRangeRingsNumber() ); if(g_pEBLPropDialog && g_pEBLPropDialog->IsShown()) g_pEBLPropDialog->UpdateProperties(); if(bUpdateEBL) { bool l_bSaveUpdatesState = m_bSaveUpdates; m_bSaveUpdates = true; UpdateEBL(); m_bSaveUpdates = l_bSaveUpdatesState; } else UpdateEBL(); }
void EBL::CentreOnBoat( bool bMoveEndPoint ) { ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); ODPoint *pEndPoint = m_pODPointList->GetLast()->GetData(); pStartPoint->m_lat = g_pfFix.Lat; pStartPoint->m_lon = g_pfFix.Lon; if(m_dLength == 0.) m_dLength = pEndPoint->m_seg_len; if(bMoveEndPoint && !m_bEndPointMoving) { if(m_bRotateWithBoat) { MaintainWith(); } else { if(!m_bFixedEndPosition) { PositionBearingDistanceMercator_Plugin(pStartPoint->m_lat, pStartPoint->m_lon, m_dEBLAngle, m_dLength, &pEndPoint->m_lat, &pEndPoint->m_lon); } else { double brg; double hdg = 0.; DistanceBearingMercator_Plugin(pEndPoint->m_lat, pEndPoint->m_lon, pStartPoint->m_lat, pStartPoint->m_lon, &brg, &m_dLength); switch(m_iMaintainWith) { case ID_MAINTAIN_WITH_HEADING: if(!isnan(g_pfFix.Hdt)) hdg = g_pfFix.Hdt; break; case ID_MAINTAIN_WITH_COG: if(!isnan(g_pfFix.Cog)) hdg = g_pfFix.Cog; break; } if(hdg > brg) m_dEBLAngle = brg + 360 - hdg; else if(hdg < brg) m_dEBLAngle = hdg - brg; else m_dEBLAngle = 0; } } } else { DistanceBearingMercator_Plugin(pEndPoint->m_lat, pEndPoint->m_lon, pStartPoint->m_lat, pStartPoint->m_lon, &m_dEBLAngle, &m_dLength); m_dBoatHeading = g_pfFix.Hdt; m_dBoatCOG = g_pfFix.Cog; } pStartPoint->m_ODPointName = _("Boat"); m_bCentreOnBoat = true; UpdateEBL(); if(m_bVRM) { ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); pStartPoint->SetODPointRangeRingsStep( m_dLength / pStartPoint->GetODPointRangeRingsNumber() ); } bool l_bRequestRefresh = true; if(g_pEBLPropDialog && g_pEBLPropDialog->IsShown()) l_bRequestRefresh = g_pEBLPropDialog->UpdateProperties(); m_bSaveUpdates = false; if(l_bRequestRefresh) RequestRefresh( g_ocpn_draw_pi->m_parent_window ); return; }
void ODPoint::SetRangeRingBBox(void) { if(m_iODPointRangeRingsNumber > 0 && m_fODPointRangeRingsStep > 0) { double l_dist = m_iODPointRangeRingsNumber * m_fODPointRangeRingsStep; double l_minlat; double l_minlon; double l_maxlat; double l_maxlon; double l_lat; double l_lon; PositionBearingDistanceMercator_Plugin(m_lat, m_lon, 0, l_dist, &l_maxlat, &l_lon); PositionBearingDistanceMercator_Plugin(m_lat, m_lon, 90, l_dist, &l_lat, &l_maxlon); PositionBearingDistanceMercator_Plugin(m_lat, m_lon, 180, l_dist, &l_minlat, &l_lon); PositionBearingDistanceMercator_Plugin(m_lat, m_lon, 270, l_dist, &l_lat, &l_minlon); m_RangeRingsBBox.Set(l_minlat, l_minlon, l_maxlat, l_maxlon); } }
void EBL::MaintainWith( void ) { ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); ODPoint *pEndPoint = m_pODPointList->GetLast()->GetData(); switch(m_iMaintainWith) { case ID_EBL_MAINTAIN_WITH_HEADING: if(!isnan(g_pfFix.Hdt)) PositionBearingDistanceMercator_Plugin(pStartPoint->m_lat, pStartPoint->m_lon, g_pfFix.Hdt + m_dEBLAngle, m_dLength, &pEndPoint->m_lat, &pEndPoint->m_lon); else PositionBearingDistanceMercator_Plugin(pStartPoint->m_lat, pStartPoint->m_lon, m_dEBLAngle, m_dLength, &pEndPoint->m_lat, &pEndPoint->m_lon); break; case ID_EBL_MAINTAIN_WITH_COG: if(!isnan(g_pfFix.Cog)) PositionBearingDistanceMercator_Plugin(pStartPoint->m_lat, pStartPoint->m_lon, g_pfFix.Cog + m_dEBLAngle, m_dLength, &pEndPoint->m_lat, &pEndPoint->m_lon); else PositionBearingDistanceMercator_Plugin(pStartPoint->m_lat, pStartPoint->m_lon, m_dEBLAngle, m_dLength, &pEndPoint->m_lat, &pEndPoint->m_lon); break; } }
void EBL::MoveStartPoint( double lat, double lon ) { ODPoint *pEndPoint = m_pODPointList->GetLast()->GetData(); ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); pStartPoint->m_lat = lat; pStartPoint->m_lon = lon; if(m_dLength == 0.) m_dLength = pEndPoint->m_seg_len; if(m_bRotateWithBoat){ MaintainWith(); } else { PositionBearingDistanceMercator_Plugin(pStartPoint->m_lat, pStartPoint->m_lon, m_dEBLAngle, m_dLength, &pEndPoint->m_lat, &pEndPoint->m_lon); } if(m_bVRM) { ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); pStartPoint->SetODPointRangeRingsStep( m_dLength / pStartPoint->GetODPointRangeRingsNumber() ); } if(g_pEBLPropDialog && g_pEBLPropDialog->IsShown()) g_pEBLPropDialog->UpdateProperties(); }
void ODDRDialogImpl::OnOK( wxCommandEvent& event ) { if( m_pDR != NULL ) { if( g_pPathMan->GetpActivePath() == m_pDR ) g_pPathMan->DeactivatePath( m_pDR ); if( !g_pPathMan->DeletePath( m_pDR ) ) return; if( g_pODPathPropDialog && ( g_pODPathPropDialog->IsShown()) && (m_pDR == g_pODPathPropDialog->GetPath()) ) { g_pODPathPropDialog->Hide(); } if( g_pPathManagerDialog && g_pPathManagerDialog->IsShown() ) g_pPathManagerDialog->UpdatePathListCtrl(); if( g_pODPointPropDialog && g_pODPointPropDialog->IsShown() ) { g_pODPointPropDialog->ValidateMark(); g_pODPointPropDialog->UpdateProperties(); } } DR *l_pDR = new(DR); g_pDRList->Append( l_pDR ); g_pPathList->Append( l_pDR ); l_pDR->m_PathNameString << _("DR") << _T(" ") << g_pDRList->GetCount(); ODPoint *beginPoint = new ODPoint( g_pfFix.Lat, g_pfFix.Lon, wxEmptyString, wxS("Start"), wxT("") ); beginPoint->SetNameShown( false ); beginPoint->SetTypeString( wxT("DR Point")); beginPoint->m_IconName = g_sDRPointIconName; beginPoint->m_bIsolatedMark = false; beginPoint->m_bShowODPointRangeRings = g_bDRPointShowRangeRings; beginPoint->m_iODPointRangeRingsNumber = g_iDRPointRangeRingsNumber; beginPoint->m_fODPointRangeRingsStep = g_fDRPointRangeRingsStep; beginPoint->m_iODPointRangeRingsStepUnits = g_iDRPointRangeRingsStepUnits; beginPoint->m_wxcODPointRangeRingsColour = g_colourDRPointRangeRingsColour; beginPoint->m_iRangeRingStyle = g_iDRPointRangeRingLineStyle; beginPoint->m_iRangeRingWidth = g_iDRPointRangeRingLineWidth; l_pDR->AddPoint( beginPoint, false ); m_textCtrlSOG->GetValue().ToDouble( &l_pDR->m_dSoG ); l_pDR->m_iCoG = g_ocpn_draw_pi->GetTrueOrMag( wxAtoi( m_textCtrlCOG->GetValue() ) ); l_pDR->m_dMagCOG = g_dVar; m_textCtrlLength->GetValue().ToDouble( &l_pDR->m_dDRPathLength ); m_textCtrlDRPointInterval->GetValue().ToDouble( &l_pDR->m_dDRPointInterval ); l_pDR->m_iLengthType = m_radioBoxLengthType->GetSelection(); l_pDR->m_iIntervalType = m_radioBoxIntervalType->GetSelection(); l_pDR->m_iDistanceUnits = m_radioBoxDistanceUnits->GetSelection(); l_pDR->m_iTimeUnits = m_radioBoxTimeUnits->GetSelection(); switch ( m_radioBoxLengthType->GetSelection() ) { case ID_LT_TIME: { switch ( m_radioBoxTimeUnits->GetSelection() ) { case ID_TU_MINUTES: l_pDR->m_dTotalLengthNM = ( l_pDR->m_dSoG / 60 ) * l_pDR->m_dDRPathLength; break; case ID_TU_HOURS: l_pDR->m_dTotalLengthNM = l_pDR->m_dSoG * l_pDR->m_dDRPathLength; break; case ID_TU_DAYS: l_pDR->m_dTotalLengthNM = ( l_pDR->m_dSoG * l_pDR->m_dDRPathLength ) * 24; break; } break; } case ID_LT_DISTANCE: { if( m_radioBoxDistanceUnits->GetSelection() == ID_DU_KILOMETRES ) l_pDR->m_dTotalLengthNM = l_pDR->m_dDRPathLength / 1.852; else l_pDR->m_dTotalLengthNM = l_pDR->m_dDRPathLength; break; } } switch ( m_radioBoxIntervalType->GetSelection() ) { case ID_IT_TIME: { switch ( m_radioBoxTimeUnits->GetSelection() ) { case ID_TU_MINUTES: l_pDR->m_dDRPointIntervalNM = ( l_pDR->m_dSoG / 60 ) * l_pDR->m_dDRPointInterval; break; case ID_TU_HOURS: l_pDR->m_dDRPointIntervalNM = l_pDR->m_dSoG * l_pDR->m_dDRPointInterval; break; case ID_TU_DAYS: l_pDR->m_dDRPointIntervalNM = ( l_pDR->m_dSoG * l_pDR->m_dDRPointInterval ) * 24; break; } break; } case ID_IT_DISTANCE: { if( m_radioBoxDistanceUnits->GetSelection() == ID_DU_KILOMETRES ) l_pDR->m_dDRPointIntervalNM = l_pDR->m_dDRPointInterval / 1.852; else l_pDR->m_dDRPointIntervalNM = l_pDR->m_dDRPointInterval; break; } } double l_dStartLat = g_pfFix.Lat; double l_dStartLon = g_pfFix.Lon; double l_dEndLat; double l_dEndLon; PositionBearingDistanceMercator_Plugin( l_dStartLat, l_dStartLon, l_pDR->m_iCoG, l_pDR->m_dTotalLengthNM, &l_dEndLat, &l_dEndLon ); int l_iNumODPoints = floor( l_pDR->m_dTotalLengthNM / l_pDR->m_dDRPointIntervalNM ); double l_cumLength = l_pDR->m_dDRPointIntervalNM; double l_dSaveLat = l_dStartLat; double l_dSaveLon = l_dStartLon; for( int i = 0; i < l_iNumODPoints; i++ ) { double l_dLat, l_dLon; PositionBearingDistanceMercator_Plugin( l_dStartLat, l_dStartLon, l_pDR->m_iCoG, l_cumLength, &l_dLat, &l_dLon ); ODPoint *l_NewPoint = new ODPoint( l_dLat, l_dLon, g_sDRPointIconName, wxT(""), wxT("") ); l_NewPoint->SetNameShown( false ); l_NewPoint->SetTypeString( wxS("DR Point") ); l_NewPoint->m_bIsolatedMark = FALSE; l_NewPoint->m_bShowODPointRangeRings = g_bDRPointShowRangeRings; l_NewPoint->m_iODPointRangeRingsNumber = g_iDRPointRangeRingsNumber; l_NewPoint->m_fODPointRangeRingsStep = g_fDRPointRangeRingsStep; l_NewPoint->m_iODPointRangeRingsStepUnits = g_iDRPointRangeRingsStepUnits; l_NewPoint->m_wxcODPointRangeRingsColour = g_colourDRPointRangeRingsColour; l_NewPoint->m_iRangeRingStyle = g_iDRPointRangeRingLineStyle; l_NewPoint->m_iRangeRingWidth = g_iDRPointRangeRingLineWidth; l_pDR->AddPoint( l_NewPoint ); g_pODSelect->AddSelectableODPoint( l_dLat, l_dLon, l_NewPoint ); g_pODSelect->AddSelectablePathSegment( l_dLat, l_dLon, l_dSaveLat, l_dSaveLon, beginPoint, l_NewPoint, l_pDR ); l_dSaveLat = l_dLat; l_dSaveLon = l_dLon; l_cumLength += l_pDR->m_dDRPointIntervalNM; } if( l_dEndLat != l_dSaveLat || l_dEndLon != l_dSaveLon ) { ODPoint *l_NewPoint = new ODPoint( l_dEndLat, l_dEndLon, g_sDRPointIconName, wxT(""), wxT("") ); l_NewPoint->SetNameShown( false ); l_NewPoint->SetTypeString( wxS("DR Point") ); l_NewPoint->m_bIsolatedMark = FALSE; l_NewPoint->m_bShowODPointRangeRings = g_bDRPointShowRangeRings; l_NewPoint->m_iODPointRangeRingsNumber = g_iDRPointRangeRingsNumber; l_NewPoint->m_fODPointRangeRingsStep = g_fDRPointRangeRingsStep; l_NewPoint->m_iODPointRangeRingsStepUnits = g_iDRPointRangeRingsStepUnits; l_NewPoint->m_wxcODPointRangeRingsColour = g_colourDRPointRangeRingsColour; l_NewPoint->m_iRangeRingStyle = g_iDRPointRangeRingLineStyle; l_NewPoint->m_iRangeRingWidth = g_iDRPointRangeRingLineWidth; l_pDR->AddPoint( l_NewPoint ); g_pODSelect->AddSelectableODPoint( l_dEndLat, l_dEndLon, l_NewPoint ); g_pODSelect->AddSelectablePathSegment( l_dSaveLat, l_dSaveLon, l_dEndLat, l_dEndLon, beginPoint, l_NewPoint, l_pDR ); } if(l_pDR->m_iPersistenceType == ID_DR_PERSISTENT || l_pDR->m_iPersistenceType == ID_DR_PERSISTENT_CRASH) g_pODConfig->AddNewPath( l_pDR, -1 ); // don't save over restart RequestRefresh( g_ocpn_draw_pi->m_parent_window ); Show( false ); #ifdef __WXOSX__ EndModal(wxID_CANCEL); #endif }
/*************************************************************************************** Calculate & Draw the laylines for the bearing compass ****************************************************************************************/ void TacticsInstrument_BearingCompass::DrawLaylines(wxGCDC* dc) { if (!wxIsNaN(m_Cog) && !wxIsNaN(m_Hdt) && !wxIsNaN(m_lat) && !wxIsNaN(m_lon) && !wxIsNaN(m_TWA) && !wxIsNaN(m_CurrDir) && !wxIsNaN(m_CurrSpeed)){ wxColour cl; GetGlobalColor(_T("DASH2"), &cl); wxPen pen1; pen1.SetStyle(wxSOLID); pen1.SetColour(cl); pen1.SetWidth(2); dc->SetPen(pen1); GetGlobalColor(_T("DASH1"), &cl); wxBrush brush1; brush1.SetStyle(wxSOLID); brush1.SetColour(cl); dc->SetBrush(brush1); dc->SetPen(*wxTRANSPARENT_PEN); GetGlobalColor(_T("DASHN"), &cl); wxBrush vbrush, tackbrush; vbrush.SetStyle(wxSOLID); tackbrush.SetStyle(wxSOLID); //m_curTack = TWA unit //it shows L= wind from left = port tack or R=wind from right = starboard tack //we're on port tack, so vertical layline is red if (m_curTack == _T("\u00B0L")) { vbrush.SetColour(wxColour(204, 41, 41, 128)); //red, transparent tackbrush.SetColour(wxColour(0, 200, 0, 128)); //green, transparent m_targetTack = _("R"); } else if (m_curTack == _T("\u00B0R")) {// we're on starboard tack, so vertical layline is green vbrush.SetColour(wxColour(0, 200, 0, 128)); //green, transparent tackbrush.SetColour(wxColour(204, 41, 41, 128)); //red, transparent m_targetTack = _("L"); } double value1 = deg2rad(m_Cog - m_ExpSmoothDegRange / 2. ) + deg2rad(m_AngleStart - ANGLE_OFFSET); double value2 = deg2rad(m_Cog + m_ExpSmoothDegRange / 2. ) + deg2rad(m_AngleStart - ANGLE_OFFSET); //draw the vertical layline dc->SetBrush(vbrush); wxPoint vpoints[3]; vpoints[0].x = m_cx; vpoints[0].y = m_cy; vpoints[1].x = m_cx + (m_radius * cos(value1));//neu : für HEadup = HDT vpoints[1].y = m_cy + (m_radius * sin(value1));//neu : für HEadup = HDT vpoints[2].x = m_cx + (m_radius * cos(value2));//neu : für HEadup = HDT vpoints[2].y = m_cy + (m_radius * sin(value2));//neu : für HEadup = HDT dc->DrawArc(vpoints[2], vpoints[1], vpoints[0]); /***************************************************************************************** Caclulate and draw the second layline (for other tack) : --------------------------------------------------------- Approach : in the bearing compass display, "head up" = COG. And TWA is based on boat heading (Hdt). to calculate the layline of the other tack, sum up diff_btw_Cog_and_HDG(now we're on Hdt) ; this is NOT NEEDED if Head-Up = Hdt !!! + 2 x TWA + Leeway --------- = predictedHdt + current_angle ====================== = newCog (on other tack) Calculation of (sea) current angle : 1. from actual pos. calculate the endpoint of predictedHdt (out: predictedLatHdt, predictedLonHdt), assuming same StW on other tack 2. at that point apply current : startpoint predictedLatHdt, predictedLonHdt + bearing + speed; out : predictedLatCog, predictedLonCog 3. calculate angle (and speed) from curr pos to predictedLatCog, predictedLonCog; out : newCog + newSOG ********************************************************************************************/ dc->SetBrush(tackbrush); double predictedKdW; //==predicted Course Through Water /********************************************* Old: with BearingCompass Head-Up = COG double diffCogHdt = m_Cog - m_Hdt; m_oldExpSmoothDiffCogHdt = m_ExpSmoothDiffCogHdt; m_ExpSmoothDiffCogHdt = alpha_diffCogHdt*diffCogHdt + (1 - alpha_diffCogHdt)*m_oldExpSmoothDiffCogHdt; if (m_targetTack == _T("R")){ // currently wind is from port ... predictedKdW = m_Cog - m_ExpSmoothDiffCogHdt - 2 * m_TWA - m_Leeway; } else if (m_targetTack == _T("L")){ //currently wind from starboard predictedKdW = m_Cog + m_ExpSmoothDiffCogHdt + 2 * m_TWA + m_Leeway; } *******************************************/ //New: with BearingCompass in Head-Up mode = Hdt double Leeway = (m_LeewayUnit == _T("\u00B0L")) ? -m_Leeway : m_Leeway; if (m_targetTack == _T("R")){ // so currently wind is from port ... //predictedKdW = m_Hdt - 2 * m_TWA - m_Leeway; predictedKdW = m_Hdt - 2 * m_TWA - Leeway; } else if (m_targetTack == _T("L")){ //so, currently wind from starboard //predictedKdW = m_Hdt + 2 * m_TWA + m_Leeway; predictedKdW = m_Hdt + 2 * m_TWA - Leeway; } else { predictedKdW = (m_TWA < 10) ? 180 : 0; // should never happen, but is this correct ??? } if (predictedKdW >= 360) predictedKdW -= 360; if (predictedKdW < 0) predictedKdW += 360; double predictedLatHdt, predictedLonHdt, predictedLatCog, predictedLonCog; double predictedCoG; //standard triangle calculation to get predicted CoG / SoG //get endpoint from boat-position by applying KdW, StW PositionBearingDistanceMercator_Plugin(m_lat, m_lon, predictedKdW, fromUsrSpeed_Plugin(m_StW, g_iDashSpeedUnit), &predictedLatHdt, &predictedLonHdt); //wxLogMessage(_T("Step1: m_lat=%f,m_lon=%f, predictedKdW=%f,m_StW=%f --> predictedLatHdt=%f,predictedLonHdt=%f\n"), m_lat, m_lon, predictedKdW, m_StW, predictedLatHdt, predictedLonHdt); //apply surface current with direction & speed to endpoint from above PositionBearingDistanceMercator_Plugin(predictedLatHdt, predictedLonHdt, m_CurrDir, m_CurrSpeed, &predictedLatCog, &predictedLonCog); //wxLogMessage(_T("Step2: predictedLatHdt=%f,predictedLonHdt=%f, m_CurrDir=%f,m_CurrSpeed=%f --> predictedLatCog=%f,predictedLonCog=%f\n"), predictedLatHdt, predictedLonHdt, m_CurrDir, m_CurrSpeed, predictedLatCog, predictedLonCog); //now get predicted CoG & SoG as difference between the 2 endpoints (coordinates) from above DistanceBearingMercator_Plugin(predictedLatCog, predictedLonCog, m_lat, m_lon, &predictedCoG, &m_predictedSog); //wxLogMessage("m_Leeway=%f, m_LeewayUnit=%s,m_targetTack=%s,predictedKdW=%.2f,predictedCoG=%f,predictedSog=%f ", m_Leeway, m_LeewayUnit, m_targetTack, predictedKdW, predictedCoG, m_predictedSog); //wxLogMessage(_T("Step3: predictedLatCog=%f,predictedLonCog=%f, m_lat=%f,m_lon=%f --> predictedCoG=%f,predictedSog=%f, AngleStart=%d\n"), predictedLatCog, predictedLonCog, m_lat, m_lon, predictedCoG, m_predictedSog, m_AngleStart); value1 = deg2rad(predictedCoG - m_ExpSmoothDegRange / 2.) + deg2rad(m_AngleStart - ANGLE_OFFSET); value2 = deg2rad(predictedCoG + m_ExpSmoothDegRange / 2.) + deg2rad(m_AngleStart - ANGLE_OFFSET); wxPoint tackpoints[3]; tackpoints[0].x = m_cx; tackpoints[0].y = m_cy; tackpoints[1].x = m_cx + (m_radius * cos(value1)); tackpoints[1].y = m_cy + (m_radius * sin(value1)); tackpoints[2].x = m_cx + (m_radius * cos(value2)); tackpoints[2].y = m_cy + (m_radius * sin(value2)); dc->DrawArc(tackpoints[2], tackpoints[1], tackpoints[0]); } }