/* * VENTA3 This is a modified Segment() */ int DrawArc(HDC hdc, long x, long y, int radius, RECT rc, double start, double end) { POINT pt[66]; int i; int istart; int iend; rectObj rect; rect.minx = x-radius; rect.maxx = x+radius; rect.miny = y-radius; rect.maxy = y+radius; rectObj rcrect; rcrect.minx = rc.left; rcrect.maxx = rc.right; rcrect.miny = rc.top; rcrect.maxy = rc.bottom; if (msRectOverlap(&rect, &rcrect)!=MS_TRUE) { return FALSE; } // JMW added faster checking... start = AngleLimit360(start); end = AngleLimit360(end); istart = iround(start/360.0*64); iend = iround(end/360.0*64); int npoly = 0; if (istart>iend) { iend+= 64; } istart++; iend--; pt[npoly].x = x + (long) (radius * fastsine(start)); pt[npoly].y = y - (long) (radius * fastcosine(start)); npoly++; for(i=0;i<64;i++) { if (i<=iend-istart) { pt[npoly].x = x + (long) (radius * xcoords[(i+istart)%64]); pt[npoly].y = y - (long) (radius * ycoords[(i+istart)%64]); npoly++; } } pt[npoly].x = x + (long) (radius * fastsine(end)); pt[npoly].y = y - (long) (radius * fastcosine(end)); npoly++; if (npoly) { Polyline(hdc,pt,npoly); // TODO check ClipPolygon for HP31X } return TRUE; }
// // The heading track line, like on Garmin units // void MapWindow::DrawHeading(HDC hdc, POINT Orig, RECT rc ) { if (DrawInfo.NAVWarning) return; // 100214 if ( mode.Is(MapWindow::Mode::MODE_CIRCLING)) return; POINT p2; double tmp = 200000*zoom.ResScaleOverDistanceModify(); if ( !( DisplayOrientation == TRACKUP || DisplayOrientation == NORTHCIRCLE || DisplayOrientation == TRACKCIRCLE )) { double trackbearing = DrawInfo.TrackBearing; p2.y= Orig.y - (int)(tmp*fastcosine(trackbearing)); p2.x= Orig.x + (int)(tmp*fastsine(trackbearing)); } else { p2.x=Orig.x; p2.y=Orig.y-(int)tmp; } // Reduce the rectangle for a better effect rc.top+=NIBLSCALE(5); rc.right-=NIBLSCALE(5); rc.bottom-=NIBLSCALE(5); rc.left+=NIBLSCALE(5); ForcedClipping=true; if (BlackScreen) _DrawLine(hdc, PS_SOLID, NIBLSCALE(1), Orig, p2, RGB_INVDRAW, rc); // 091109 else _DrawLine(hdc, PS_SOLID, NIBLSCALE(1), Orig, p2, RGB_BLACK, rc); ForcedClipping=false; }
void MapWindow::CalculateOrigin(const RECT rc, POINT *Orig) { if (mode.Is(Mode::MODE_PAN)) { // North up DisplayAngle = 0.0; DisplayAircraftAngle = DrawInfo.TrackBearing; GliderCenter = true; } else { if (mode.Is(Mode::MODE_TARGET_PAN)) { CalculateOrientationTargetPan(); } else { CalculateOrientationNormal(); } } if(mode.Is(Mode::MODE_TARGET_PAN)) { if (ScreenLandscape) { Orig->x = (rc.left + rc.right - targetPanSize)/2; Orig->y = (rc.bottom + rc.top)/2; } else { Orig->x = (rc.left + rc.right)/2; Orig->y = (rc.bottom + rc.top + targetPanSize)/2; } } else if(mode.Is(Mode::MODE_PAN) || mode.Is(Mode::MODE_CIRCLING)) { Orig->x = (rc.left + rc.right)/2; Orig->y = (rc.bottom + rc.top)/2; } else { // automagic northup smart if (DisplayOrientation == NORTHSMART) { double trackbearing = DrawInfo.TrackBearing; int middleXY,spanxy; if (ScreenLandscape) { middleXY=((rc.bottom-BottomSize)+rc.top)/2; spanxy=NIBLSCALE(50); Orig->y= middleXY + (int)(spanxy*fastcosine(trackbearing)); // This was moving too much the map! // spanx=NIBLSCALE(40); // Orig->x= middleX - (int)(spanx*fastsine(trackbearing)); Orig->x = (rc.left + rc.right)/2; } else { middleXY=(rc.left+rc.right)/2; spanxy=NIBLSCALE(50); Orig->x= middleXY - (int)(spanxy*fastsine(trackbearing)); Orig->y = ((rc.bottom-BottomSize) + rc.top)/2; } } else { // 100924 if we are in north up autorient, position the glider in middle screen if ((zoom.Scale()*1.4) >= AutoOrientScale) { Orig->x = (rc.left + rc.right)/2; Orig->y=((rc.bottom-BottomSize)+rc.top)/2; } else { // else do it normally using configuration Orig->x = ((rc.right - rc.left )*GliderScreenPositionX/100)+rc.left; Orig->y = ((rc.top - rc.bottom )*GliderScreenPositionY/100)+rc.bottom; } } } }
void MapWindow::DrawHeadUpLine(HDC hdc, POINT Orig, RECT rc, double fMin, double fMax ) { COLORREF rgbCol = RGB_BLACK; POINT p1, p2; double tmp = fMax*zoom.ResScaleOverDistanceModify(); double trackbearing = DisplayAircraftAngle+ (DerivedDrawInfo.Heading-DrawInfo.TrackBearing); p2.y= Orig.y - (int)(tmp*fastcosine(trackbearing)); p2.x= Orig.x + (int)(tmp*fastsine(trackbearing)); p1.y= Orig.y; p1.x= Orig.x; if (BlackScreen) rgbCol = RGB_INVDRAW; ForcedClipping=true; // Reduce the rectangle for a better effect rc.top+=NIBLSCALE(5); rc.right-=NIBLSCALE(5); rc.bottom-=NIBLSCALE(5); rc.left+=NIBLSCALE(5); _DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p1, p2, rgbCol, rc); ForcedClipping=false; }
/* * VENTA3 This is a modified Segment() */ int LKSurface::DrawArc(long x, long y, int radius, const RECT& rc, double start, double end) { POINT pt[66]; int i; int istart; int iend; if ((x - radius) > rc.right) return false; if ((x + radius) < rc.left) return false; if ((y - radius) > rc.bottom) return false; if ((y + radius) < rc.top) return false; // JMW added faster checking... start = AngleLimit360(start); end = AngleLimit360(end); istart = iround(start / 360.0 * 64); iend = iround(end / 360.0 * 64); int npoly = 0; if (istart > iend) { iend += 64; } istart++; iend--; pt[npoly].x = x + (long) (radius * fastsine(start)); pt[npoly].y = y - (long) (radius * fastcosine(start)); npoly++; for (i = 0; i < 64; i++) { if (i <= iend - istart) { pt[npoly].x = x + (long) (radius * xcoords[(i + istart) % 64]); pt[npoly].y = y - (long) (radius * ycoords[(i + istart) % 64]); npoly++; } } pt[npoly].x = x + (long) (radius * fastsine(end)); pt[npoly].y = y - (long) (radius * fastcosine(end)); npoly++; Polyline(pt, npoly, rc); return true; }
void MapWindow::DrawHeadUpLine(LKSurface& Surface, const POINT& Orig, const RECT& rc, double fMin, double fMax ) { const double tmp = fMax*zoom.ResScaleOverDistanceModify(); const double trackbearing = DisplayAircraftAngle+ (DerivedDrawInfo.Heading-DrawInfo.TrackBearing); const POINT p2 = { Orig.x + (int)(tmp*fastsine(trackbearing)), Orig.y - (int)(tmp*fastcosine(trackbearing)) }; const LKColor rgbCol = BlackScreen?RGB_INVDRAW:RGB_BLACK; // Reduce the rectangle for a better effect const RECT ClipRect = {rc.left+NIBLSCALE(5), rc.top+NIBLSCALE(5), rc.right-NIBLSCALE(5), rc.bottom-NIBLSCALE(5) }; Surface.DrawLine(PEN_SOLID, NIBLSCALE(1), Orig, p2, rgbCol, ClipRect); }
void MapWindow::DrawFuturePos(LKSurface& Surface, const POINT& Orig, const RECT& rc, bool headUpLine) { if(DrawInfo.Speed < 13.88) return; //Don't continue if ground speed < 50 Km/h const double trackBearing = headUpLine ? DisplayAircraftAngle+(DerivedDrawInfo.Heading-DrawInfo.TrackBearing) : DrawInfo.TrackBearing; const double dist2min=120*DrawInfo.Speed*zoom.ResScaleOverDistanceModify(); // 2 min if(dist2min>=NIBLSCALE(3)) { //proceed only if the distance is not too small on the map const double dist5min=300*DrawInfo.Speed*zoom.ResScaleOverDistanceModify(); // 5 min const double dist10min=600*DrawInfo.Speed*zoom.ResScaleOverDistanceModify(); //10 min // Reduce the rectangle for a better effect const RECT ClipRect = (RECT){rc.left+NIBLSCALE(5), rc.top+NIBLSCALE(5), rc.right-NIBLSCALE(5), rc.bottom-NIBLSCALE(5) }; POINT p1,p2; if( !MapWindow::mode.autoNorthUP() && !headUpLine && (DisplayOrientation==TRACKUP || DisplayOrientation==NORTHCIRCLE || DisplayOrientation==TARGETCIRCLE || DisplayOrientation==TARGETUP)) { //Track up map view p1.x=Orig.x-NIBLSCALE(4); p2.x=Orig.x+NIBLSCALE(4); p1.y=p2.y=Orig.y-(int)round(dist2min); Surface.DrawLine(PEN_SOLID,NIBLSCALE(1),p1,p2,BlackScreen?RGB_INVDRAW:RGB_BLACK,ClipRect); p1.y=p2.y=Orig.y-(int)round(dist5min); Surface.DrawLine(PEN_SOLID,NIBLSCALE(1),p1,p2,BlackScreen?RGB_INVDRAW:RGB_BLACK,ClipRect); p1.y=p2.y=Orig.y-(int)round(dist10min); Surface.DrawLine(PEN_SOLID,NIBLSCALE(1),p1,p2,BlackScreen?RGB_INVDRAW:RGB_BLACK,ClipRect); } else { //North up map view const double sin=fastsine(trackBearing); const double cos=fastcosine(trackBearing); double distXsin=dist2min*sin; double distXcos=dist2min*cos; const double tickXsin=NIBLSCALE(4)*sin; const double tickXcos=NIBLSCALE(4)*cos; p1.x=Orig.x+(int)round(distXsin-tickXcos); p1.y=Orig.y-(int)round(distXcos+tickXsin); p2.x=Orig.x+(int)round(distXsin+tickXcos); p2.y=Orig.y-(int)round(distXcos-tickXsin); Surface.DrawLine(PEN_SOLID,NIBLSCALE(1),p1,p2,BlackScreen?RGB_INVDRAW:RGB_BLACK,ClipRect); distXsin=dist5min*sin; distXcos=dist5min*cos; p1.x=Orig.x+(int)round(distXsin-tickXcos); p1.y=Orig.y-(int)round(distXcos+tickXsin); p2.x=Orig.x+(int)round(distXsin+tickXcos); p2.y=Orig.y-(int)round(distXcos-tickXsin); Surface.DrawLine(PEN_SOLID,NIBLSCALE(1),p1,p2,BlackScreen?RGB_INVDRAW:RGB_BLACK,ClipRect); distXsin=dist10min*sin; distXcos=dist10min*cos; p1.x=Orig.x+(int)round(distXsin-tickXcos); p1.y=Orig.y-(int)round(distXcos+tickXsin); p2.x=Orig.x+(int)round(distXsin+tickXcos); p2.y=Orig.y-(int)round(distXcos-tickXsin); Surface.DrawLine(PEN_SOLID,NIBLSCALE(1),p1,p2,BlackScreen?RGB_INVDRAW:RGB_BLACK,ClipRect); } } }
void frotate(float &xin, float &yin, const float &angle) { float x= xin; float y= yin; static float lastangle = 0; static float cost=1,sint=0; if(angle != lastangle) { lastangle = angle; cost = (float)fastcosine(angle); sint = (float)fastsine(angle); } xin = x*cost - y*sint; yin = y*cost + x*sint; }
void rotate(double &xin, double &yin, const double &angle) { double x= xin; double y= yin; static double lastangle = 0; static double cost=1,sint=0; if(angle != lastangle) { lastangle = angle; cost = (double)fastcosine(angle); sint = (double)fastsine(angle); } xin = x*cost - y*sint; yin = y*cost + x*sint; }
void frotatescale(float &xin, float &yin, const float &angle, const float &scale) { float x= xin; float y= yin; static float lastangle = 0; static float lastscale = 0; static float cost=1,sint=0; if((angle != lastangle)||(scale != lastscale)) { lastangle = angle; lastscale = scale; cost = (float)fastcosine(angle)*scale; sint = (float)fastsine(angle)*scale; } xin = x*cost - y*sint; yin = y*cost + x*sint; }
void rotatescale(double &xin, double &yin, const double &angle, const double &scale) { double x= xin; double y= yin; static double lastangle = 0; static double lastscale = 0; static double cost=1,sint=0; if((angle != lastangle)||(scale != lastscale)) { lastangle = angle; lastscale = scale; cost = (double)fastcosine(angle)*scale; sint = (double)fastsine(angle)*scale; } xin = x*cost - y*sint; yin = y*cost + x*sint; }
// // The heading track line, like on Garmin units // void MapWindow::DrawHeading(HDC hdc, POINT Orig, RECT rc ) { if (GPS_INFO.NAVWarning) return; // 100214 if (zoom.RealScale()>5 || mode.Is(MapWindow::Mode::MODE_CIRCLING)) return; POINT p2; double tmp = 12000*zoom.ResScaleOverDistanceModify(); if ( !( DisplayOrientation == TRACKUP || DisplayOrientation == NORTHCIRCLE || DisplayOrientation == TRACKCIRCLE )) { double trackbearing = DrawInfo.TrackBearing; p2.y= Orig.y - (int)(tmp*fastcosine(trackbearing)); p2.x= Orig.x + (int)(tmp*fastsine(trackbearing)); } else { p2.x=Orig.x; p2.y=Orig.y-(int)tmp; } if (BlackScreen) _DrawLine(hdc, PS_SOLID, NIBLSCALE(1), Orig, p2, RGB_INVDRAW, rc); // 091109 else _DrawLine(hdc, PS_SOLID, NIBLSCALE(1), Orig, p2, RGB_BLACK, rc); }
// Used by dlgTarget only // A note about this function. We are changing map drawing parameters here, but we paint from the winmain thread. // We are NOT using this from drawthread! the dialog target pan is sort of an hack, and not a good example. // Do not consider emulating the target dialog, because it should be moved to draw thread somehow. void MapWindow::SetTargetPan(bool do_pan, int target_point, DWORD dlgSize /* = 0 */) { static double old_latitude; static double old_longitude; if(dlgSize) targetPanSize = dlgSize; if (!mode.Is(Mode::MODE_TARGET_PAN) || (TargetPanIndex != target_point)) { targetMoved = false; } TargetPanIndex = target_point; if (do_pan && !mode.Is(Mode::MODE_TARGET_PAN)) { old_latitude = PanLatitude; old_longitude = PanLongitude; mode.Special(do_pan ? Mode::MODE_SPECIAL_TARGET_PAN : Mode::MODE_SPECIAL_PAN, true); zoom.SwitchMode(); } if (do_pan) { LockTaskData(); if (ValidTaskPoint(target_point)) { PanLongitude = WayPointList[Task[target_point].Index].Longitude; PanLatitude = WayPointList[Task[target_point].Index].Latitude; if (target_point==0) { TargetZoomDistance = max(2e3, (double)StartRadius*2); } else if (!ValidTaskPoint(target_point+1)) { TargetZoomDistance = max(2e3, (double)FinishRadius*2); } else if (AATEnabled) { if (Task[target_point].AATType == SECTOR) { const double start = Task[target_point].AATStartRadial; const double finish = Task[target_point].AATFinishRadial; const double xs = fastsine(start); const double ys = fastcosine(start); const double xf = fastsine(finish); const double yf = fastcosine(finish); // calculate rectangle area taken by the sector const double top = AngleInRange(start, finish, 0, true) ? 1 : max(max(ys, yf), 0.0); const double right = AngleInRange(start, finish, 90, true) ? 1 : max(max(xs, xf), 0.0); const double bottom = AngleInRange(start, finish, 180, true) ? -1 : min(min(ys, yf), 0.0); const double left = AngleInRange(start, finish, 270, true) ? -1 : min(min(xs, xf), 0.0); // get area center const double radius = Task[target_point].AATSectorRadius; const double x = (left + right) / 2; const double y = (top + bottom) / 2; double bearing, range; xXY_Brg_Rng(0, 0, x, y, &bearing, &range); // find area center geographic data FindLatitudeLongitude(WayPointList[Task[target_point].Index].Latitude, WayPointList[Task[target_point].Index].Longitude, bearing, range * radius, &PanLatitude, &PanLongitude); TargetZoomDistance = max(2e3, max(right - left, top - bottom) * radius); } else { TargetZoomDistance = max(2e3, Task[target_point].AATCircleRadius*2); } } else { TargetZoomDistance = max(2e3, (double)SectorRadius*2); } } UnlockTaskData(); } else if (mode.Is(Mode::MODE_TARGET_PAN)) { PanLongitude = old_longitude; PanLatitude = old_latitude; mode.Special(Mode::MODE_SPECIAL_TARGET_PAN, do_pan); zoom.SwitchMode(); } mode.Special(Mode::MODE_SPECIAL_TARGET_PAN, do_pan); }
void MapWindow::DrawTRI(HDC hDC, const RECT rc) { POINT Start; static short top=(((rc.bottom-BottomSize-(rc.top+TOPLIMITER)-BOTTOMLIMITER)/PANELROWS)+rc.top+TOPLIMITER)- (rc.top+TOPLIMITER); Start.y = ((rc.bottom-BottomSize-top)/2)+top-NIBLSCALE(10); Start.x = (rc.right - rc.left)/2; HPEN hpBlack; HBRUSH hbBlack; HPEN hpWhite; HBRUSH hbWhite; HPEN hpBorder; HBRUSH hbBorder; HPEN hpOld; HBRUSH hbOld; // gauge size radius static int radius = NIBLSCALE(65); static int planesize = radius-NIBLSCALE(10); // planebody static int planeradius = NIBLSCALE(6); static int tailsize = planesize/4+NIBLSCALE(2); static int innerradius = radius - NIBLSCALE(8); static POINT d00[2][2],d15[2][4],d30[2][4], d45[2][4], d60[2][4]; TCHAR Buffer[LKSIZEBUFFERVALUE]; double beta=0.0; bool disabled=false; if (DoInit[MDI_DRAWTRI]) { top=(((rc.bottom-BottomSize-(rc.top+TOPLIMITER)-BOTTOMLIMITER)/PANELROWS)+rc.top+TOPLIMITER)- (rc.top+TOPLIMITER); radius = NIBLSCALE(65); planesize = radius-NIBLSCALE(10); planeradius = NIBLSCALE(6); tailsize = planesize/4+NIBLSCALE(2); innerradius = radius - NIBLSCALE(8); // [a][b] a=0 external circle a=1 inner circle b=1-4 d00[0][0].x= Start.x - radius; d00[0][0].y= Start.y; d00[1][0].x= Start.x - innerradius; d00[1][0].y= Start.y; d00[0][1].x= Start.x + radius; d00[0][1].y= Start.y; d00[1][1].x= Start.x + innerradius; d00[1][1].y= Start.y; d15[0][0].x= Start.x - (long) (radius*fastcosine(15.0)); d15[0][0].y= Start.y + (long) (radius*fastsine(15.0)); d15[1][0].x= Start.x - (long) (innerradius*fastcosine(15.0)); d15[1][0].y= Start.y + (long) (innerradius*fastsine(15.0)); d15[0][1].x= Start.x - (long) (radius*fastcosine(15.0)); d15[0][1].y= Start.y - (long) (radius*fastsine(15.0)); d15[1][1].x= Start.x - (long) (innerradius*fastcosine(15.0)); d15[1][1].y= Start.y - (long) (innerradius*fastsine(15.0)); d15[0][2].x= Start.x + (long) (radius*fastcosine(15.0)); d15[0][2].y= Start.y + (long) (radius*fastsine(15.0)); d15[1][2].x= Start.x + (long) (innerradius*fastcosine(15.0)); d15[1][2].y= Start.y + (long) (innerradius*fastsine(15.0)); d15[0][3].x= Start.x + (long) (radius*fastcosine(15.0)); d15[0][3].y= Start.y - (long) (radius*fastsine(15.0)); d15[1][3].x= Start.x + (long) (innerradius*fastcosine(15.0)); d15[1][3].y= Start.y - (long) (innerradius*fastsine(15.0)); d30[0][0].x= Start.x - (long) (radius*fastcosine(30.0)); d30[0][0].y= Start.y + (long) (radius*fastsine(30.0)); d30[1][0].x= Start.x - (long) (innerradius*fastcosine(30.0)); d30[1][0].y= Start.y + (long) (innerradius*fastsine(30.0)); d30[0][1].x= Start.x - (long) (radius*fastcosine(30.0)); d30[0][1].y= Start.y - (long) (radius*fastsine(30.0)); d30[1][1].x= Start.x - (long) (innerradius*fastcosine(30.0)); d30[1][1].y= Start.y - (long) (innerradius*fastsine(30.0)); d30[0][2].x= Start.x + (long) (radius*fastcosine(30.0)); d30[0][2].y= Start.y + (long) (radius*fastsine(30.0)); d30[1][2].x= Start.x + (long) (innerradius*fastcosine(30.0)); d30[1][2].y= Start.y + (long) (innerradius*fastsine(30.0)); d30[0][3].x= Start.x + (long) (radius*fastcosine(30.0)); d30[0][3].y= Start.y - (long) (radius*fastsine(30.0)); d30[1][3].x= Start.x + (long) (innerradius*fastcosine(30.0)); d30[1][3].y= Start.y - (long) (innerradius*fastsine(30.0)); d45[0][0].x= Start.x - (long) (radius*fastcosine(45.0)); d45[0][0].y= Start.y + (long) (radius*fastsine(45.0)); d45[1][0].x= Start.x - (long) (innerradius*fastcosine(45.0)); d45[1][0].y= Start.y + (long) (innerradius*fastsine(45.0)); d45[0][1].x= Start.x - (long) (radius*fastcosine(45.0)); d45[0][1].y= Start.y - (long) (radius*fastsine(45.0)); d45[1][1].x= Start.x - (long) (innerradius*fastcosine(45.0)); d45[1][1].y= Start.y - (long) (innerradius*fastsine(45.0)); d45[0][2].x= Start.x + (long) (radius*fastcosine(45.0)); d45[0][2].y= Start.y + (long) (radius*fastsine(45.0)); d45[1][2].x= Start.x + (long) (innerradius*fastcosine(45.0)); d45[1][2].y= Start.y + (long) (innerradius*fastsine(45.0)); d45[0][3].x= Start.x + (long) (radius*fastcosine(45.0)); d45[0][3].y= Start.y - (long) (radius*fastsine(45.0)); d45[1][3].x= Start.x + (long) (innerradius*fastcosine(45.0)); d45[1][3].y= Start.y - (long) (innerradius*fastsine(45.0)); d60[0][0].x= Start.x - (long) (radius*fastcosine(60.0)); d60[0][0].y= Start.y + (long) (radius*fastsine(60.0)); d60[1][0].x= Start.x - (long) (innerradius*fastcosine(60.0)); d60[1][0].y= Start.y + (long) (innerradius*fastsine(60.0)); d60[0][1].x= Start.x - (long) (radius*fastcosine(60.0)); d60[0][1].y= Start.y - (long) (radius*fastsine(60.0)); d60[1][1].x= Start.x - (long) (innerradius*fastcosine(60.0)); d60[1][1].y= Start.y - (long) (innerradius*fastsine(60.0)); d60[0][2].x= Start.x + (long) (radius*fastcosine(60.0)); d60[0][2].y= Start.y + (long) (radius*fastsine(60.0)); d60[1][2].x= Start.x + (long) (innerradius*fastcosine(60.0)); d60[1][2].y= Start.y + (long) (innerradius*fastsine(60.0)); d60[0][3].x= Start.x + (long) (radius*fastcosine(60.0)); d60[0][3].y= Start.y - (long) (radius*fastsine(60.0)); d60[1][3].x= Start.x + (long) (innerradius*fastcosine(60.0)); d60[1][3].y= Start.y - (long) (innerradius*fastsine(60.0)); DoInit[MDI_DRAWTRI]=false; } // end dirty hack doinit //if (!CALCULATED_INFO.Flying) { // speed is in m/s if(DrawInfo.Speed <5.5 && !DrawInfo.GyroscopeAvailable) disabled=true; if (disabled) { hpBlack = LKPen_Grey_N1; hbBlack = LKBrush_Grey; } else { hpBlack = LKPen_Black_N1; hbBlack = LKBrush_Black; beta = DrawInfo.GyroscopeAvailable ? DrawInfo.Roll : DerivedDrawInfo.BankAngle; } hpWhite = LKPen_White_N1; hbWhite = LKBrush_White; hpBorder = LKPen_Grey_N2; hbBorder = LKBrush_Grey; hpOld = (HPEN)SelectObject(hDC, hpWhite); hbOld = (HBRUSH)SelectObject(hDC, hbWhite); Circle(hDC, Start.x, Start.y, radius, rc, false, true ); if(DrawInfo.AccelerationAvailable) DrawAcceleration(hDC, rc); SelectObject(hDC, hpBorder); SelectObject(hDC, hbBorder); Circle(hDC, Start.x, Start.y, radius+NIBLSCALE(2), rc, false, false ); SelectObject(hDC, hpBlack); SelectObject(hDC, hbBlack); Circle(hDC, Start.x, Start.y, planeradius, rc, false, true ); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d00[0][0], d00[1][0], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d00[0][1], d00[1][1], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d15[0][0], d15[1][0], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d15[0][1], d15[1][1], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d15[0][2], d15[1][2], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d15[0][3], d15[1][3], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d30[0][0], d30[1][0], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d30[0][1], d30[1][1], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d30[0][2], d30[1][2], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d30[0][3], d30[1][3], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d45[0][0], d45[1][0], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d45[0][1], d45[1][1], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d45[0][2], d45[1][2], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d45[0][3], d45[1][3], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d60[0][0], d60[1][0], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d60[0][1], d60[1][1], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d60[0][2], d60[1][2], RGB_BLUE,rc); _DrawLine(hDC, PS_SOLID, NIBLSCALE(1), d60[0][3], d60[1][3], RGB_BLUE,rc); POINT a1, a2; const double beta_sine = fastsine(beta); const double beta_cosine = fastcosine(beta); a1.x = Start.x - (long)(planesize * beta_cosine); a1.y = Start.y - (long)(planesize * beta_sine); a2.x = Start.x + (long)(planesize * beta_cosine); a2.y = Start.y + (long)(planesize * beta_sine); if (disabled) _DrawLine(hDC, PS_SOLID, NIBLSCALE(4), a1, a2, RGB_GREY,rc); else _DrawLine(hDC, PS_SOLID, NIBLSCALE(4), a1, a2, RGB_BLACK,rc); a1.x = Start.x; a1.y = Start.y; a2.x = Start.x + (long)(tailsize * beta_sine); a2.y = Start.y - (long)(tailsize * beta_cosine); if (disabled) _DrawLine(hDC, PS_SOLID, NIBLSCALE(4), a1, a2, RGB_GREY,rc); else _DrawLine(hDC, PS_SOLID, NIBLSCALE(4), a1, a2, RGB_BLACK,rc); SelectObject(hDC, LK8TitleFont); int bankindy=Start.y-radius/2; #ifndef __MINGW32__ if (beta > 1) _stprintf(Buffer, TEXT("%2.0f\xB0"), beta); else if (beta < -1) _stprintf(Buffer, TEXT("%2.0f\xB0"), -beta); else _tcscpy(Buffer, TEXT("--")); #else if (beta > 1) _stprintf(Buffer, TEXT("%2.0f°"), beta); else if (beta < -1) _stprintf(Buffer, TEXT("%2.0f°"), -beta); else _tcscpy(Buffer, TEXT("--")); #endif LKWriteText(hDC, Buffer, Start.x , bankindy, 0, WTMODE_NORMAL, WTALIGN_CENTER, RGB_BLUE, false); // MapDirty = true; // if (!disabled) MapWindow::RefreshMap(); SelectObject(hDC, hbOld); SelectObject(hDC, hpOld); }
void Heading(NMEA_INFO *Basic, DERIVED_INFO *Calculated) { double x0, y0, mag=0; static double LastTime = 0; static double lastHeading = 0; static double lastSpeed = 0; if (DoInit[MDI_HEADING]) { LastTime = 0; lastHeading = 0; DoInit[MDI_HEADING]=false; } if ((Basic->Speed>0)||(Calculated->WindSpeed>0)) { x0 = fastsine(Basic->TrackBearing)*Basic->Speed; y0 = fastcosine(Basic->TrackBearing)*Basic->Speed; x0 += fastsine(Calculated->WindBearing)*Calculated->WindSpeed; y0 += fastcosine(Calculated->WindBearing)*Calculated->WindSpeed; Calculated->Heading = AngleLimit360(atan2(x0,y0)*RAD_TO_DEG); if (!Calculated->Flying) { // don't take wind into account when on ground Calculated->Heading = Basic->TrackBearing; } // calculate turn rate in wind coordinates if(Basic->Time > LastTime) { double dT = Basic->Time - LastTime; LKASSERT(dT!=0); Calculated->TurnRateWind = AngleLimit180(Calculated->Heading - lastHeading)/dT; lastHeading = Calculated->Heading; } if (ISCAR) { // On ground, TAS is GS. Wind gradient irrilevant, normally. Calculated->TrueAirspeedEstimated = Basic->Speed; LKASSERT(AirDensityRatio(Calculated->NavAltitude)!=0); Calculated->IndicatedAirspeedEstimated = Basic->Speed/AirDensityRatio(Calculated->NavAltitude); } else { // calculate estimated true airspeed mag = isqrt4((unsigned long)(x0*x0*100+y0*y0*100))/10.0; Calculated->TrueAirspeedEstimated = mag; LKASSERT(AirDensityRatio(Calculated->NavAltitude)!=0); Calculated->IndicatedAirspeedEstimated = mag/AirDensityRatio(Calculated->NavAltitude); } // estimate bank angle (assuming balanced turn) double angle = atan(DEG_TO_RAD*Calculated->TurnRateWind* Calculated->TrueAirspeedEstimated/9.81); Calculated->BankAngle = RAD_TO_DEG*angle; if (ISCAR) { if(Basic->Time > LastTime) { Calculated->Gload = ((Basic->Speed - lastSpeed) / (Basic->Time-LastTime))/9.81; lastSpeed=Basic->Speed; } else { Calculated->Gload = 0; } } else { Calculated->Gload = 1.0/max(0.001,fabs(cos(angle))); } LastTime = Basic->Time; // estimate pitch angle (assuming balanced turn) /* Calculated->PitchAngle = RAD_TO_DEG* atan2(Calculated->GPSVario-Calculated->Vario, Calculated->TrueAirspeedEstimated); */ // should be used as here only when no real vario available Calculated->PitchAngle = RAD_TO_DEG* atan2(Calculated->Vario, Calculated->TrueAirspeedEstimated); // update zigzag wind if ( ((AutoWindMode==D_AUTOWIND_ZIGZAG) || (AutoWindMode==D_AUTOWIND_BOTHCIRCZAG)) && (!ReplayLogger::IsEnabled()) ) { double zz_wind_speed; double zz_wind_bearing; int quality=0; quality = WindKalmanUpdate(Basic, Calculated, &zz_wind_speed, &zz_wind_bearing); if (quality>0) { SetWindEstimate(zz_wind_speed, zz_wind_bearing); Calculated->WindSpeed = zz_wind_speed; Calculated->WindBearing = zz_wind_bearing; /* 100118 redundant!! removed. TOCHECK * Vector v_wind; v_wind.x = zz_wind_speed*cos(zz_wind_bearing*3.1415926/180.0); v_wind.y = zz_wind_speed*sin(zz_wind_bearing*3.1415926/180.0); LockFlightData(); if (windanalyser) { windanalyser->slot_newEstimate(Basic, Calculated, v_wind, quality); } UnlockFlightData(); */ } } // else basic speed is 0 and there is no wind.. } else { Calculated->Heading = Basic->TrackBearing; Calculated->TrueAirspeedEstimated = 0; // BUGFIX 100318 Calculated->IndicatedAirspeedEstimated = 0; // BUGFIX 100318 } }
void LKSurface::Segment(long x, long y, int radius, const RECT& rc, double start, double end) { // JMW added faster checking... if ((x - radius) > rc.right) return; if ((x + radius) < rc.left) return; if ((y - radius) > rc.bottom) return; if ((y + radius) < rc.top) return; bool EmptySector = end == start; if(EmptySector) { RasterPoint pt[2]; start = AngleLimit360(start); pt[0].x = x; pt[0].y = y; pt[1].x = x + (long) (radius * fastsine(start)); pt[1].y = y - (long) (radius * fastcosine(start)); Polyline(pt, array_size(pt), rc); } else { RasterPoint pt[68]; start = AngleLimit360(start); end = AngleLimit360(end); const int istart = std::ceil(start / 360.0 * 64); const int iend = std::floor(((end > start) ? end : end + 360) / 360 * 64); int npoly = 0; // Center point pt[npoly].x = x; pt[npoly].y = y; npoly++; // first Segment point pt[npoly].x = x + (long) (radius * fastsine(start)); pt[npoly].y = y - (long) (radius * fastcosine(start)); npoly++; for (int i = 0; i < 64; i++) { if (i <= iend - istart) { pt[npoly].x = x + (long) (radius * xcoords[(i + istart) % 64]); pt[npoly].y = y - (long) (radius * ycoords[(i + istart) % 64]); npoly++; } } // Last Segment Point pt[npoly].x = x + (long) (radius * fastsine(end)); pt[npoly].y = y - (long) (radius * fastcosine(end)); npoly++; // Close Polygon ( center point ) pt[npoly].x = x; pt[npoly].y = y; npoly++; assert(npoly <= (int)array_size(pt)); Polygon(pt, npoly, rc); } }
int DrawCompassArc(HDC hdc, long x, long y, int radius, RECT rc, double bearing) { const int indicatorStep = 10; // For Oren: remember to always DeleteObject you create with Create, or in 1 hour any // device will run out of GDI space, including your PC... // Meanwhile, I have created LKObjects, so anytime we should use them . No need to delete them. //HPEN hPenBlack = ::CreatePen(PS_SOLID, (5), RGB(0x00,0x0,0x0)); //HPEN hPenWhite = (HPEN)CreatePen(PS_SOLID, (2), RGB(0xff,0xff,0xff)); HPEN hPenBlack = LKPen_Black_N5; HPEN hPenWhite = LKPen_White_N2; HFONT oldfont; HPEN oldpen; oldpen=(HPEN) SelectObject(hdc, hPenBlack); DrawArc(hdc, x, y,radius, rc, 300, 60); int heading = (int)(bearing +0.5); // -----------Draw the detents around the circle----------------------------- double angleDiff = heading % indicatorStep; int screenAngle = (int)(300 - angleDiff); int curHeading = (int)(heading - 60 - angleDiff); TCHAR textBuffer[32]; POINT pt[2]; int i; oldfont=(HFONT)SelectObject(hdc, LK8MediumFont); // always remember to save object or we miss font for(i = - 60; i<= 60; i+=indicatorStep,screenAngle += indicatorStep,curHeading += indicatorStep) { if ( (screenAngle < 300) && (screenAngle > 60) ) { continue; } screenAngle = (int)AngleLimit360(screenAngle); pt[0].x = x + (long) (radius * fastsine(screenAngle) ); pt[0].y = y - (long) (radius * fastcosine(screenAngle) ); // The length of the tickmarks on the compass rose double tickLength; // Make sure the display heading is between 0 and 360 int displayHeading = (int)AngleLimit360(curHeading); // If the heading is a multiple of ten, it gets a long tick if(displayHeading%30==0) { tickLength = 15; if(displayHeading%30==0) { int drawHdg = displayHeading/10; switch ( drawHdg ) { case 0: wsprintf( textBuffer, _T("N")); break; case 9: wsprintf( textBuffer, _T("E")); break; case 18: wsprintf( textBuffer, _T("S")); break; case 27: wsprintf( textBuffer, _T("W")); break; default: wsprintf( textBuffer, _T("%d"), displayHeading/10 ); } SIZE textSize; GetTextExtentPoint(hdc, textBuffer, _tcslen(textBuffer), &textSize); int textX = x + (long) ((radius - (textSize.cy/2)-2) * fastsine(screenAngle) ) - textSize.cx/2; int textY = y - (long) ((radius - (textSize.cy/2)-2) * fastcosine(screenAngle) ); drawOutlineText(hdc,textX,textY ,textBuffer,RGB_WHITE); } } else // Otherwise it gets a short tick tickLength = 10; pt[1].x = x + (long) ((radius -tickLength) * fastsine(screenAngle) ); pt[1].y = y - (long) ((radius -tickLength) * fastcosine(screenAngle) ); SelectObject(hdc, hPenBlack); ::Polyline(hdc,pt,2); SelectObject(hdc, hPenWhite); ::Polyline(hdc,pt,2); } SelectObject(hdc, hPenWhite); DrawArc(hdc, x, y,radius, rc, 300, 60); SelectObject(hdc, oldfont); SelectObject(hdc, oldpen); return 0; }
void MapWindow::DrawTask(HDC hdc, RECT rc, const POINT &Orig_Aircraft) { int i; double tmp; COLORREF whitecolor = RGB_WHITE; COLORREF origcolor = SetTextColor(hDCTemp, whitecolor); HPEN oldpen = 0; HBRUSH oldbrush = 0; static short size_tasklines=0; if (DoInit[MDI_DRAWTASK]) { switch (ScreenSize) { case ss480x272: case ss272x480: case ss320x240: case ss240x320: size_tasklines=NIBLSCALE(4); break; default: size_tasklines=NIBLSCALE(3); break; } DoInit[MDI_DRAWTASK]=false; } if (!WayPointList) return; oldpen = (HPEN) SelectObject(hdc, hpStartFinishThick); oldbrush = (HBRUSH) SelectObject(hdc, GetStockObject(HOLLOW_BRUSH)); LockTaskData(); // protect from external task changes for (i = 1; ValidTaskPoint(i); i++) { if (!ValidTaskPoint(i + 1)) { // final waypoint if (ActiveWayPoint > 1 || !ValidTaskPoint(2)) { // only draw finish line when past the first // waypoint. FIXED 110307: or if task is with only 2 tps DrawStartEndSector(hdc, rc, Task[i].Start, Task[i].End, Task[i].Index, FinishLine, FinishRadius); } } else { // normal sector if (AATEnabled != TRUE) { //_DrawLine(hdc, PS_DASH, NIBLSCALE(3), WayPointList[Task[i].Index].Screen, Task[i].Start, RGB_PETROL, rc); //_DrawLine(hdc, PS_DASH, NIBLSCALE(3), WayPointList[Task[i].Index].Screen, Task[i].End, RGB_PETROL, rc); // DrawDashLine(hdc, size_tasklines, WayPointList[Task[i].Index].Screen, Task[i].Start, RGB_PETROL, rc); // DrawDashLine(hdc, size_tasklines, WayPointList[Task[i].Index].Screen, Task[i].End, RGB_PETROL, rc); } int Type = 0; double Radius = 0.; GetTaskSectorParameter(i, &Type, &Radius); switch (Type) { case CIRCLE: tmp = Radius * zoom.ResScaleOverDistanceModify(); Circle(hdc, WayPointList[Task[i].Index].Screen.x, WayPointList[Task[i].Index].Screen.y, (int) tmp, rc, false, false); break; case SECTOR: tmp = Radius * zoom.ResScaleOverDistanceModify(); Segment(hdc, WayPointList[Task[i].Index].Screen.x, WayPointList[Task[i].Index].Screen.y, (int) tmp, rc, Task[i].AATStartRadial - DisplayAngle, Task[i].AATFinishRadial - DisplayAngle); break; case DAe: if (!AATEnabled) { // this Type exist only if not AAT task // JMW added german rules tmp = 500 * zoom.ResScaleOverDistanceModify(); Circle(hdc, WayPointList[Task[i].Index].Screen.x, WayPointList[Task[i].Index].Screen.y, (int) tmp, rc, false, false); tmp = 10e3 * zoom.ResScaleOverDistanceModify(); Segment(hdc, WayPointList[Task[i].Index].Screen.x, WayPointList[Task[i].Index].Screen.y, (int) tmp, rc, Task[i].AATStartRadial - DisplayAngle, Task[i].AATFinishRadial - DisplayAngle); } break; case LINE: if (!AATEnabled) { // this Type exist only if not AAT task if(ISGAAIRCRAFT) { POINT start,end; double rotation=AngleLimit360(Task[i].Bisector-DisplayAngle); int length=14*ScreenScale; //Make intermediate WP lines always of the same size independent by zoom level start.x=WayPointList[Task[i].Index].Screen.x+(long)(length*fastsine(rotation)); start.y=WayPointList[Task[i].Index].Screen.y-(long)(length*fastcosine(rotation)); rotation=Reciprocal(rotation); end.x=WayPointList[Task[i].Index].Screen.x+(long)(length*fastsine(rotation)); end.y=WayPointList[Task[i].Index].Screen.y-(long)(length*fastcosine(rotation)); _DrawLine(hdc, PS_SOLID, NIBLSCALE(3), start, end, taskcolor, rc); } else _DrawLine(hdc, PS_SOLID, NIBLSCALE(3), Task[i].Start, Task[i].End, taskcolor, rc); } break; case CONE: tmp = Radius * zoom.ResScaleOverDistanceModify(); int center_x = WayPointList[Task[i].Index].Screen.x; int center_y = WayPointList[Task[i].Index].Screen.y; Circle(hdc, center_x, center_y, (int) tmp, rc, false, false); HPEN prevPen = (HPEN)::SelectObject(hdc, hpTerrainLine); for( int j = 1; j < 5 && tmp > 0; ++j) { Circle(hdc, center_x, center_y, tmp -= NIBLSCALE(5), rc, true, true); } ::SelectObject(hdc, prevPen); break; } if (AATEnabled && !DoOptimizeRoute()) { // ELSE HERE IS *** AAT *** // JMW added iso lines if ((i == ActiveWayPoint) || (mode.Is(Mode::MODE_TARGET_PAN) && (i == TargetPanIndex))) { // JMW 20080616 flash arc line if very close to target static bool flip = false; if (DerivedDrawInfo.WaypointDistance < AATCloseDistance()*2.0) { flip = !flip; } else { flip = true; } if (flip) { for (int j = 0; j < MAXISOLINES - 1; j++) { if (TaskStats[i].IsoLine_valid[j] && TaskStats[i].IsoLine_valid[j + 1]) { _DrawLine(hdc, PS_SOLID, NIBLSCALE(2), TaskStats[i].IsoLine_Screen[j], TaskStats[i].IsoLine_Screen[j + 1], RGB(0, 0, 255), rc); } } } } } } } if ((ActiveWayPoint < 2) && ValidTaskPoint(0) && ValidTaskPoint(1)) { DrawStartEndSector(hdc, rc, Task[0].Start, Task[0].End, Task[0].Index, StartLine, StartRadius); if (EnableMultipleStartPoints) { for (i = 0; i < MAXSTARTPOINTS; i++) { if (StartPoints[i].Active && ValidWayPoint(StartPoints[i].Index)) { DrawStartEndSector(hdc, rc, StartPoints[i].Start, StartPoints[i].End, StartPoints[i].Index, StartLine, StartRadius); } } } } for (i = 0; ValidTaskPoint(i + 1); i++) { int imin = min(Task[i].Index, Task[i + 1].Index); int imax = max(Task[i].Index, Task[i + 1].Index); // JMW AAT! double bearing = Task[i].OutBound; POINT sct1, sct2; if (AATEnabled) { LatLon2Screen(Task[i].AATTargetLon, Task[i].AATTargetLat, sct1); LatLon2Screen(Task[i + 1].AATTargetLon, Task[i + 1].AATTargetLat, sct2); DistanceBearing(Task[i].AATTargetLat, Task[i].AATTargetLon, Task[i + 1].AATTargetLat, Task[i + 1].AATTargetLon, NULL, &bearing); // draw nominal track line DrawDashLine(hdc, NIBLSCALE(1), // 091217 WayPointList[imin].Screen, WayPointList[imax].Screen, taskcolor, rc); } else { sct1 = WayPointList[imin].Screen; sct2 = WayPointList[imax].Screen; } if ((i >= ActiveWayPoint && DoOptimizeRoute()) || !DoOptimizeRoute()) { POINT ClipPt1 = sct1, ClipPt2 = sct2; if(LKGeom::ClipLine((POINT) {rc.left, rc.top}, (POINT) {rc.right, rc.bottom}, ClipPt1, ClipPt2)) { DrawMulticolorDashLine(hdc, size_tasklines, sct1, sct2, taskcolor, RGB_BLACK,rc); // draw small arrow along task direction POINT p_p; POINT Arrow[2] = { {6, 6}, {-6, 6} }; ScreenClosestPoint(sct1, sct2, Orig_Aircraft, &p_p, NIBLSCALE(25)); threadsafePolygonRotateShift(Arrow, 2, p_p.x, p_p.y, bearing - DisplayAngle); _DrawLine(hdc, PS_SOLID, size_tasklines-NIBLSCALE(1), Arrow[0], p_p, taskcolor, rc); _DrawLine(hdc, PS_SOLID, size_tasklines-NIBLSCALE(1), Arrow[1], p_p, taskcolor, rc); } } } // Draw DashLine From current position to Active TurnPoint center if(ValidTaskPoint(ActiveWayPoint)) { POINT ptStart; LatLon2Screen(DrawInfo.Longitude, DrawInfo.Latitude, ptStart); DrawDashLine(hdc, NIBLSCALE(1), ptStart, WayPointList[Task[ActiveWayPoint].Index].Screen, taskcolor, rc); } { UnlockTaskData(); } // restore original color SetTextColor(hDCTemp, origcolor); SelectObject(hdc, oldpen); SelectObject(hdc, oldbrush); }
rectObj MapWindow::CalculateScreenBounds(double scale, const RECT& rc) { // compute lat lon extents of visible screen rectObj sb; if (scale>= 1.0) { POINT screen_center; LatLon2Screen(PanLongitude, PanLatitude, screen_center); sb.minx = sb.maxx = PanLongitude; sb.miny = sb.maxy = PanLatitude; unsigned int dx, dy; unsigned int maxsc=0; dx = screen_center.x-rc.right; dy = screen_center.y-rc.top; maxsc = max(maxsc, dx*dx+dy*dy); dx = screen_center.x-rc.left; dy = screen_center.y-rc.top; maxsc = max(maxsc, dx*dx+dy*dy); dx = screen_center.x-rc.left; dy = screen_center.y-rc.bottom; maxsc = max(maxsc, dx*dx+dy*dy); dx = screen_center.x-rc.right; dy = screen_center.y-rc.bottom; maxsc = max(maxsc, dx*dx+dy*dy); maxsc = isqrt4(maxsc); for (int i=0; i<10; i++) { double ang = i*360.0/10; POINT p; double X, Y; p.x = screen_center.x + iround(fastcosine(ang)*maxsc*scale); p.y = screen_center.y + iround(fastsine(ang)*maxsc*scale); Screen2LatLon(p.x, p.y, X, Y); sb.minx = min(X, sb.minx); sb.miny = min(Y, sb.miny); sb.maxx = max(X, sb.maxx); sb.maxy = max(Y, sb.maxy); } } else { double xmin, xmax, ymin, ymax; int x, y; double X, Y; x = rc.left; y = rc.top; Screen2LatLon(x, y, X, Y); xmin = X; xmax = X; ymin = Y; ymax = Y; x = rc.right; y = rc.top; Screen2LatLon(x, y, X, Y); xmin = min(xmin, X); xmax = max(xmax, X); ymin = min(ymin, Y); ymax = max(ymax, Y); x = rc.right; y = rc.bottom; Screen2LatLon(x, y, X, Y); xmin = min(xmin, X); xmax = max(xmax, X); ymin = min(ymin, Y); ymax = max(ymax, Y); x = rc.left; y = rc.bottom; Screen2LatLon(x, y, X, Y); xmin = min(xmin, X); xmax = max(xmax, X); ymin = min(ymin, Y); ymax = max(ymax, Y); sb.minx = xmin; sb.maxx = xmax; sb.miny = ymin; sb.maxy = ymax; } return sb; }
bool DoTarget(NMEA_INFO *Basic, DERIVED_INFO *Calculated) { double x0, y0, etas, ttgo=0; double bearing, distance; if (LKTargetIndex<0 || LKTargetIndex>=MAXTRAFFIC) return false; // DoTarget is called from MapWindow, in real time. We have enough CPU power there now #if 0 if ( LastDoTarget > Basic->Time ) LastDoTarget=Basic->Time; // We calculate in real time, because PFLAA sentences are calculated too in real time if ( Basic->Time < (LastDoTarget+3.0) ) { return false; } LastDoTarget=Basic->Time; #endif #ifdef DEBUG_LKT StartupStore(_T("... DoTarget Copy LKTraffic\n")); #endif //LockFlightData(); memcpy(LKTraffic, Basic->FLARM_Traffic, sizeof(LKTraffic)); //UnlockFlightData(); if (LKTARG.ID <=0) return false; DistanceBearing(Basic->Latitude, Basic->Longitude, LKTARG.Latitude, LKTARG.Longitude, &distance, &bearing); LKTARG.Distance=distance; LKTARG.Bearing=bearing; if (LKTARG.Speed>1) { x0 = fastsine(LKTARG.TrackBearing)*LKTARG.Speed; y0 = fastcosine(LKTARG.TrackBearing)*LKTARG.Speed; x0 += fastsine(Calculated->WindBearing)*Calculated->WindSpeed; y0 += fastcosine(Calculated->WindBearing)*Calculated->WindSpeed; // LKTARG.Heading = AngleLimit360(atan2(x0,y0)*RAD_TLK_DEG); // 101210 check etas = isqrt4((unsigned long)(x0*x0*100+y0*y0*100))/10.0; LKASSERT(AirDensityRatio(LKTARG.Altitude)!=0); LKTARG.EIAS = etas/AirDensityRatio(LKTARG.Altitude); } else { LKTARG.EIAS=0; } //double height_above_target = Calculated->NavAltitude - LKTARG.Altitude; // We DONT use EnergyHeight here because we are not considering the Target's TE either LKTARG.AltArriv = Calculated->NavAltitude - GlidePolar::MacCreadyAltitude(MACCREADY, distance, bearing, Calculated->WindSpeed, Calculated->WindBearing, 0, 0, // final glide, use wind true, &ttgo) - LKTARG.Altitude; // We CANNOT use RelativeAltitude because when ghost or zombie, it wont be updated in real time in respect // to OUR real position!! Lets use the last target altitude known. double relalt=Calculated->NavAltitude - LKTARG.Altitude; if (relalt==0) LKTARG.GR=999; else { // we need thus to invert the relative altitude LKTARG.GR=distance/(relalt); } return true; }