double BoatPlan::SpeedAtApparentWind(double A, double VA, double *pW) { int iters = 0; double VW = VA, W = A, VB = 0; // initial guess double lp = 1; for(;;) { double cVB = Speed(W, VW); VB -= (VB - cVB) * lp; double cVA = VelocityApparentWind(VB, deg2rad(W), VW); double cA = rad2posdeg(DirectionApparentWind(cVA, VB, deg2rad(W), VW)); if(isnan(cVA) || isnan(cA) || iters++ > 256) { if(pW) *pW = NAN; return NAN; } if(fabsf(cVA - VA) < 2e-2 && fabsf(cA - A) < 2e-2) { if(pW) *pW = W; return cVB; } VW -= (cVA - VA) * lp; W -= (cA - A) * lp; lp *= .97; } }
void BoatDialog::OnMouseEventsPolarPlot( wxMouseEvent& event ) { #if 0 if(event.Leaving()) { m_stTrueWindAngle->SetLabel(_("N/A")); m_stTrueWindKnots->SetLabel(_("N/A")); m_stApparentWindAngle->SetLabel(_("N/A")); m_stApparentWindKnots->SetLabel(_("N/A")); m_stBoatAngle->SetLabel(_("N/A")); m_stBoatKnots->SetLabel(_("N/A")); return; } wxPoint p = event.GetPosition(); int w, h; m_PlotWindow->GetSize( &w, &h); /* range + to - */ double W, VW, B, VB, A, VA; double windspeed; switch(m_lPlotType->GetSelection()) { case 0: if(m_cPlotType->GetSelection() == 0) { // polar if(!m_PlotScale) return; double x = (double)p.x - w/2; double y = (double)p.y - h/2; /* range +- */ x /= m_PlotScale; y /= m_PlotScale; B = rad2posdeg(atan2(x, -y)); } else B = (double)p.x/w*360; windspeed = m_sWindSpeed->GetValue(); break; case 1: { B = m_sWindDirection->GetValue(); double i = (double)p.x/w*num_wind_speeds; int i0 = floor(i), i1 = ceil(i); double d = i - i0; windspeed = (1-d)*wind_speeds[i0] + d*wind_speeds[i1]; } break; } switch(m_cPlotVariable->GetSelection()) { case 0: // true wind W = B; VW = windspeed; VB = m_Boat.Plans[m_SelectedSailPlan].Speed(W, VW); VA = BoatPlan::VelocityApparentWind(VB, W, VW); A = rad2posdeg(BoatPlan::DirectionApparentWind(VA, VB, W, VW)); break; case 1: A = heading_resolve(B); VW = windspeed; VB = m_Boat.Plans[m_SelectedSailPlan].SpeedAtApparentWindDirection(A, VW, &W); W = positive_degrees(W); VA = BoatPlan::VelocityApparentWind(VB, W, VW); break; case 2: W = B; VA = windspeed; VB = m_Boat.Plans[m_SelectedSailPlan].SpeedAtApparentWindSpeed(W, VA); VW = BoatPlan::VelocityTrueWind(VA, VB, W); A = rad2posdeg(BoatPlan::DirectionApparentWind(VA, VB, W, VW)); break; case 3: A = heading_resolve(B); VA = windspeed; VB = m_Boat.Plans[m_SelectedSailPlan].SpeedAtApparentWind(A, VA, &W); W = positive_degrees(W); VW = BoatPlan::VelocityTrueWind(VA, VB, W); } m_stBoatAngle->SetLabel(wxString::Format(_T("%03.0f"), B)); m_stBoatKnots->SetLabel(wxString::Format(_T("%.1f"), VB)); int newmousew = round(B); if(newmousew != m_MouseW) { m_MouseW = newmousew; RefreshPlots(); } m_stTrueWindAngle->SetLabel(wxString::Format(_T("%03.0f"), W)); m_stTrueWindKnots->SetLabel(wxString::Format(_T("%.1f"), VW)); m_stApparentWindAngle->SetLabel(wxString::Format(_T("%03.0f"), A)); m_stApparentWindKnots->SetLabel(wxString::Format(_T("%.1f"), VA)); #endif }