void MapWindow::DrawBestCruiseTrack(LKSurface& Surface, const POINT& Orig) { if (OvertargetMode>OVT_TASK) return; if (!ValidTaskPoint(ActiveTaskPoint)) return; if (DerivedDrawInfo.WaypointDistance < 0.010) return; // dont draw bestcruise indicator if not needed if (fabs(DerivedDrawInfo.BestCruiseTrack-DerivedDrawInfo.WaypointBearing)<2) { // 091202 10 to 2 return; } const auto hpOld = Surface.SelectObject(LKPen_Blue_N1); const auto hbOld = Surface.SelectObject(LKBrush_Blue); if (Appearance.BestCruiseTrack == ctBestCruiseTrackDefault){ int dy = (long)(70); POINT Arrow[7] = { {-1,-40}, {1,-40}, {1,0}, {6,8}, {-6,8}, {-1,0}, {-1,-40}}; Arrow[2].y -= dy; Arrow[3].y -= dy; Arrow[4].y -= dy; Arrow[5].y -= dy; PolygonRotateShift(Arrow, 7, Orig.x, Orig.y, DerivedDrawInfo.BestCruiseTrack-DisplayAngle); Surface.Polygon(Arrow,7); } else if (Appearance.BestCruiseTrack == ctBestCruiseTrackAltA){ POINT Arrow[] = { {-1,-40}, {-1,-62}, {-6,-62}, {0,-70}, {6,-62}, {1,-62}, {1,-40}, {-1,-40}}; PolygonRotateShift(Arrow, sizeof(Arrow)/sizeof(Arrow[0]), Orig.x, Orig.y, DerivedDrawInfo.BestCruiseTrack-DisplayAngle); Surface.Polygon(Arrow, (sizeof(Arrow)/sizeof(Arrow[0]))); } Surface.SelectObject(hpOld); Surface.SelectObject(hbOld); }
void Statistics::DrawFilledLineGraph(LKSurface& Surface, const RECT& rc, LeastSquares* lsdata, const LKColor& color) { POINT line[4]; for (int i=0; i<lsdata->sum_n-1; i++) { line[0].x = (int)((lsdata->xstore[i]-x_min)*xscale)+rc.left+BORDER_X; line[0].y = (int)((y_max-lsdata->ystore[i])*yscale)+rc.top; line[1].x = (int)((lsdata->xstore[i+1]-x_min)*xscale)+rc.left+BORDER_X; line[1].y = (int)((y_max-lsdata->ystore[i+1])*yscale)+rc.top; line[2].x = line[1].x; line[2].y = rc.bottom-BORDER_Y; line[3].x = line[0].x; line[3].y = rc.bottom-BORDER_Y; Surface.Polygon(line, 4); } }
// This is painting traffic icons on the screen. void MapWindow::LKDrawFLARMTraffic(LKSurface& Surface, const RECT& rc, const ScreenProjection& _Proj, const POINT& Orig_Aircraft) { if (!EnableFLARMMap) return; if (!DrawInfo.FLARM_Available) return; // init scaled coords for traffic icon static int iCircleSize = 7; static int iRectangleSize = 4; static short tscaler=0; if (DoInit[MDI_DRAWFLARMTRAFFIC]) { switch (ScreenSize) { case ss480x640: case ss480x800: case ss800x480: case ss640x480: iCircleSize = 9; iRectangleSize = 5; tscaler=NIBLSCALE(7)-2; break; case ss240x320: case ss272x480: case ss320x240: case ss480x272: case ss480x234: case ss400x240: iCircleSize = 7; iRectangleSize = 4; tscaler=NIBLSCALE(13)-2; break; default: iCircleSize = 7; iRectangleSize = 4; tscaler=NIBLSCALE(7); break; } DoInit[MDI_DRAWFLARMTRAFFIC]=false; } POINT Arrow[5]; TCHAR lbuffer[50]; const auto hpold = Surface.SelectObject(LKPen_Black_N1); int i; int painted=0; // double dX, dY; TextInBoxMode_t displaymode = {0}; displaymode.NoSetFont = 1; #if 0 double screenrange = GetApproxScreenRange(); double scalefact = screenrange/6000.0; // FIX 100820 #endif const auto oldfont = Surface.SelectObject(LK8MapFont); for (i=0,painted=0; i<FLARM_MAX_TRAFFIC; i++) { // limit to 10 icons map traffic if (painted>=10) { i=FLARM_MAX_TRAFFIC; continue; } if ( (DrawInfo.FLARM_Traffic[i].ID !=0) && (DrawInfo.FLARM_Traffic[i].Status != LKT_ZOMBIE) ) { painted++; double target_lon; double target_lat; target_lon = DrawInfo.FLARM_Traffic[i].Longitude; target_lat = DrawInfo.FLARM_Traffic[i].Latitude; #if (0) // No scaling, wrong if ((EnableFLARMMap==2)&&(scalefact>1.0)) { double distance; double bearing; DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, target_lat, target_lon, &distance, &bearing); FindLatitudeLongitude(DrawInfo.Latitude, DrawInfo.Longitude, bearing, distance*scalefact, &target_lat, &target_lon); } #endif POINT sc, sc_name, sc_av; sc = _Proj.LonLat2Screen(target_lon, target_lat); sc_name = sc; sc_name.y -= NIBLSCALE(16); sc_av = sc_name; _tcscpy(lbuffer,_T("")); if (DrawInfo.FLARM_Traffic[i].Cn && DrawInfo.FLARM_Traffic[i].Cn[0]!=_T('?')) { // 100322 _tcscat(lbuffer,DrawInfo.FLARM_Traffic[i].Cn); } if (DrawInfo.FLARM_Traffic[i].Average30s>=0.1) { size_t len = _tcslen(lbuffer); if (len > 0) _stprintf(lbuffer + len,_T(":%.1f"),LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s); else _stprintf(lbuffer,_T("%.1f"),LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s); } displaymode.Border=1; if (_tcslen(lbuffer)>0) TextInBox(Surface, &rc, lbuffer, sc.x+tscaler, sc.y+tscaler, &displaymode, false); // red circle if ((DrawInfo.FLARM_Traffic[i].AlarmLevel>0) && (DrawInfo.FLARM_Traffic[i].AlarmLevel<4)) { DrawBitmapIn(Surface, sc, hFLARMTraffic,true); } #if 1 // 1 Arrow[0].x = -4; Arrow[0].y = 5; Arrow[1].x = 0; Arrow[1].y = -6; Arrow[2].x = 4; Arrow[2].y = 5; Arrow[3].x = 0; Arrow[3].y = 2; Arrow[4].x = -4; Arrow[4].y = 5; for (int q=0; q < 5; q++) { Arrow[q].x = (LONG) ((double)Arrow[q].x * 1.7); Arrow[q].y = (LONG) ((double)Arrow[q].y * 1.7); } #else Arrow[0].x = scaler[0]; Arrow[0].y = scaler[1]; Arrow[1].x = 0; Arrow[1].y = scaler[2]; Arrow[2].x = scaler[3]; Arrow[2].y = scaler[1]; Arrow[3].x = 0; Arrow[3].y = scaler[4]; Arrow[4].x = scaler[0]; Arrow[4].y = scaler[1]; #endif /* switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321 case LKT_GHOST: Surface.SelectObject(yellowBrush); break; case LKT_ZOMBIE: Surface.SelectObject(redBrush); break; default: Surface.SelectObject(greenBrush); break; } */ /************************************************************************* * calculate climb color *************************************************************************/ int iVarioIdx = (int)(2*DrawInfo.FLARM_Traffic[i].Average30s -0.5)+NO_VARIO_COLORS/2; if(iVarioIdx < 0) iVarioIdx =0; if(iVarioIdx >= NO_VARIO_COLORS) iVarioIdx =NO_VARIO_COLORS-1; Surface.SelectObject(*variobrush[iVarioIdx]); switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321 case LKT_GHOST: Surface.Rectangle(sc.x-iRectangleSize, sc.y-iRectangleSize,sc.x+iRectangleSize, sc.y+iRectangleSize); break; case LKT_ZOMBIE: Surface.DrawCircle(sc.x, sc.x, iCircleSize, rc, true ); break; default: PolygonRotateShift(Arrow, 5, sc.x, sc.y, DrawInfo.FLARM_Traffic[i].TrackBearing - DisplayAngle); Surface.Polygon(Arrow,5); break; } } } Surface.SelectObject(oldfont); Surface.SelectObject(hpold); }
void Topology::Paint(LKSurface& Surface, const RECT& rc) { if (!shapefileopen) return; bool nolabels=false; // 130217 scaleCat 5 and 10 are the same! So careful.. if (scaleCategory==10||scaleCategory==5) { // for water areas, use scaleDefault if ( MapWindow::zoom.RealScale()>scaleDefaultThreshold) { return; } // since we just checked category 10, if we are over scale we set nolabels if ( MapWindow::zoom.RealScale()>scaleThreshold) nolabels=true; } else if (MapWindow::zoom.RealScale() > scaleThreshold) return; // TODO code: only draw inside screen! // this will save time with rendering pixmaps especially // checkVisible does only check lat lon , not screen pixels.. // We need to check also screen. const auto hpOld = Surface.SelectObject(hPen); LKSurface::OldBrush hbOld {}; if (hbBrush) { hbOld = Surface.SelectObject(hbBrush); } const auto hfOld = Surface.SelectObject(MapTopologyFont); // get drawing info int iskip = 1; // attempt to bugfix 100615 polyline glitch with zoom over 33Km // do not skip points, if drawing coast lines which have a scaleThreshold of 100km! // != 5 and != 10 if (scaleCategory>10) { if (MapWindow::zoom.RealScale()>0.25*scaleThreshold) { iskip = 2; } if (MapWindow::zoom.RealScale()>0.5*scaleThreshold) { iskip = 3; } if (MapWindow::zoom.RealScale()>0.75*scaleThreshold) { iskip = 4; } } // use the already existing screenbounds_latlon, calculated by CalculateScreenPositions in MapWindow2 rectObj screenRect = MapWindow::screenbounds_latlon; static POINT pt[MAXCLIPPOLYGON]; for (int ixshp = 0; ixshp < shpfile.numshapes; ixshp++) { XShape *cshape = shpCache[ixshp]; if (!cshape || cshape->hide) continue; shapeObj *shape = &(cshape->shape); switch(shape->type) { case(MS_SHAPE_POINT):{ #if 101016 // -------------------------- NOT PRINTING ICONS --------------------------------------------- bool dobitmap=false; if (scaleCategory<90 || (MapWindow::zoom.RealScale()<2)) dobitmap=true; // first a latlon overlap check, only approximated because of fastcosine in latlon2screen if (checkVisible(*shape, screenRect)) for (int tt = 0; tt < shape->numlines; tt++) { for (int jj=0; jj< shape->line[tt].numpoints; jj++) { POINT sc; MapWindow::LatLon2Screen(shape->line[tt].point[jj].x, shape->line[tt].point[jj].y, sc); if (dobitmap) { // bugfix 101212 missing case for scaleCategory 0 (markers) if (scaleCategory==0||cshape->renderSpecial(Surface, sc.x, sc.y, rc)) MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true); } else { cshape->renderSpecial(Surface, sc.x, sc.y, rc); } } } } #else // -------------------------- PRINTING ICONS --------------------------------------------- // no bitmaps for small town over a certain zoom level and no bitmap if no label at all levels bool nobitmap=false, noiconwithnolabel=false; if (scaleCategory==90 || scaleCategory==100) { noiconwithnolabel=true; if (MapWindow::MapScale>4) nobitmap=true; } if (checkVisible(*shape, screenRect)) for (int tt = 0; tt < shape->numlines; tt++) { for (int jj=0; jj< shape->line[tt].numpoints; jj++) { POINT sc; MapWindow::LatLon2Screen(shape->line[tt].point[jj].x, shape->line[tt].point[jj].y, sc); if (!nobitmap) #if 101016 // only paint icon if label is printed too if (noiconwithnolabel) { if (cshape->renderSpecial(Surface, sc.x, sc.y,labelprinted)) MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true); } else { MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true); cshape->renderSpecial(Surface, sc.x, sc.y,labelprinted); } #else MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true); cshape->renderSpecial(Surface, sc.x, sc.y); #endif } } } #endif // Use optimized point icons 1.23e break; case(MS_SHAPE_LINE): if (checkVisible(*shape, screenRect)) for (int tt = 0; tt < shape->numlines; ++tt) { int minx = rc.right; int miny = rc.bottom; int msize = min(shape->line[tt].numpoints, MAXCLIPPOLYGON); MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize, 1); for (int jj=0; jj< msize; ++jj) { if (pt[jj].x<=minx) { minx = pt[jj].x; miny = pt[jj].y; } } Surface.Polyline(pt, msize, rc); cshape->renderSpecial(Surface,minx,miny,rc); } break; case(MS_SHAPE_POLYGON): // if it's a water area (nolabels), print shape up to defaultShape, but print // labels only up to custom label levels if ( nolabels ) { if (checkVisible(*shape, screenRect)) { for (int tt = 0; tt < shape->numlines; ++tt) { int msize = min(shape->line[tt].numpoints/iskip, MAXCLIPPOLYGON); MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize*iskip, iskip); Surface.Polygon(pt, msize, rc); } } } else if (checkVisible(*shape, screenRect)) { for (int tt = 0; tt < shape->numlines; ++tt) { int minx = rc.right; int miny = rc.bottom; int msize = min(shape->line[tt].numpoints/iskip, MAXCLIPPOLYGON); MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize*iskip, iskip); for (int jj=0; jj< msize; ++jj) { if (pt[jj].x<=minx) { minx = pt[jj].x; miny = pt[jj].y; } } Surface.Polygon(pt, msize, rc); cshape->renderSpecial(Surface,minx,miny,rc); } } break; default: break; } }
void MapWindow::DrawRunway(LKSurface& Surface, const WAYPOINT* wp, const RECT& rc, const ScreenProjection* _Proj, double fScaleFact, BOOL picto) { if(!picto && !_Proj) { // if we don't draw picto ScreenProjection parameter are mandatory. assert(false); return; } int solid= false; bool bGlider = false; bool bOutland = false; bool bRunway = false; static double rwl = 8; static double rwb = 1; static double cir = 6; static double scale_drawradio=0; static double scale_bigfont=0; static double scale_fullinfos=0; RasterPoint Center; if(picto) { Center.x = rc.left+ (rc.right- rc.left)/2; Center.y = rc.bottom +(rc.top-rc.bottom)/2; } else { Center = _Proj->ToRasterPoint(wp->Latitude, wp->Longitude); } int l,p,b; if(picto) fScaleFact /=2000; else fScaleFact /=1600; if (DoInit[MDI_MAPWPVECTORS]) { // // How long and thick is the runway drawn, and how big is the circle. // No rule possible, it depends on how we are dealing with many other // custom things on screen, because LK is drawing differently depending // on geometry, resolution, orientation. We dont split bits. // switch(ScreenSize) { case ss240x320: rwl = 9.0; rwb = 2.0;cir = 4.0; break; // 43 case ss240x400: rwl = 9.0; rwb = 1.0;cir = 4.0; break; // 53 case ss272x480: rwl = 9.0; rwb = 2.5;cir = 4.0; break; // 169 case ss480x640: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 43 case ss600x800: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 43 case ss480x800: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 53 case sslandscape: rwl = 6.0; rwb = 1.0;cir = 5.0; break; // sslandscape is never assigned! case ss320x240: rwl = 9.0; rwb = 2.0;cir = 4.0; break; // 43 case ss400x240: rwl = 9.0; rwb = 1.0;cir = 4.0; break; // 53 case ss480x234: rwl = 9.0; rwb = 1.0;cir = 4.0; break; // 21 case ss480x272: rwl = 9.0; rwb = 2.5;cir = 4.0; break; // 169 case ss640x480: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 43 case ss800x600: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 43 case ss800x480: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 53 case ssnone: #if defined(ANDROID) || defined(KOBO) rwl = 6.0; rwb = 2.5; cir = 5.0; break; #else // the line above is only a workaround to avoid runaway to be tool long on Anrtoid and Kobo // waiting for a definitive and more elegant solution. // #define X ScreenSizeX== #define Y ScreenSizeY== // Ok this doesnt look nice, but lets remember we are inside a DoInit. // Generally the generic setup is good for everyone, but in case we // can make it custom for any resolution. if (X 1024 && Y 768) {; rwl = 4.5; rwb = 2.5; cir = 5.0; } else if (X 1014 && Y 758) {; rwl = 4.5; rwb = 2.5; cir = 5.0; } else if (X 720 && Y 408) {; rwl = 10.0; rwb = 6.0; cir = 5.0; } else if (X 720 && Y 432) {; rwl = 10.0; rwb = 4.0; cir = 5.0; } else // .. and this is the rule of thumb, I could not find a better idea // I think it is easier to redesign the drawing approach and make it // really scalable. // // This hack works for: 800x600 960x540 1280x720 (and relative portrait modes) // These are the screen resolutions used by kobo, samsung s4 mini and s5 mini // if (ScreenLandscape) { if (ScreenSizeX<=480) { // testlk> Ok: t5 Bad for: - rwl = 9.0*(480.0/ScreenSizeX); rwb = 2.5*(480.0/ScreenSizeX); cir = 4.0; } else { // testlk> Ok: 3,13,14,22 Bad: t4, t15, t23 rwl = 6.0; rwb = 2.5; cir = 5.0; } } else { if (ScreenSizeX<480) { // testlk> Ok: 10,19 Bad for: 20 rwl = 6.0*(480.0/ScreenSizeX); rwb = 2.5*(480.0/ScreenSizeX); cir = 4.0; } else { // testlk> Ok: 8,28 Bad for: - rwl = 6.0; rwb = 2.5; cir = 5.0; } } break; #endif } // // These are the (absolute) scale thresholds for painting informations // For example, paint just radio starting from 5.0km (3.6abs) etc. // There is no rule possible, it matters only testing. // switch(ScreenSize) { case ss480x272: scale_drawradio=2.6; scale_bigfont=1.1; scale_fullinfos=0.8; break; case ss800x480: scale_drawradio=2.6; scale_bigfont=1.5; scale_fullinfos=1.5; break; case ss640x480: scale_drawradio=3.6; scale_bigfont=1.5; scale_fullinfos=1.5; break; default: scale_drawradio=3.6; scale_bigfont=1.5; scale_fullinfos=1.5; break; } DoInit[MDI_MAPWPVECTORS]=false; } if( wp->RunwayLen > 100) /* square if no runway defined */ { if (picto) l = (int) (rwl); else { #ifndef __linux__ // We cant rescale runways , no method found. if (ScreenSize==ssnone) l = (int) (rwl * (1.0+ (680.0/800.0-1.0)/4.0)); // wtf..! else #endif l = (int) (rwl * (1.0+ ((double)wp->RunwayLen/800.0-1.0)/4.0)); } b = (int) (rwb/1.5 ); } else { l = (int)( rwl*0.5); b = l ; } #if defined(ANDROID) || defined(KOBO) l = (int)(l * 2.0 * fScaleFact / ScreenScale); if(l==0) l=1; b = (int)(b * 2.0 * fScaleFact / ScreenScale); if(b==0) b=1; p = (int)(cir * 2.0 * fScaleFact); if(p==0) p=1; #else l = (int)(l * fScaleFact); if(l==0) l=1; b = (int)(b * fScaleFact); if(b==0) b=1; p = (int)(cir * 2.0 * fScaleFact); if(p==0) p=1; #endif switch(wp->Style) { case STYLE_AIRFIELDSOLID: solid = true; bRunway = true; bOutland = false; bGlider = false; break; case STYLE_AIRFIELDGRASS: solid = false; bRunway = true; bOutland = false; bGlider = false; break; case STYLE_OUTLANDING : solid = false; bRunway = true; bOutland = true; bGlider = false; b*=2; break; case STYLE_GLIDERSITE : solid = false; bRunway = true; bOutland = false; bGlider = true; break; default: return; break; } // Do not print glidersite at low zoom levels, in any case // not useful on some resolutions // if( !picto && (MapWindow::zoom.RealScale() > 3) ) // bGlider=false; const auto oldPen = Surface.SelectObject(LK_BLACK_PEN); const auto oldBrush = Surface.SelectObject(LKBrush_Red); if( wp->Reachable == TRUE) Surface.SelectObject(LKBrush_Green); if(!bOutland) { if (picto) Surface.DrawCircle(Center.x, Center.y, p, true); else Surface.DrawCircle(Center.x, Center.y, p, rc, true); } if(bRunway) { POINT Runway[5] = { { b, l }, // 1 {-b, l }, // 2 {-b,-l }, // 3 { b,-l }, // 4 { b,l } // 5 }; if(!bOutland) { #ifndef DITHER if(solid) Surface.SelectObject(LKBrush_DarkGrey ); else Surface.SelectObject(LKBrush_White); #else if(solid) Surface.SelectObject(LKBrush_Black); else Surface.SelectObject(LKBrush_White); #endif } if(picto) { threadsafePolygonRotateShift(Runway, 5, Center.x, Center.y, wp->RunwayDir); } else { PolygonRotateShift(Runway, 5, Center.x, Center.y, wp->RunwayDir- (int)MapWindow::GetDisplayAngle()); } Surface.Polygon(Runway ,5 ); } // bRunway if(fScaleFact >= 0.9) { if(bGlider) { int iScale = (int)(fScaleFact*2.0); double fFact = 0.04*fScaleFact/1.5; if(iScale==0) iScale=1; POINT WhiteWing [17] = { { (long)(-228 * fFact ) , (long)(13 * fFact)}, //1 { (long) (-221 * fFact ) , (long)(-5 * fFact)}, //2 { (long) (-102 * fFact ) , (long)(-50 * fFact)}, //3 { (long) (8 * fFact ) , (long)( 5 * fFact)}, //4 { (long) (149 * fFact ) , (long)(-55 * fFact)}, //5 { (long) (270 * fFact ) , (long)(-12 * fFact)}, //6 { (long) (280 * fFact ) , (long)( 5 * fFact)}, //7 { (long) (152 * fFact ) , (long)(-30 * fFact)}, //8 { (long) (48 * fFact ) , (long)( 27 * fFact)}, //9 { (long) (37 * fFact ) , (long)( 44 * fFact)}, //10 { (long)(-20 * fFact ) , (long)( 65 * fFact)}, //11 { (long)(-29 * fFact ) , (long)( 80 * fFact)}, //12 { (long)(-56 * fFact ) , (long)( 83 * fFact)}, //13 { (long)(-50 * fFact ) , (long)( 40 * fFact)}, //14 { (long)(-30 * fFact ) , (long)( 27 * fFact)}, //15 { (long)(-103 * fFact ) , (long)(-26 * fFact)}, //16 { (long)(-228 * fFact ) , (long)( 13 * fFact)} //17 }; if (picto) threadsafePolygonRotateShift(WhiteWing, 17, Center.x, Center.y, 0/*+ wp->RunwayDir-Brg*/); else PolygonRotateShift(WhiteWing, 17, Center.x, Center.y, 0/*+ wp->RunwayDir-Brg*/); Surface.Polygon(WhiteWing ,17 ); } } // StartupStore(_T(".......fscale=%f *1600=%f realscale = %f\n"), fScaleFact, fScaleFact*1600, MapWindow::zoom.RealScale()); if( !picto && (MapWindow::zoom.RealScale() <= scale_drawradio) ) { const auto hfOld = Surface.SelectObject(MapWindow::zoom.RealScale() <= scale_bigfont ? LK8PanelUnitFont : LK8GenericVar02Font); #ifndef DITHER if (INVERTCOLORS) Surface.SelectObject(LKBrush_Petrol); else Surface.SelectObject(LKBrush_LightCyan); #else if (INVERTCOLORS) Surface.SelectObject(LKBrush_Black); else Surface.SelectObject(LKBrush_White); #endif unsigned int offset = p + NIBLSCALE(1) ; { if ( _tcslen(wp->Freq)>0 ) { MapWindow::LKWriteBoxedText(Surface,rc,wp->Freq, Center.x- offset, Center.y -offset, WTALIGN_RIGHT, RGB_WHITE, RGB_BLACK); } // // Full infos! 1.5km scale // if (MapWindow::zoom.RealScale() <=scale_fullinfos) { if ( _tcslen(wp->Code)==4 ) { MapWindow::LKWriteBoxedText(Surface,rc,wp->Code,Center.x + offset, Center.y - offset, WTALIGN_LEFT, RGB_WHITE,RGB_BLACK); } if (wp->Altitude >0) { TCHAR tAlt[20]; _stprintf(tAlt,_T("%.0f %s"),wp->Altitude*ALTITUDEMODIFY,Units::GetUnitName(Units::GetUserAltitudeUnit())); MapWindow::LKWriteBoxedText(Surface,rc,tAlt, Center.x + offset, Center.y + offset, WTALIGN_LEFT, RGB_WHITE, RGB_BLACK); } } } Surface.SelectObject(hfOld); } Surface.SelectObject(oldPen); Surface.SelectObject(oldBrush); }
// draw aircraft void RenderPlaneSideview(LKSurface& Surface, double fDist, double fAltitude,double brg, DiagrammStruct* psDia ) { //BOOL bInvCol = true ; //INVERTCOLORS #define NO_AP_PTS 17 int deg = DEG_TO_INT(AngleLimit360(brg)); double fCos = COSTABLE[deg]; double fSin = SINETABLE[deg]; int TAIL = 6; int PROFIL = 1; int FINB = 3; int BODY = 2; int NOSE = 7; int WING = (int) (22.0 ); int TUBE = (int) (14.0 ) ; int FINH = 6+BODY; POINT Start; int HEAD = TUBE / 2; TUBE = 3 * TUBE/ 2; POINT AircraftSide [8] = { {(int)(fSin * (HEAD+0 ) ), -BODY-1}, // 1 {(int)(fSin * (HEAD+NOSE) ), 0}, // 2 {(int)(fSin * (HEAD+0 ) ), BODY+1}, // 3 {(int)(fSin * (-TUBE) ), BODY}, // 4 -1 {(int)(fSin * -TUBE ), -FINH}, // 5 {(int)(fSin * (-TUBE+FINB) ), -FINH}, // 6 {(int)(fSin * (-TUBE+FINB+3) ), -BODY+1}, // 7 +1 {(int)(fSin * (HEAD+0) ), -BODY-1} // 8 }; #define FACT 2 BODY = (int)((double)(BODY+1) * fCos * fCos); int DIA = (BODY + PROFIL); /* both wings */ POINT AircraftWing [13] = { {(int)(fCos * BODY ) , -DIA}, // 1 {(int)(fCos * (int)( FACT*BODY) ), -PROFIL}, // 2 {(int)(fCos * WING ) , -PROFIL}, // 3 {(int)(fCos * WING ), 0* PROFIL}, // 4 {(int)(fCos * (int)( FACT*BODY) ) , PROFIL}, // 5 {(int)(fCos * BODY ), DIA}, // 6 {(int)(fCos * -BODY ) , DIA}, // 7 {(int)(fCos * (int)( -FACT*BODY)), PROFIL}, // 8 {(int)(fCos * -WING ), 0* PROFIL }, // 9 {(int)(fCos * -WING ) , -PROFIL} , // 10 {(int)(fCos * (int)( -FACT*BODY)), -PROFIL}, // 11 {(int)(fCos * -BODY ) , -DIA}, // 12 {(int)(fCos * BODY ), -DIA} // 13 }; POINT AircraftWingL [7] = { {(int)(0 * -BODY ), DIA }, // 1 {(int)(fCos * (int)( -FACT*BODY)), PROFIL }, // 2 {(int)(fCos * -WING ), 0* PROFIL }, // 3 {(int)(fCos * -WING ), -PROFIL }, // 4 {(int)(fCos * (int)( -FACT*BODY)), -PROFIL }, // 5 {(int)(0 * -BODY ), -DIA }, // 6 {(int)(0 * -BODY ), DIA } // 7 }; POINT AircraftWingR [7] = { {(int)(0 * BODY ) , -DIA }, // 1 {(int)(fCos * (int)( FACT*BODY) ) , -PROFIL }, // 2 {(int)(fCos * WING ) , -PROFIL }, // 3 {(int)(fCos * WING ) , 0* PROFIL}, // 4 {(int)(fCos * (int)( FACT*BODY) ) , PROFIL }, // 5 {(int)(0 * BODY ) , DIA }, // 6 {(int)(0 * BODY ) , -DIA } // 7 }; POINT AircraftTail [5] = { {(int)(fCos * TAIL - fSin*TUBE), -FINH}, // 1 {(int)(fCos * TAIL - fSin*TUBE), -FINH +PROFIL}, // 2 {(int)(fCos * -TAIL - fSin*TUBE), -FINH +PROFIL}, // 3 {(int)(fCos * -TAIL - fSin*TUBE), -FINH }, // 4 {(int)(fCos * TAIL - fSin*TUBE), -FINH}, // 5 }; Start.x = CalcDistanceCoordinat(fDist, psDia); Start.y = CalcHeightCoordinat(fAltitude, psDia); const auto oldPen = Surface.SelectObject(LK_BLACK_PEN); const auto oldBrush = Surface.SelectObject(LKBrush_White); PolygonRotateShift(AircraftWing, 13, Start.x, Start.y, 0); PolygonRotateShift(AircraftSide, 8, Start.x, Start.y, 0); PolygonRotateShift(AircraftTail, 5, Start.x, Start.y, 0); PolygonRotateShift(AircraftWingL, 7, Start.x, Start.y, 0); PolygonRotateShift(AircraftWingR, 7, Start.x, Start.y, 0); #ifndef UNDITHER LKBrush GreenBrush(RGB_GREEN); LKBrush RedBrush(RGB_RED); #else LKBrush GreenBrush(RGB_WHITE); LKBrush RedBrush(RGB_BLACK); #endif if((brg < 180)) { Surface.SelectObject(RedBrush); Surface.Polygon(AircraftWingL ,7 ); Surface.SelectObject(LKBrush_White); Surface.Polygon(AircraftSide ,8 ); Surface.SelectObject(GreenBrush); Surface.Polygon(AircraftWingR ,7 ); Surface.SelectObject(oldBrush); } else { Surface.SelectObject(GreenBrush); Surface.Polygon(AircraftWingR ,7 ); Surface.SelectObject(LKBrush_White); Surface.Polygon(AircraftSide ,8 ); Surface.SelectObject(RedBrush); Surface.Polygon(AircraftWingL ,7 ); Surface.SelectObject(oldBrush); } if((brg < 90)|| (brg > 270)) { Surface.Polygon(AircraftTail ,5 ); } Surface.SelectObject(oldPen); Surface.SelectObject(oldBrush); } //else !asp_heading_task
int RenderFAISector (LKSurface& Surface, const RECT& rc , double lat1, double lon1, double lat2, double lon2, int iOpposite , const LKColor& fillcolor) { POINT Pt1; float fFAI_Percentage = FAI_NORMAL_PERCENTAGE; double fDist_a, fDist_b, fDist_c, fAngle; int i; int iPolyPtr=0; double lat_d,lon_d; double alpha, fDistTri, cos_alpha=0; POINT apSectorPolygon[MAX_FAI_SECTOR_PTS+1]; DistanceBearing(lat1, lon1, lat2, lon2, &fDist_c, &fAngle); if(fabs(fDist_c) < 1000.0) /* distance too short for a FAI sector */ return -1; double fDistMax = fDist_c/FAI_NORMAL_PERCENTAGE; double fDistMin = fDist_c/(1.0-2.0*FAI28_45Threshold); double fDelta_Dist = 2.0* fDist_c*fFAI_Percentage / (double)(FAI_SECTOR_STEPS-1); double fA, fB; double fMinLeg, fMaxLeg,fDiff=0; double dir = -1.0; BOOL bBigFAISector = false; if(fDistMax > FAI28_45Threshold) { bBigFAISector = true; fDistMax = fDist_c/FAI_BIG_PERCENTAGE; } if(fDistMin < FAI28_45Threshold) { fDistMin = fDist_c/(1.0-2.0*FAI_NORMAL_PERCENTAGE); } if (iOpposite >0) { dir = 1.0; } //#define HELP_LINES #ifdef HELP_LINES int x2,y2, style; FindLatitudeLongitude(lat1, lon1, AngleLimit360 (fAngle), fDist_c/2, &lat_d, &lon_d); x1 = (lon_d - lon_c)*fastcosine(lat_d); y1 = (lat_d - lat_c); FindLatitudeLongitude(lat_d, lon_d, AngleLimit360 (fAngle-90.0), fDist_c, &lat_d, &lon_d); x2 = (lon_d - lon_c)*fastcosine(lat_d); y2 = (lat_d - lat_c); Surface.DrawLine(rc, x1, y1, x2, y2, style); #endif /******************************************************************** * right below threshold 1 ********************************************************************/ fA = fDistMin; if(fDistMax > FAI28_45Threshold) fB = FAI28_45Threshold; else fB = fDistMax ; if(fA<fB) { fDelta_Dist =(fB-fA)/ (double)(FAI_SECTOR_STEPS-1); fDistTri = fA; for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fDist_a = FAI_NORMAL_PERCENTAGE * fDistTri; fDist_b = fDistTri - fDist_a - fDist_c; LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDistTri += fDelta_Dist; } } /******************************************************************** * right threshold extender 2 ********************************************************************/ if(fDistMin < FAI28_45Threshold) if(bBigFAISector && (fDistMin < FAI28_45Threshold)) { fMaxLeg = FAI28_45Threshold*FAI_BIG_MAX_PERCENTAGE; fMinLeg = FAI28_45Threshold*FAI_BIG_PERCENTAGE; fA = FAI28_45Threshold*FAI_NORMAL_PERCENTAGE; fB = FAI28_45Threshold-fMaxLeg-fDist_c; if(fB < fMinLeg) fB = fMinLeg; fDist_a = fA; fDelta_Dist = (fB-fA) / (double)(FAI_SECTOR_STEPS-1); for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fDist_b = FAI28_45Threshold - fDist_a - fDist_c; LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDist_a += fDelta_Dist; } } /******************************************************************** * right above threshold 3 ********************************************************************/ if(bBigFAISector) { fA = FAI28_45Threshold; if(fDistMin > fA) fA= fDistMin; fB =fDist_c/(1- FAI_BIG_PERCENTAGE-FAI_BIG_MAX_PERCENTAGE); if(fA < fB) { fDelta_Dist =(fB-fA)/ (double)(FAI_SECTOR_STEPS-1); fDistTri = fA; for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fMaxLeg = fDistTri*FAI_BIG_MAX_PERCENTAGE; fMinLeg = fDistTri*FAI_BIG_PERCENTAGE; fDist_a = fDistTri-fMinLeg-fDist_c;; fDist_b = fMinLeg; if(fDist_a > fMaxLeg) { fDiff = fDist_a - fMaxLeg; fDist_b+=fDiff; fDist_a-=fDiff; } LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_a*fDist_a + fDist_c*fDist_c - fDist_b*fDist_b )/(2.0*fDist_c*fDist_a); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_a, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDistTri += fDelta_Dist; } } } /******************************************************************** * TOP limited round 4 ********************************************************************/ if(fDistMax <= FAI28_45Threshold) fDist_b = fDistMax*(1.0-2*FAI_NORMAL_PERCENTAGE); else fDist_b = fDistMax*FAI_BIG_MAX_PERCENTAGE; fDist_a = fDistMax-fDist_b-fDist_c; fDelta_Dist = (fDist_a-fDist_b) / (double)(FAI_SECTOR_STEPS-1); for(i =0 ;i < FAI_SECTOR_STEPS; i++) { LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDist_a -= fDelta_Dist; fDist_b += fDelta_Dist; } /******************************************************************** * calc left leg ********************************************************************/ /******************************************************************** * LEFT above threshold 5 ********************************************************************/ if(bBigFAISector) { fB = FAI28_45Threshold; if( fB < fDistMin) fB = fDistMin; fA =fDist_c/(1- FAI_BIG_PERCENTAGE-FAI_BIG_MAX_PERCENTAGE); if(fA >= fB) { fDelta_Dist =(fA-fB)/ (double)(FAI_SECTOR_STEPS-1); fDistTri = fA; for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fMaxLeg = fDistTri*FAI_BIG_MAX_PERCENTAGE; fMinLeg = fDistTri*FAI_BIG_PERCENTAGE; fDist_a = fDistTri-fMinLeg-fDist_c; fDist_b = fMinLeg; if(fDist_a > fMaxLeg) { fDiff = fDist_a - fMaxLeg; fDist_b+=fDiff; fDist_a-=fDiff; } LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDistTri -= fDelta_Dist; } } } /******************************************************************** * LEFT threshold extender 6 ********************************************************************/ if(fDistMin < FAI28_45Threshold) if((fDistMin < FAI28_45Threshold) && (FAI28_45Threshold < fDistMax)) { fMaxLeg = FAI28_45Threshold*FAI_BIG_MAX_PERCENTAGE; fMinLeg = FAI28_45Threshold*FAI_BIG_PERCENTAGE; fA = FAI28_45Threshold*FAI_NORMAL_PERCENTAGE; fB = FAI28_45Threshold-fMaxLeg-fDist_c; if(fB < fMinLeg) fB = fMinLeg; fDist_b = fB; fDelta_Dist = (fA-fB) / (double)(FAI_SECTOR_STEPS-1); for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fDist_a = FAI28_45Threshold - fDist_b - fDist_c; LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDist_b += fDelta_Dist; } } /******************************************************************** * LEFT below threshold 7 ********************************************************************/ fA = fDistMin; if(fDistMax > FAI28_45Threshold) fB = FAI28_45Threshold; else fB = fDistMax ; if(fA<fB) { fDelta_Dist =(fB-fA)/ (double)(FAI_SECTOR_STEPS-1); fDistTri = fB; for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fDist_b = FAI_NORMAL_PERCENTAGE * fDistTri; fDist_a = fDistTri - fDist_b - fDist_c; LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDistTri -= fDelta_Dist; } } /******************************************************************** * low open PEAK round 8 ********************************************************************/ if(fDistMin >FAI28_45Threshold) { fDist_b = fDistMin*FAI_BIG_PERCENTAGE; fDist_a = fDistMin-fDist_b-fDist_c; fDelta_Dist = (fDist_b-fDist_a) / (double)(FAI_SECTOR_STEPS-1); for(i =0 ;i < FAI_SECTOR_STEPS; i++) { LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDist_a += fDelta_Dist; fDist_b -= fDelta_Dist; } } /******************************************************************** * draw polygon ********************************************************************/ LKPen hpSectorPen(PEN_SOLID, IBLSCALE(2), fillcolor ); LKPen hpOldPen = Surface.SelectObject(hpSectorPen); LKBrush hpOldBrush = Surface.SelectObject(LKBrush_Hollow); Surface.Polygon(apSectorPolygon,iPolyPtr,rc); Surface.SelectObject(hpOldPen); Surface.SelectObject(hpOldBrush); hpSectorPen.Release(); /******************************************************************** * calc round leg grid ********************************************************************/ hpSectorPen.Create(PEN_SOLID, (1), RGB_BLACK ); Surface.SelectObject(hpSectorPen); Surface.SetTextColor(RGB_BLACK); double fTic= 1/DISTANCEMODIFY; if(fDist_c > 5/DISTANCEMODIFY) fTic = 10/DISTANCEMODIFY; if(fDist_c > 50/DISTANCEMODIFY) fTic = 25/DISTANCEMODIFY; if(fDist_c > 100/DISTANCEMODIFY) fTic = 50/DISTANCEMODIFY; // if(fDist_c > 200/DISTANCEMODIFY) fTic = 100/DISTANCEMODIFY; if(fDist_c > 500/DISTANCEMODIFY) fTic = 250/DISTANCEMODIFY; POINT line[2]; BOOL bFirstUnit = true; LKASSERT(fTic!=0); fDistTri = ((int)(fDistMin/fTic)+1) * fTic ; LKFont hfOld = Surface.SelectObject(LK8PanelUnitFont); int iCnt = 0; while(fDistTri <= fDistMax) { TCHAR text[180]; SIZE tsize; if(bFirstUnit) _stprintf(text, TEXT("%i%s"), (int)(fDistTri*DISTANCEMODIFY), Units::GetUnitName(Units::GetUserDistanceUnit())); else _stprintf(text, TEXT("%i"), (int)(fDistTri*DISTANCEMODIFY)); bFirstUnit = false; Surface.GetTextSize(text, _tcslen(text), &tsize); int j=0; if(fDistTri < FAI28_45Threshold) { fDist_b = fDistTri*FAI_NORMAL_PERCENTAGE; fDist_a = fDistTri-fDist_b-fDist_c; fDelta_Dist = (fDist_a-fDist_b) / (double)(FAI_SECTOR_STEPS-1); } else { fMaxLeg = fDistTri*FAI_BIG_MAX_PERCENTAGE; fMinLeg = fDistTri*FAI_BIG_PERCENTAGE; fA = fMaxLeg; fB = fDistTri-fA-fDist_c; fDist_a = fA; fDist_b = fB; if(fB < fMinLeg) { fDiff = fMinLeg-fB; fB+=2*fDiff; fDist_b += fDiff; fDist_a -= fDiff; } if(fB > fMaxLeg) { fDiff = fB - fMaxLeg; fB+=2*fDiff; fDist_b-=fDiff; fDist_a+=fDiff; } fFAI_Percentage = FAI_BIG_PERCENTAGE; fDelta_Dist = (fA-fB) / (double)(FAI_SECTOR_STEPS-1); } for(i =0 ;i < FAI_SECTOR_STEPS; i++) { LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, line[0]); if(j> 0) { ForcedClipping=true; Surface.DrawLine(PEN_DASH, NIBLSCALE(1), line[0] , line[1] , RGB_BLACK, rc); ForcedClipping=false; } if(j==0) { Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text)); j=1; } // TCHAR text[180]; SIZE tsize; if(iCnt==0) _stprintf(text, TEXT("%i%s"), (int)(fDistTri*DISTANCEMODIFY), Units::GetUnitName(Units::GetUserDistanceUnit())); else _stprintf(text, TEXT("%i"), (int)(fDistTri*DISTANCEMODIFY)); Surface.GetTextSize(text, _tcslen(text), &tsize); if(i == 0) Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text)); if(iCnt > 1) if(i == FAI_SECTOR_STEPS-1) Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text)); if(iCnt > 2) if((i== (FAI_SECTOR_STEPS/2))) Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text)); line[1] = line[0]; fDist_a -= fDelta_Dist; fDist_b += fDelta_Dist; } fDistTri+=fTic;iCnt++; // if((iCnt %2) ==0) // DrawText(hdc, line[0].x, line[0].y, ETO_OPAQUE, NULL, text, _tcslen(text), NULL); } Surface.SelectObject(hfOld); Surface.SelectObject(hpOldPen); return 0; }
void MapWindow::DrawWindAtAircraft2(LKSurface& Surface, const POINT& Orig, const RECT& rc) { int i; POINT Start; TCHAR sTmp[12]; static SIZE tsize = {0,0}; if (DerivedDrawInfo.WindSpeed<1) { return; // JMW don't bother drawing it if not significant } if (tsize.cx == 0){ const auto oldFont = Surface.SelectObject(MapWindowBoldFont); Surface.GetTextSize(TEXT("99"), 2, &tsize); Surface.SelectObject(oldFont); tsize.cx = tsize.cx/2; } int wmag = iround(4.0*DerivedDrawInfo.WindSpeed); Start.y = Orig.y; Start.x = Orig.x; int kx = tsize.cx/ScreenScale/2; POINT Arrow[7] = { {0,-20}, {-6,-26}, {0,-20}, {6,-26}, {0,-20}, {8+kx, -24}, {-8-kx, -24}}; for (i=1;i<4;i++) Arrow[i].y -= wmag; PolygonRotateShift(Arrow, 7, Start.x, Start.y, DerivedDrawInfo.WindBearing-DisplayAngle); // // Draw Wind Arrow // POINT Tail[2] = {{0,-20}, {0,-26-min(20,wmag)*3}}; double angle = AngleLimit360(DerivedDrawInfo.WindBearing-DisplayAngle); for(i=0; i<2; i++) { if (ScreenScale>1) { Tail[i].x *= ScreenScale; Tail[i].y *= ScreenScale; } protateshift(Tail[i], angle, Start.x, Start.y); } // optionally draw dashed line for wind arrow Surface.DrawLine(PEN_DASH, 1, Tail[0], Tail[1], LKColor(0,0,0), rc); // Paint wind value only while circling if ( (mode.Is(Mode::MODE_CIRCLING)) ) { _stprintf(sTmp, _T("%d"), iround(DerivedDrawInfo.WindSpeed * SPEEDMODIFY)); TextInBoxMode_t TextInBoxMode = {0}; TextInBoxMode.AlligneCenter = true; // { 16 | 32 }; // JMW test {2 | 16}; TextInBoxMode.WhiteBorder = true; if (Arrow[5].y>=Arrow[6].y) { TextInBox(Surface, &rc, sTmp, Arrow[5].x-kx, Arrow[5].y, 0, &TextInBoxMode); } else { TextInBox(Surface, &rc, sTmp, Arrow[6].x-kx, Arrow[6].y, 0, &TextInBoxMode); } } const auto hpOld = Surface.SelectObject(LKPen_Black_N2); const auto hbOld = Surface.SelectObject(LKBrush_Grey); Surface.Polygon(Arrow,5); Surface.SelectObject(hbOld); Surface.SelectObject(hpOld); }
void RenderAirspaceTerrain(LKSurface& Surface, double PosLat, double PosLon, double brg, DiagrammStruct* psDiag) { RECT rc = psDiag->rc; //rc.bottom +=BORDER_Y; double range = psDiag->fXMax - psDiag->fXMin; // km double hmax = psDiag->fYMax; double lat, lon; int i, j; if (!IsDithered() && IsMultimapTerrain()) { RenderSky(Surface, rc, SKY_HORIZON_COL, SKY_SPACE_COL, GC_NO_COLOR_STEPS); } else { Surface.FillRect(&rc, MapWindow::hInvBackgroundBrush[BgMapColor]); } FindLatitudeLongitude(PosLat, PosLon, brg, psDiag->fXMin, &lat, &lon); POINT apTerrainPolygon[AIRSPACE_SCANSIZE_X + 4] = {}; double d_lat[AIRSPACE_SCANSIZE_X] = {}; double d_lon[AIRSPACE_SCANSIZE_X] = {}; double d_h[AIRSPACE_SCANSIZE_X] = {}; #define FRAMEWIDTH 2 RasterTerrain::Lock(); // want most accurate rounding here RasterTerrain::SetTerrainRounding(0, 0); double fj; for (j = 0; j < AIRSPACE_SCANSIZE_X; j++) { // scan range fj = (double) j * 1.0 / (double) (AIRSPACE_SCANSIZE_X - 1); FindLatitudeLongitude(lat, lon, brg, range*fj, &d_lat[j], &d_lon[j]); d_h[j] = RasterTerrain::GetTerrainHeight(d_lat[j], d_lon[j]); if (d_h[j] == TERRAIN_INVALID) d_h[j] = 0; //@ 101027 BUGFIX hmax = max(hmax, d_h[j]); } RasterTerrain::Unlock(); /******************************************************************************** * scan line ********************************************************************************/ if (IsMultimapAirspace()) Sideview_iNoHandeldSpaces = CAirspaceManager::Instance().ScanAirspaceLineList(d_lat, d_lon, d_h, Sideview_pHandeled, MAX_NO_SIDE_AS); // Sideview_pHandeled[GC_MAX_NO]; else Sideview_iNoHandeldSpaces = 0; #if BUGSTOP LKASSERT(Sideview_iNoHandeldSpaces < MAX_NO_SIDE_AS); #endif if (Sideview_iNoHandeldSpaces >= MAX_NO_SIDE_AS) Sideview_iNoHandeldSpaces = MAX_NO_SIDE_AS - 1; /******************************************************************************** * bubble sort to start with biggest airspaces ********************************************************************************/ int iSizeLookupTable[MAX_NO_SIDE_AS]; for (i = 0; i < Sideview_iNoHandeldSpaces; i++) iSizeLookupTable[i] = i; for (i = 0; i < Sideview_iNoHandeldSpaces; i++) { #if BUGSTOP LKASSERT(iSizeLookupTable[i] < MAX_NO_SIDE_AS); #endif for (j = i; j < Sideview_iNoHandeldSpaces; j++) { #if BUGSTOP LKASSERT(iSizeLookupTable[j] < MAX_NO_SIDE_AS); #endif if (iSizeLookupTable[i] >= MAX_NO_SIDE_AS) continue; if (iSizeLookupTable[j] >= MAX_NO_SIDE_AS) continue; if (Sideview_pHandeled[iSizeLookupTable[i]].iAreaSize < Sideview_pHandeled[iSizeLookupTable[j]].iAreaSize) { int iTmp = iSizeLookupTable[i]; iSizeLookupTable[i] = iSizeLookupTable[j]; iSizeLookupTable[j] = iTmp; } } } /********************************************************************************** * transform into diagram coordinates **********************************************************************************/ double dx1 = (double) (rc.right) / (double) (AIRSPACE_SCANSIZE_X - 1); int x0 = rc.left; LKASSERT(Sideview_iNoHandeldSpaces < MAX_NO_SIDE_AS); for (i = 0; i < Sideview_iNoHandeldSpaces; i++) { Sideview_pHandeled[i].rc.left = (long) ((Sideview_pHandeled[i].rc.left) * dx1) + x0 - FRAMEWIDTH / 2; Sideview_pHandeled[i].rc.right = (long) ((Sideview_pHandeled[i].rc.right) * dx1) + x0 + FRAMEWIDTH / 2; Sideview_pHandeled[i].rc.bottom = CalcHeightCoordinat((double) Sideview_pHandeled[i].rc.bottom, psDiag) + FRAMEWIDTH / 2; Sideview_pHandeled[i].rc.top = CalcHeightCoordinat((double) Sideview_pHandeled[i].rc.top, psDiag) - FRAMEWIDTH / 2; Sideview_pHandeled[i].iMaxBase = Sideview_pHandeled[i].rc.bottom; Sideview_pHandeled[i].iMinTop = Sideview_pHandeled[i].rc.top; int iN = Sideview_pHandeled[i].iNoPolyPts; #if BUGSTOP LKASSERT(iN < GC_MAX_POLYGON_PTS); #endif if (iN >= GC_MAX_POLYGON_PTS) iN = GC_MAX_POLYGON_PTS - 1; if (Sideview_pHandeled[i].bRectAllowed == false) { for (j = 0; j < iN; j++) { Sideview_pHandeled[i].apPolygon[j].x = (long) (((Sideview_pHandeled[i].apPolygon[j].x) * dx1) + x0); Sideview_pHandeled[i].apPolygon[j].y = CalcHeightCoordinat((double) Sideview_pHandeled[i].apPolygon[j].y, psDiag); if (j != iN - 1) { if ((j < iN / 2)) { Sideview_pHandeled[i].iMaxBase = min((long) Sideview_pHandeled[i].iMaxBase, (long) Sideview_pHandeled[i].apPolygon[j].y); } else { Sideview_pHandeled[i].iMinTop = max((long) Sideview_pHandeled[i].iMinTop, (long) Sideview_pHandeled[i].apPolygon[j].y); } } } } } /********************************************************************************** * draw airspaces **********************************************************************************/ const auto oldpen = Surface.SelectObject(LK_NULL_PEN); _TCHAR text [80]; LKASSERT(Sideview_iNoHandeldSpaces < MAX_NO_SIDE_AS); for (int m = 0; m < Sideview_iNoHandeldSpaces; m++) { int iSizeIdx = iSizeLookupTable[m]; #if BUGSTOP LKASSERT(iSizeIdx < MAX_NO_SIDE_AS && iSizeIdx >= 0); #endif if (iSizeIdx >= MAX_NO_SIDE_AS) iSizeIdx = MAX_NO_SIDE_AS - 1; int type = Sideview_pHandeled[iSizeIdx].iType; RECT rcd = Sideview_pHandeled[iSizeIdx].rc; LKColor FrameColor; double fFrameColFact; if (Sideview_pHandeled[iSizeIdx].bEnabled) { Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(type)); Surface.SetTextColor(MapWindow::GetAirspaceColourByClass(type)); fFrameColFact = 0.8; FrameColor = MapWindow::GetAirspaceColourByClass(type); } else { Surface.SelectObject(LKBrush_Hollow); Surface.SetTextColor(RGB_GGREY); FrameColor = RGB_GGREY; fFrameColFact = 1.2; } if (INVERTCOLORS) fFrameColFact *= 0.8; else fFrameColFact *= 1.2; LKColor Color = FrameColor.ChangeBrightness(fFrameColFact); LKPen mpen2(PEN_SOLID, FRAMEWIDTH, Color); const auto oldpen2 = Surface.SelectObject(mpen2); if (Sideview_pHandeled[iSizeIdx].bRectAllowed == true) Surface.Rectangle(rcd.left + 1, rcd.top, rcd.right, rcd.bottom); else Surface.Polygon(Sideview_pHandeled[iSizeIdx].apPolygon, Sideview_pHandeled[iSizeIdx].iNoPolyPts); Surface.SelectObject(oldpen2); if (Sideview_pHandeled[iSizeIdx].bEnabled) Surface.SetTextColor(Sideview_TextColor); // RGB_MENUTITLEFG else Surface.SetTextColor(RGB_GGREY); /*********************************************** * build view overlap for centering text ***********************************************/ rcd.bottom = min(rcd.bottom, Sideview_pHandeled[iSizeIdx].iMaxBase); rcd.top = max(rcd.top, Sideview_pHandeled[iSizeIdx].iMinTop); rcd.left = max(rcd.left, rc.left); rcd.right = min(rcd.right, rc.right); rcd.bottom = min(rcd.bottom, rc.bottom); rcd.top = max(rcd.top, rc.top); SIZE textsize; SIZE aispacesize = {rcd.right - rcd.left, rcd.bottom - rcd.top}; LK_tcsncpy(text, Sideview_pHandeled[iSizeIdx].szAS_Name, NAME_SIZE - 1/* sizeof(text)/sizeof(text[0])*/); Surface.GetTextSize(text, &textsize); int x = rcd.left + aispacesize.cx / 2; ; int y = rcd.top + aispacesize.cy / 2; // int iTextheight = tsize.cy; int iOffset = 0; BOOL blongtext = false; if (aispacesize.cy > (2 * textsize.cy) && (textsize.cx < aispacesize.cx)) { iOffset = textsize.cy / 2; } if ((textsize.cx < aispacesize.cx) && (textsize.cy < aispacesize.cy)) { Surface.DrawText(x - textsize.cx / 2, y - iOffset - textsize.cy / 2, text); blongtext = true; } LK_tcsncpy(text, CAirspaceManager::Instance().GetAirspaceTypeShortText(Sideview_pHandeled[iSizeIdx].iType), NAME_SIZE); Surface.GetTextSize(text, &textsize); if (textsize.cx < aispacesize.cx) { if (2 * textsize.cy < aispacesize.cy) { Surface.DrawText(x - textsize.cx / 2, y + iOffset - textsize.cy / 2, text); } else { if ((textsize.cy < aispacesize.cy) && (!blongtext)) Surface.DrawText(x - textsize.cx / 2, y - iOffset - textsize.cy / 2, text); } } } Surface.SelectObject(oldpen); /********************************************************************************** * draw airspace frames in reversed order **********************************************************************************/ #ifdef OUTLINE_2ND for (int m = 0; m < Sideview_iNoHandeldSpaces; m++) { int iSizeIdx = iSizeLookupTable[Sideview_iNoHandeldSpaces - m - 1]; if (Sideview_pHandeled[iSizeIdx].bEnabled) { #if BUGSTOP LKASSERT(iSizeIdx < MAX_NO_SIDE_AS); #endif if (iSizeIdx >= MAX_NO_SIDE_AS) iSizeIdx = MAX_NO_SIDE_AS - 1; int type = Sideview_pHandeled[iSizeIdx].iType; RECT rcd = Sideview_pHandeled[iSizeIdx].rc; LKColor FrameColor = MapWindow::GetAirspaceColourByClass(type); double fFrameColFact; Surface.SelectObject(LKBrush_Hollow); if (Sideview_pHandeled[iSizeIdx].bEnabled) { // Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(type)); Surface.SetTextColor(MapWindow::GetAirspaceColourByClass(type)); fFrameColFact = 0.8; } else { Surface.SetTextColor(RGB_GGREY); FrameColor = RGB_GGREY; fFrameColFact = 1.2; } if (INVERTCOLORS) fFrameColFact *= 0.8; else fFrameColFact *= 1.2; LKColor lColor = FrameColor.ChangeBrightness(fFrameColFact); LKPen mpen2(PEN_SOLID, FRAMEWIDTH, lColor); const auto oldpen2 = Surface.SelectObject(mpen2); if (Sideview_pHandeled[iSizeIdx].bRectAllowed == true) Surface.Rectangle(rcd.left + 1, rcd.top, rcd.right, rcd.bottom); else Surface.Polygon(Sideview_pHandeled[iSizeIdx].apPolygon, Sideview_pHandeled[iSizeIdx].iNoPolyPts); Surface.SelectObject(oldpen2); } } #endif /************************************************************* * draw ground *************************************************************/ // draw ground /********************************************************************* * draw terrain *********************************************************************/ LKPen hpHorizonGround(PEN_SOLID, IBLSCALE(1) + 1, LKColor(126, 62, 50)); LKBrush hbHorizonGround(GROUND_COLOUR); const auto oldPen = Surface.SelectObject(hpHorizonGround); const auto oldBrush = Surface.SelectObject(hbHorizonGround); for (j = 0; j < AIRSPACE_SCANSIZE_X; j++) { // scan range apTerrainPolygon[j].x = iround(j * dx1) + x0; apTerrainPolygon[j].y = CalcHeightCoordinat(d_h[j], psDiag); } apTerrainPolygon[AIRSPACE_SCANSIZE_X].x = iround(AIRSPACE_SCANSIZE_X * dx1) + x0; ; // x0; apTerrainPolygon[AIRSPACE_SCANSIZE_X].y = CalcHeightCoordinat(0, psDiag); //iBottom; apTerrainPolygon[AIRSPACE_SCANSIZE_X + 1].x = iround(0 * dx1) + x0; //iround(j*dx1)+x0; apTerrainPolygon[AIRSPACE_SCANSIZE_X + 1].y = CalcHeightCoordinat(0, psDiag); //iBottom; apTerrainPolygon[AIRSPACE_SCANSIZE_X + 2] = apTerrainPolygon[0]; static_assert(array_size(apTerrainPolygon) >= AIRSPACE_SCANSIZE_X + 3, "wrong array size"); Surface.Polygon(apTerrainPolygon, AIRSPACE_SCANSIZE_X + 3); Surface.SelectObject(oldPen); Surface.SelectObject(oldBrush); /********************************************************************* * draw sea *********************************************************************/ #ifdef MSL_SEA_DRAW // draw sea if (psDiag->fYMin < GC_SEA_LEVEL_TOLERANCE) { RECT sea = {rc.left, rc.bottom, rc.right, rc.bottom + SV_BORDER_Y}; #ifndef UNDITHER RenderSky(Surface, sea, RGB_STEEL_BLUE, RGB_ROYAL_BLUE, 7); #else RenderSky(Surface, sea, RGB_BLACK, RGB_BLACK, 2); #endif } #else if (psDiag->fYMin < GC_SEA_LEVEL_TOLERANCE) Rectangle(hdc, rc.left, rc.bottom, rc.right, rc.bottom + BORDER_Y); #endif Surface.SetTextColor(Sideview_TextColor); // RGB_MENUTITLEFG }