Example #1
0
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);
}
Example #3
0
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;
}
Example #4
0
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);
}
Example #6
0
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);
}
Example #7
0
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();
}
Example #8
0
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();
}
Example #9
0
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;
}
Example #10
0
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);
    }
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
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();
}
Example #14
0
/***************************************************************************************
  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]);
	}
}