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_EBL_MAINTAIN_WITH_HEADING: if(!isnan(g_pfFix.Hdt)) hdg = g_pfFix.Hdt; break; case ID_EBL_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 DistanceMercatorFunc::Execute(wxSQLite3FunctionContext& ctx) { if ( ctx.GetArgCount() != 4 ) { ctx.SetResultError(_T("Function takes exactly 4 arguments.")); return; } double lat0 = ctx.GetDouble(0); double lon0 = ctx.GetDouble(1); double lat1 = ctx.GetDouble(2); double lon1 = ctx.GetDouble(3); if ( lat0 > 90. || lat0 < -90. || lat1 > 90. || lat1 < -90.) { ctx.SetResultError(_T("Latitude must be between -90 and 90.")); return; } if ( lon0 > 180. || lon0 < -180. || lon1 > 180. || lon1 < -180.) { ctx.SetResultError(_T("Longitude must be between -180 and 180.")); return; } double dist; DistanceBearingMercator_Plugin(lat0, lon0, lat1, lon1, NULL, &dist); ctx.SetResult(dist); }
void watchdog_pi::OnTimer( wxTimerEvent & ) { /* calculate course and speed over ground from gps */ if(m_lasttimerfix.FixTime == 0) { m_lasttimerfix = m_lastfix; return; } double dt = m_lastfix.FixTime - m_lasttimerfix.FixTime; if(!isnan(m_lastfix.Lat) && !isnan(m_lasttimerfix.Lat) && dt > 0) { /* this way helps avoid surge speed from gps from surfing waves etc... */ double cog, sog; DistanceBearingMercator_Plugin(m_lastfix.Lat, m_lastfix.Lon, m_lasttimerfix.Lat, m_lasttimerfix.Lon, &cog, &sog); sog *= (3600.0 / dt); if(isnan(m_cog)) m_cog = cog, m_sog = sog; else { m_cog = .25*cog + .75*m_cog; m_sog = .25*sog + .75*m_sog; } } else m_sog = m_cog = NAN; m_lasttimerfix = m_lastfix; }
void EBL::MoveEndPoint( void ) { ODPoint *pEndPoint = m_pODPointList->GetLast()->GetData(); ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); DistanceBearingMercator_Plugin(pEndPoint->m_lat, pEndPoint->m_lon, pStartPoint->m_lat, pStartPoint->m_lon, &m_dEBLAngle, &m_dLength); if(m_bRotateWithBoat) { switch(m_iMaintainWith) { case ID_EBL_MAINTAIN_WITH_HEADING: m_dEBLAngle -= g_pfFix.Hdt; break; case ID_EBL_MAINTAIN_WITH_COG: m_dEBLAngle -= g_pfFix.Cog; break; } } m_dBoatHeading = g_pfFix.Hdt; m_dBoatCOG = g_pfFix.Cog; 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 ConfigurationBatchDialog::OnConnect( wxCommandEvent& event ) { double nm; m_tMiles->GetValue().ToDouble(&nm); for(std::vector<BatchSource*>::iterator it = sources.begin(); it != sources.end(); it++) { (*it)->destinations.clear(); for(std::vector<BatchSource*>::iterator it2 = sources.begin(); it2 != sources.end(); it2++) if(*it != *it2) { double distance; double lat1, lon1, lat2, lon2; RouteMap::PositionLatLon((*it)->Name, lat1, lon1); RouteMap::PositionLatLon((*it2)->Name, lat2, lon2); DistanceBearingMercator_Plugin(lat1, lon1, lat2, lon2, 0, &distance); if(distance <= nm) (*it)->destinations.push_back(*it2); } } m_lSources->SetSelection(-1); }
void TacticsInstrument_FromOwnship::SetData(int st, double data, wxString unit) { if (st == m_cap_flag1) { c_lat = data; } else if (st == m_cap_flag2) { c_lon = data; } else if (st == m_cap_flag3) { s_lat = data; } else if (st == m_cap_flag4) { s_lon = data; } else return; if ( s_lat < 99999999 && s_lon < 99999999 ) { double brg,dist; DistanceBearingMercator_Plugin(c_lat, c_lon, s_lat, s_lon, &brg, &dist); m_data1.Printf(_T("%03d ") + DEGREE_SIGN,(int)brg); m_data2.Printf(_T("%3.2f %s"), toUsrDistance_Plugin(dist, g_iDashDistanceUnit), getUsrDistanceUnit_Plugin(g_iDashDistanceUnit).c_str()); } Refresh(false); }
void EBL::ResizeVRM( void ) { ODPoint *pEndPoint = m_pODPointList->GetLast()->GetData(); ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); double brg, dd; DistanceBearingMercator_Plugin( pEndPoint->m_lat, pEndPoint->m_lon, pStartPoint->m_lat, pStartPoint->m_lon, &brg, &dd ); pEndPoint->m_seg_len = dd; if(g_pEBLPropDialog && g_pEBLPropDialog->IsShown()) g_pEBLPropDialog->UpdateProperties(); }
void EBL::ResizeVRM( double lat, double lon ) { ODPoint *pEndPoint = m_pODPointList->GetLast()->GetData(); pEndPoint->m_lat = lat; pEndPoint->m_lon = lon; ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); double brg; DistanceBearingMercator_Plugin( lat, lon, pStartPoint->m_lat, pStartPoint->m_lon, &brg, &m_dLength ); pEndPoint->m_seg_len = m_dLength; if(g_pEBLPropDialog && g_pEBLPropDialog->IsShown()) g_pEBLPropDialog->UpdateProperties(); }
bool ODSelect::IsSegmentSelected( float a, float b, float c, float d, float slat, float slon ) { double adder = 0.; if( ( c * d ) < 0. ) { // Arrange for points to be increasing longitude, c to d double dist, brg; DistanceBearingMercator_Plugin( a, c, b, d, &brg, &dist ); if( brg < 180. ) // swap points? { double tmp; tmp = c; c = d; d = tmp; tmp = a; a = b; b = tmp; } if( d < 0. ) // idl? { d += 360.; if( slon < 0. ) adder = 360.; } } // As a course test, use segment bounding box test if( ( slat >= ( fmin ( a,b ) - selectRadius ) ) && ( slat <= ( fmax ( a,b ) + selectRadius ) ) && ( ( slon + adder ) >= ( fmin ( c,d ) - selectRadius ) ) && ( ( slon + adder ) <= ( fmax ( c,d ) + selectRadius ) ) ) { // Use vectors to do hit test.... ODvector2D va, vb, vn; // Assuming a Mercator projection double ap, cp; toSM( a, c, 0., 0., &cp, &ap ); double bp, dp; toSM( b, d, 0., 0., &dp, &bp ); double slatp, slonp; toSM( slat, slon + adder, 0., 0., &slonp, &slatp ); va.x = slonp - cp; va.y = slatp - ap; vb.x = dp - cp; vb.y = bp - ap; double delta = vGetLengthOfNormal( &va, &vb, &vn ); if( fabs( delta ) < ( selectRadius * 1852 * 60 ) ) return true; } return false; }
void WeatherRouting::OnGoTo( wxCommandEvent& event ) { RouteMapOverlay *rmo = CurrentRouteMap(true); if(rmo) { RouteMapConfiguration config = rmo->GetConfiguration(); double distance; DistanceBearingMercator_Plugin(config.StartLat, config.StartLon, config.EndLat, config.EndLon, NULL, &distance); JumpToPosition(config.StartLat, config.StartLon, .25/distance); } }
void EBL::CentreOnLatLon( double lat, double lon ) { ODPoint *pStartPoint = m_pODPointList->GetFirst()->GetData(); ODPoint *pEndPoint = m_pODPointList->GetLast()->GetData(); pStartPoint->m_lat = lat; pStartPoint->m_lon = lon; DistanceBearingMercator_Plugin(pEndPoint->m_lat, pEndPoint->m_lon, pStartPoint->m_lat, pStartPoint->m_lon, &m_dEBLAngle, &m_dLength); m_bRotateWithBoat = false; m_bCentreOnBoat = false; pStartPoint->m_ODPointName = _("Start"); if(pStartPoint->GetIconName() != wxEmptyString) { pStartPoint->SetIconName( g_sEBLStartIconName ); pStartPoint->ReLoadIcon(); } m_bCentreOnBoat = false; m_bSaveUpdates = true; UpdateEBL(); if(g_pEBLPropDialog && g_pEBLPropDialog->IsShown()) g_pEBLPropDialog->UpdateProperties(); RequestRefresh( g_ocpn_draw_pi->m_parent_window ); return; }
bool PathProp::UpdateProperties( Path *pPath ) { if( NULL == pPath ) return false; ::wxBeginBusyCursor(); m_PathNameCtl->SetValue( pPath->m_PathNameString ); m_textDescription->SetValue( pPath->m_PathDescription); m_pPathActive->SetValue( pPath->IsActive() ); double brg; double join_distance = 0.; ODPoint *first_point = pPath->GetPoint( 1 ); if( first_point ) DistanceBearingMercator_Plugin( first_point->m_lat, first_point->m_lon, g_dLat, g_dLon, &brg, &join_distance ); // Update the "tides event" column header wxListItem column_info; if( m_opList->GetColumn( 6, column_info ) ) { wxString c = _("Next tide event"); if( gpIDX && m_starttime.IsValid() ) { c = _T("@~~"); c.Append( wxString( gpIDX->IDX_station_name, wxConvUTF8 ) ); int i = c.Find( ',' ); if( i != wxNOT_FOUND ) c.Remove( i ); } column_info.SetText( c ); m_opList->SetColumn( 6, column_info ); } // Total length double total_length = pPath->m_path_length; wxString slen; slen.Printf( wxT("%5.2f ") + getUsrDistanceUnit_Plugin(), toUsrDistance_Plugin( total_length ) ); m_TotalDistCtl->SetValue( slen ); wxString time_form; wxString tide_form; // Iterate on Route Points wxODPointListNode *node = pPath->m_pODPointList->GetFirst(); int i = 0; double slat = g_dLat; double slon = g_dLon; int stopover_count = 0; bool arrival = true; // marks which pass over the wpt we do - 1. arrival 2. departure bool enroute = true; // for active route, skip all points up to the active point wxString nullify = _T("----"); while( node ) { ODPoint *prp = node->GetData(); long item_line_index = i + stopover_count; // Leg wxString t; t.Printf( _T("%d"), i ); if( i == 0 ) t = _T("Boat"); if( arrival ) m_opList->SetItem( item_line_index, 0, t ); // Mark Name if( arrival ) m_opList->SetItem( item_line_index, 1, prp->GetName() ); // Store Dewcription if( arrival ) m_opList->SetItem( item_line_index, 8, prp->GetDescription() ); // Distance // Note that Distance/Bearing for Leg 000 is as from current position double brg, leg_dist; bool starting_point = false; starting_point = ( i == 0 ) && enroute; if( m_pEnroutePoint && !starting_point ) starting_point = ( prp->m_GUID == m_pEnroutePoint->m_GUID ); DistanceBearingMercator_Plugin( prp->m_lat, prp->m_lon, slat, slon, &brg, &leg_dist ); // calculation of course at current WayPoint. double course=10, tmp_leg_dist=23; wxODPointListNode *next_node = node->GetNext(); ODPoint * _next_prp = (next_node)? next_node->GetData(): NULL; if (_next_prp ) { DistanceBearingMercator_Plugin( _next_prp->m_lat, _next_prp->m_lon, prp->m_lat, prp->m_lon, &course, &tmp_leg_dist ); }else { course = 0.0; tmp_leg_dist = 0.0; } //prp->SetCourse(course); // save the course to the next waypoint for printing. // end of calculation t.Printf( _T("%6.2f ") + getUsrDistanceUnit_Plugin(), toUsrDistance_Plugin( leg_dist ) ); if( arrival ) m_opList->SetItem( item_line_index, 2, t ); if( !enroute ) m_opList->SetItem( item_line_index, 2, nullify ); prp->SetDistance(leg_dist); // save the course to the next waypoint for printing. // Bearing if( g_bShowMag ) t.Printf( _T("%03.0f Deg. M"), g_ocpn_draw_pi->GetTrueOrMag( brg ) ); else t.Printf( _T("%03.0f Deg. T"), g_ocpn_draw_pi->GetTrueOrMag( brg ) ); // if( arrival ) // m_opList->SetItem( item_line_index, 3, t ); // if( !enroute ) // m_opList->SetItem( item_line_index, 3, nullify ); // Course (bearing of next ) if (_next_prp){ if( g_bShowMag ) t.Printf( _T("%03.0f Deg. M"), g_ocpn_draw_pi->GetTrueOrMag( course ) ); else t.Printf( _T("%03.0f Deg. T"), g_ocpn_draw_pi->GetTrueOrMag( course ) ); if( arrival ) m_opList->SetItem( item_line_index, 7, t ); } else m_opList->SetItem( item_line_index, 7, nullify ); // Lat/Lon wxString tlat = toSDMM_PlugIn( 1, prp->m_lat, prp->m_bIsInTrack ); // low precision for routes if( arrival ) m_opList->SetItem( item_line_index, 4, tlat ); wxString tlon = toSDMM_PlugIn( 2, prp->m_lon, prp->m_bIsInTrack ); if( arrival ) m_opList->SetItem( item_line_index, 5, tlon ); tide_form = _T(""); //LMT_Offset = long( ( prp->m_lon ) * 3600. / 15. ); // Save for iterating distance/bearing calculation slat = prp->m_lat; slon = prp->m_lon; // if stopover (ETD) found, loop for next output line for the same point // with departure time & tide information if( arrival && ( prp->m_seg_etd.IsValid() ) ) { stopover_count++; arrival = false; } else { arrival = true; i++; node = node->GetNext(); } } if( pPath->m_ActiveLineColour == wxEmptyString ) m_chColor->Select( 0 ); else { for( unsigned int i = 0; i < sizeof( ::GpxxColorNames ) / sizeof(wxString); i++ ) { if( pPath->m_ActiveLineColour == ::GpxxColorNames[i] ) { m_chColor->Select( i + 1 ); break; } } } if( pPath->m_ActiveFillColour == wxEmptyString ) m_chLineColor->Select( 0 ); else { for( unsigned int i = 0; i < sizeof( ::GpxxColorNames ) / sizeof(wxString); i++ ) { if( pPath->m_ActiveFillColour == ::GpxxColorNames[i] ) { m_chLineColor->Select( i + 1 ); break; } } } for( unsigned int i = 0; i < sizeof( ::StyleValues ) / sizeof(int); i++ ) { if( pPath->m_style == ::StyleValues[i] ) { m_chStyle->Select( i ); break; } } for( unsigned int i = 0; i < sizeof( ::WidthValues ) / sizeof(int); i++ ) { if( pPath->m_width == ::WidthValues[i] ) { m_chWidth->Select( i ); break; } } ::wxEndBusyCursor(); return true; }
void TacticsInstrument_BearingCompass::SetData(int st, double data, wxString unit) { if (st == OCPN_DBP_STC_COG) { m_Cog = data; } else if (st == OCPN_DBP_STC_HDT) { m_AngleStart = -data; m_MainValue = data; m_MainValueUnit = unit; m_Hdt = data; } else if (st == OCPN_DBP_STC_CURRDIR) { m_CurrDir = data; m_CurrDirUnit = unit; } else if (st == OCPN_DBP_STC_CURRSPD) { m_CurrSpeed = data; m_CurrSpeedUnit = unit; } else if (st == OCPN_DBP_STC_DTW) { if (!GetSingleWaypoint(_T("TacticsWP"), m_pMark)){ m_ExtraValueDTW = data; m_ExtraValueDTWUnit = unit; } } else if (st == OCPN_DBP_STC_TWA) { m_curTack = unit; m_TWA = data; } else if (st == OCPN_DBP_STC_TWD) { m_TWD = data; } else if (st == OCPN_DBP_STC_AWA) { m_AWA = data; } else if (st == OCPN_DBP_STC_TWS) { m_TWS = data; } else if (st == OCPN_DBP_STC_LEEWAY) { m_Leeway = data; m_LeewayUnit = unit; } else if (st == OCPN_DBP_STC_LAT) { m_lat = data; } else if (st == OCPN_DBP_STC_LON) { m_lon = data; } else if (st == OCPN_DBP_STC_STW) { m_StW = data; } if (m_Cog != -999 && m_Hdt != -999){ m_diffCogHdt = m_Cog - m_Hdt; } if (st == OCPN_DBP_STC_BRG) { //if (!GetSingleWaypoint(_T("TacticsWP"), m_pMark)){ m_Bearing = data; m_ToWpt = unit; /*} else{ if (m_pMark) { double dist; DistanceBearingMercator_Plugin(m_pMark->m_lat, m_pMark->m_lon, m_lat, m_lon, &m_Bearing, &dist); m_ToWpt = _T("TacticsWP"); m_ExtraValueDTW = toUsrDistance_Plugin(dist, g_iDashDistanceUnit); m_ExtraValueDTWUnit = getUsrDistanceUnit_Plugin(g_iDashDistanceUnit); } }*/ m_BearingUnit = _T("\u00B0"); } if (!GetSingleWaypoint(_T("TacticsWP"), m_pMark)) m_pMark = NULL; if (m_pMark && !wxIsNaN(m_lat) && !wxIsNaN(m_lon)) { double dist; DistanceBearingMercator_Plugin(m_pMark->m_lat, m_pMark->m_lon, m_lat, m_lon, &m_Bearing, &dist); m_ToWpt = _T("TacticsWP"); m_ExtraValueDTW = toUsrDistance_Plugin(dist, g_iDashDistanceUnit); m_ExtraValueDTWUnit = getUsrDistanceUnit_Plugin(g_iDashDistanceUnit); m_BearingUnit = _T("\u00B0"); } if (!m_pMark && wxIsNaN(m_Bearing)){ m_ToWpt = _T("---"); m_ExtraValueDTW = NAN; m_predictedSog = NAN; m_ExtraValueDTWUnit = getUsrDistanceUnit_Plugin(g_iDashDistanceUnit); m_BearingUnit = _T("\u00B0"); } CalculateLaylineDegreeRange(); }
/*************************************************************************************** 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]); } }