void MapWindow::LKCalculateWaypointReachable(const bool forced) { #if USEONEHZLIMITER if (!forced) ONEHZLIMITER; #endif static short multicalc_slot=0; // -1 (which becomes immediately 0) will force full loading on startup, but this is not good // because currently we are not waiting for ProgramStarted=3 // and the first scan is made while still initializing other things short numslots=1; // TODO assign numslots with a function, based also on available CPU time if (NumberOfWayPoints>200) { numslots=NumberOfWayPoints/400; // keep numslots optimal if (numslots<MULTICALC_MINROBIN) numslots=MULTICALC_MINROBIN; // seconds for full scan, as this is executed at 1Hz if (numslots>MULTICALC_MAXROBIN) numslots=MULTICALC_MAXROBIN; // When waypointnumber has changed, we wont be using an exceeded multicalc_slot, which would crash the sw // In this case, we shall probably continue for the first round to calculate without going from the beginning // but this is not a problem, we are round-robin all the time here. if (++multicalc_slot>numslots) multicalc_slot=1; } else { multicalc_slot=0; // forcing full scan } unsigned int i; double waypointDistance, waypointBearing,altitudeRequired,altitudeDifference; // LandableReachable is used only by the thermal bar indicator in MapWindow2, after here // apparently, is used to tell you if you are below final glide but in range for a landable wp // Since nov 2011 we dont user LandableReachable in FinalGlide anymore. // However it is still to be understood what drawbacks we might have by changing calculations here. LandableReachable = false; if (!WayPointList) return; unsigned int scanstart; unsigned int scanend; #if DEBUGCW unsigned int numwpscanned=0; #endif LockTaskData(); if (multicalc_slot==0) { scanstart=0; // including this scanend=NumberOfWayPoints; // will be used -1, so up to this excluded value #if DEBUGCW StartupStore(_T("... wps=%d multicalc_slot=0 ignored numslot=%d, full scan %d < %d%s"),NumberOfWayPoints, numslots,scanstart,scanend,NEWLINE); #endif } else { scanstart=(NumberOfWayPoints/numslots)*(multicalc_slot-1); if (multicalc_slot==numslots) scanend=NumberOfWayPoints; else scanend=scanstart+(NumberOfWayPoints/numslots); #if DEBUGCW StartupStore(_T("... wps=%d multicalc_slot=%d of %d, scan %d < %d%s"),NumberOfWayPoints, multicalc_slot, numslots,scanstart,scanend,NEWLINE); #endif } int overtarg=GetOvertargetIndex(); if (overtarg<0) overtarg=999999; for(i=scanstart;i<scanend;i++) { // signed Overtgarget -1 becomes a very high number, casted unsigned if ( ( ((WayPointCalc[i].AltArriv[AltArrivMode] >=0)||(WayPointList[i].Visible)) && (WayPointCalc[i].IsLandable || (WayPointList[i].Style==STYLE_THERMAL))) || WaypointInTask(i) || (i==(unsigned int)overtarg) ) { DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, WayPointList[i].Latitude, WayPointList[i].Longitude, &waypointDistance, &waypointBearing); WayPointCalc[i].Distance=waypointDistance; WayPointCalc[i].Bearing=waypointBearing; CalculateGlideRatio(waypointDistance, DerivedDrawInfo.NavAltitude - WayPointList[i].Altitude - GetSafetyAltitude(i)); altitudeRequired = GlidePolar::MacCreadyAltitude (GetMacCready(i,0), waypointDistance, waypointBearing, DerivedDrawInfo.WindSpeed, DerivedDrawInfo.WindBearing, 0,0,true,0) + WayPointList[i].Altitude + GetSafetyAltitude(i) - DerivedDrawInfo.EnergyHeight; WayPointCalc[i].AltReqd[AltArrivMode] = altitudeRequired; WayPointList[i].AltArivalAGL = DerivedDrawInfo.NavAltitude - altitudeRequired; if(WayPointList[i].AltArivalAGL >=0){ WayPointList[i].Reachable = TRUE; if (CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, waypointDistance, waypointBearing)) { if ((signed)i!=TASKINDEX) { LandableReachable = true; } } else { WayPointList[i].Reachable = FALSE; } } else { WayPointList[i].Reachable = FALSE; } #if DEBUGCW numwpscanned++; #endif } // if landable or in task } // for all waypoints // This is wrong, because multicalc will not necessarily find the LandableReachable at each pass // As of nov 2011 it is better not to change it, and let further investigation after 3.0 if (!LandableReachable) // indentation wrong here for(i=scanstart;i<scanend;i++) { if(!WayPointList[i].Visible && WayPointList[i].FarVisible) { // visible but only at a distance (limit this to 100km radius) if( WayPointCalc[i].IsLandable ) { #if DEBUGCW numwpscanned++; #endif DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, WayPointList[i].Latitude, WayPointList[i].Longitude, &waypointDistance, &waypointBearing); WayPointCalc[i].Distance=waypointDistance; // VENTA6 WayPointCalc[i].Bearing=waypointBearing; if (waypointDistance<100000.0) { altitudeRequired = GlidePolar::MacCreadyAltitude (GetMacCready(i,0), waypointDistance, waypointBearing, // 091221 DerivedDrawInfo.WindSpeed, DerivedDrawInfo.WindBearing, 0,0,true,0) + WayPointList[i].Altitude + GetSafetyAltitude(i); altitudeDifference = DerivedDrawInfo.NavAltitude + DerivedDrawInfo.EnergyHeight - altitudeRequired; WayPointList[i].AltArivalAGL = altitudeDifference; WayPointCalc[i].AltReqd[AltArrivMode] = altitudeRequired; if(altitudeDifference >=0){ WayPointList[i].Reachable = TRUE; if (CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, waypointDistance, waypointBearing)) { LandableReachable = true; } else WayPointList[i].Reachable = FALSE; } else { WayPointList[i].Reachable = FALSE; } } else { WayPointList[i].Reachable = FALSE; } // <100000 } // landable wp } // visible or far visible } // for all waypoint UnlockTaskData(); #if DEBUGCW StartupStore(_T("...... processed wps: %d\n"),numwpscanned); #endif }
void MapWindow::DrawWaypointsNew(HDC hdc, const RECT rc) { unsigned int i; int bestwp=-1; TCHAR Buffer[LKSIZEBUFFER]; TCHAR Buffer2[LKSIZEBUFFER]; TCHAR sAltUnit[LKSIZEBUFFERUNIT]; TextInBoxMode_t TextDisplayMode = {0}; static int resizer[10]={ 20,20,20,3,5,8,10,12,0 }; // if pan mode, show full names int pDisplayTextType = DisplayTextType; if (!WayPointList) return; _tcscpy(sAltUnit, Units::GetAltitudeName()); MapWaypointLabelListCount = 0; int arrivalcutoff=0, foundairport=0; bool isairport; bool islandpoint; // setting decluttericons will not paint outlanding, and use minrunway to declutter even more bool decluttericons=false; // inrange : max scale allowed to print non-landable waypoints bool inrange=true; // minimal size of a runway to paint it while decluttering int minrunway=0; // // RealScale // // 2km 1.42 // 3.5km 2.5 // 5km 3.57 // 7.5km 5.35 // 10km 7.14 // 15km 10.71 // 20km 14.28 // 25km 17.85 // 40km 28.57 // 50km 35.71 // 75km 53.57 switch(DeclutterMode) { case dmDisabled: //inrange=(MapWindow::zoom.RealScale() <=18 ? true:false); // 17.85, 25km scale inrange=(MapWindow::zoom.RealScale() <=15 ? true:false); // 14.28, 20km scale decluttericons=false; break; case dmLow: inrange=(MapWindow::zoom.RealScale() <=11 ? true:false); // 10.71, 15km scale decluttericons=(MapWindow::zoom.RealScale() >=14 ? true : false); minrunway=200; break; case dmMedium: inrange=(MapWindow::zoom.RealScale() <=10 ? true:false); decluttericons=(MapWindow::zoom.RealScale() >=10 ? true : false); minrunway=400; break; case dmHigh: inrange=(MapWindow::zoom.RealScale() <=10 ? true:false); decluttericons=(MapWindow::zoom.RealScale() >=10 ? true : false); minrunway=800; break; case dmVeryHigh: inrange=(MapWindow::zoom.RealScale() <=10 ? true:false); decluttericons=(MapWindow::zoom.RealScale() >=10 ? true : false); minrunway=1600; break; default: LKASSERT(0); break; } if (MapWindow::zoom.RealScale() <=20) for(i=0;i<NumberOfWayPoints;i++) { if (WayPointList[i].Visible != TRUE ) continue; // false may not be FALSE? if (WayPointCalc[i].IsAirport) { if (WayPointList[i].Reachable == FALSE) { SelectObject(hDCTemp,hBmpAirportUnReachable); } else { SelectObject(hDCTemp,hBmpAirportReachable); if ( arrivalcutoff < (int)(WayPointList[i].AltArivalAGL)) { arrivalcutoff = (int)(WayPointList[i].AltArivalAGL); bestwp=i; foundairport++; } } } else { if ( WayPointCalc[i].IsOutlanding ) { // outlanding if (WayPointList[i].Reachable == FALSE) SelectObject(hDCTemp,hBmpFieldUnReachable); else { SelectObject(hDCTemp,hBmpFieldReachable); // get the outlanding as bestwp only if no other choice if (foundairport == 0) { // do not set arrivalcutoff: any next reachable airport is better than an outlanding if ( arrivalcutoff < (int)(WayPointList[i].AltArivalAGL)) bestwp=i; } } } else continue; // do not draw icons for normal turnpoints here } if(Appearance.IndLandable == wpLandableDefault) { double fScaleFact =MapWindow::zoom.RealScale(); if(fScaleFact < 0.1) fScaleFact = 0.1; // prevent division by zero fScaleFact = zoom.DrawScale(); if(fScaleFact > 20000.0) fScaleFact = 20000.0; // limit to prevent huge airfiel symbols if(fScaleFact < 1600) fScaleFact = 1600; // limit to prevent tiny airfiel symbols if (decluttericons) { if (WayPointCalc[i].IsAirport && (WayPointList[i].RunwayLen>minrunway || WayPointList[i].RunwayLen==0)) { DrawRunway(hdc,&WayPointList[i],rc, fScaleFact); } } else DrawRunway(hdc,&WayPointList[i],rc, fScaleFact); } else { DrawBitmapX(hdc, WayPointList[i].Screen.x-10, WayPointList[i].Screen.y-10, 20,20, hDCTemp,0,0,SRCPAINT,false); DrawBitmapX(hdc, WayPointList[i].Screen.x-10, WayPointList[i].Screen.y-10, 20,20, hDCTemp,20,0,SRCAND,false); } } // for all waypoints if (foundairport==0 && bestwp>=0) arrivalcutoff = (int)WayPointList[bestwp].AltArivalAGL; for(i=0;i<NumberOfWayPoints;i++) { if(WayPointList[i].Visible ) { bool irange = false; bool intask = false; bool islandable; // isairport+islandpoint bool excluded=false; bool dowrite; intask = WaypointInTask(i); dowrite = intask; // initially set only for intask memset((void*)&TextDisplayMode, 0, sizeof(TextDisplayMode)); // airports are also landpoints. should be better handled isairport=((WayPointList[i].Flags & AIRPORT) == AIRPORT); islandpoint=((WayPointList[i].Flags & LANDPOINT) == LANDPOINT); islandable=WayPointCalc[i].IsLandable; // always in range if MapScale <=10 irange = inrange; if(MapWindow::zoom.RealScale() > 20) { SelectObject(hDCTemp,hInvSmall); irange=false; goto NiklausWirth; // with compliments } if (decluttericons) { if (! (WayPointCalc[i].IsAirport && (WayPointList[i].RunwayLen>minrunway || WayPointList[i].RunwayLen==0))) { SelectObject(hDCTemp,hInvSmall); irange=false; goto NiklausWirth; } } if( islandable ) { if(WayPointList[i].Reachable){ TextDisplayMode.Reachable = 1; if ( isairport ) SelectObject(hDCTemp,hBmpAirportReachable); else SelectObject(hDCTemp,hBmpFieldReachable); if ((GetMultimap_Labels()<MAPLABELS_ALLOFF)||intask) { dowrite = true; // exclude outlandings worst than visible airports, only when there are visible reachable airports! if ( isairport==false && islandpoint==true ) { if ( (int)WayPointList[i].AltArivalAGL >=2000 ) { // more filter excluded=true; } else { if ( (bestwp>=0) && (i==(unsigned)bestwp) && (foundairport==0) ) { // this outlanding is the best option isairport=true; islandpoint=false; // make it an airport TODO paint it as best } else { if ( foundairport >0 ) { if ( (int)WayPointList[i].AltArivalAGL <= arrivalcutoff ) { excluded=true; } } } } } else // do not display airport arrival if close to the best so far. // ex: best arrival is 1200m, include onlye below 1200/4 (prevent division by zero) // This way we only display far points, and skip closer points // WE NEED MORE INFO ABOUT LANDING POINTS: THE .CUP FORMAT WILL LET US KNOW WHAT IS // BEST TO SHOW AND WHAT IS NOT. Winpilot format is useless here. { dowrite=true;// TEST FIX not necessary probably // it's an airport if ( (bestwp>=0) && (i != (unsigned)bestwp) && (arrivalcutoff>600) ) { if ( (arrivalcutoff / ((int)WayPointList[i].AltArivalAGL+1))<4 ) { excluded=true; } } } } } else // landable waypoint is unreachable { dowrite=true; if ( isairport ) { SelectObject(hDCTemp,hBmpAirportUnReachable); } else { SelectObject(hDCTemp,hBmpFieldUnReachable); } } } else { // waypoint is an ordinary turnpoint if(MapWindow::zoom.RealScale() > 4) { if (BlackScreen) SelectObject(hDCTemp,hInvSmall); else SelectObject(hDCTemp,hSmall); } else { if (BlackScreen) SelectObject(hDCTemp,hInvTurnPoint); else SelectObject(hDCTemp,hTurnPoint); } } // end landable-not landable NiklausWirth: if (intask || (OutlinedTp==(OutlinedTp_t)otAll) ) { TextDisplayMode.WhiteBold = 1; TextDisplayMode.Color=RGB_WHITE; } // No matter of how we thought to draw it, let it up to the user.. switch(NewMapDeclutter) { case 0: excluded=false; // no decluttering: show all airports and outlandings break; case 1: if ( isairport ) excluded=false; // show all airports, declutter outlandings break; default: break; // else work normally } // here come both turnpoints and landables.. if( intask || irange || dowrite) { // irange always set when MapScale <=10 bool draw_alt = TextDisplayMode.Reachable && ((GetMultimap_Labels()<MAPLABELS_ONLYTOPO) || intask); // 100711 reachable landing point! if (excluded==true) draw_alt=false; // exclude close outlandings switch(pDisplayTextType) { case DISPLAYNAME: case DISPLAYFIRSTTHREE: case DISPLAYFIRSTFIVE: case DISPLAYFIRST8: case DISPLAYFIRST10: case DISPLAYFIRST12: dowrite = (GetMultimap_Labels()<MAPLABELS_ONLYTOPO) || intask || islandable; // 100711 if ( (islandable && !isairport) && MapWindow::zoom.RealScale() >=10 ) dowrite=0; // FIX then no need to go further // 101215 if (DisplayTextType == DISPLAYNAME) { _tcscpy(Buffer2,WayPointList[i].Name); } else { LK_tcsncpy(Buffer2, WayPointList[i].Name, resizer[DisplayTextType]); } // ConvToUpper(Buffer2); if (draw_alt) { if ( ArrivalValue == (ArrivalValue_t) avAltitude ) { if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) ) wsprintf(Buffer, TEXT("%s:%d"), Buffer2, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY)); else wsprintf(Buffer, TEXT("%s:%d%s"), Buffer2, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit); } else wsprintf(Buffer, TEXT("%s:%d"), Buffer2, (int)WayPointCalc[i].GR); if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.Border = 1; TextDisplayMode.WhiteBold = 0; } else TextDisplayMode.WhiteBold = 1; // outlined TextDisplayMode.Color=RGB_WHITE; } else { //wsprintf(Buffer, TEXT("%s"),Buffer2); _tcscpy(Buffer,Buffer2); if (islandable && isairport) { TextDisplayMode.WhiteBold = 1; // outlined TextDisplayMode.Color=RGB_WHITE; } } break; case DISPLAYNUMBER: dowrite = (GetMultimap_Labels()<MAPLABELS_ONLYTOPO) || intask || islandable; if ( (islandable && !isairport) && MapWindow::zoom.RealScale() >=10 ) dowrite=0; // FIX then no need to go further if (draw_alt) { if ( ArrivalValue == (ArrivalValue_t) avAltitude ) { if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) ) wsprintf(Buffer, TEXT("%d:%d"), WayPointList[i].Number, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY)); else wsprintf(Buffer, TEXT("%d:%d%s"), WayPointList[i].Number, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit); } else wsprintf(Buffer, TEXT("%d:%d"), WayPointList[i].Number, (int)(WayPointCalc[i].GR)); if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.Border = 1; TextDisplayMode.WhiteBold = 0; } else TextDisplayMode.WhiteBold = 1; // outlined TextDisplayMode.Color=RGB_WHITE; } else { wsprintf(Buffer, TEXT("%d"),WayPointList[i].Number); if (islandable && isairport) { TextDisplayMode.WhiteBold = 1; // outlined TextDisplayMode.Color=RGB_WHITE; } } break; case DISPLAYNAMEIFINTASK: dowrite = intask; if (intask) { if (draw_alt) { if ( ArrivalValue == (ArrivalValue_t) avAltitude ) { if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) ) wsprintf(Buffer, TEXT("%s:%d"), WayPointList[i].Name, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY)); else wsprintf(Buffer, TEXT("%s:%d%s"), WayPointList[i].Name, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit); } else wsprintf(Buffer, TEXT("%s:%d"), WayPointList[i].Name, (int)(WayPointCalc[i].GR)); if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.Border = 1; TextDisplayMode.WhiteBold = 0; } else TextDisplayMode.WhiteBold = 1; // outlined TextDisplayMode.Color=RGB_WHITE; } else { wsprintf(Buffer, TEXT("%s"),WayPointList[i].Name); // TODO CHECK THIS, UNTESTED.. if (islandable && isairport) { TextDisplayMode.WhiteBold = 1; // outlined TextDisplayMode.Color=RGB_WHITE; } } } else { wsprintf(Buffer, TEXT(" ")); dowrite=true; } break; case DISPLAYNONE: dowrite = (GetMultimap_Labels()<MAPLABELS_ONLYTOPO) || intask || islandable; if (draw_alt) { if ( ArrivalValue == (ArrivalValue_t) avAltitude ) { if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) ) wsprintf(Buffer, TEXT("%d"), (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY)); else wsprintf(Buffer, TEXT("%d%s"), (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit); } else wsprintf(Buffer, TEXT("%d"), (int)(WayPointCalc[i].GR) ); if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.Border = 1; TextDisplayMode.WhiteBold = 0; } else TextDisplayMode.WhiteBold = 1; // outlined TextDisplayMode.Color=RGB_WHITE; } else { wsprintf(Buffer, TEXT(" ")); } break; default: #if (WINDOWSPC<1) //ASSERT(0); #endif break; } // end intask/irange/dowrite if (MapWindow::zoom.RealScale()<20 && islandable && dowrite) { TextInBox(hdc, &rc, Buffer, WayPointList[i].Screen.x+5, WayPointList[i].Screen.y, 0, &TextDisplayMode, true); dowrite=false; // do not pass it along } // Do not show takeoff for gliders, check TakeOffWayPoint if (i==RESWP_TAKEOFF) { if (TakeOffWayPoint) { intask=false; // 091031 let TAKEOFF be decluttered WayPointList[i].Visible=TRUE; } else { WayPointList[i].Visible=FALSE; dowrite=false; } } if(i==RESWP_OPTIMIZED) { dowrite = DoOptimizeRoute(); } if (dowrite) { MapWaypointLabelAdd( Buffer, WayPointList[i].Screen.x+5, WayPointList[i].Screen.y, &TextDisplayMode, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), intask,islandable,isairport,excluded,i,WayPointList[i].Style); } } // end if intask { ; } } // if visible } // for all waypoints qsort(&MapWaypointLabelList, MapWaypointLabelListCount, sizeof(MapWaypointLabel_t), MapWaypointLabelListCompare); int j; // now draw task/landable waypoints in order of range (closest last) // writing unconditionally for (j=MapWaypointLabelListCount-1; j>=0; j--){ MapWaypointLabel_t *E = &MapWaypointLabelList[j]; // draws if they are in task unconditionally, // otherwise, does comparison if ( E->inTask || (E->isLandable && !E->isExcluded) ) { TextInBox(hdc, &rc, E->Name, E->Pos.x, E->Pos.y, 0, &(E->Mode), false); // At low zoom, dont print the bitmap because drawn task would make it look offsetted if(MapWindow::zoom.RealScale() > 2) continue; // If we are at low zoom, use a dot for icons, so we dont clutter the screen if(MapWindow::zoom.RealScale() > 1) { if (BlackScreen) SelectObject(hDCTemp,hInvSmall); else SelectObject(hDCTemp,hSmall); } else { if (BlackScreen) SelectObject(hDCTemp,hInvTurnPoint); else SelectObject(hDCTemp,hTurnPoint); } DrawBitmapX(hdc, E->Pos.x-10, E->Pos.y-10, 20,20, hDCTemp,0,0,SRCPAINT,false); DrawBitmapX(hdc, E->Pos.x-10, E->Pos.y-10, 20,20, hDCTemp,20,0,SRCAND,false); } // wp in task } // for all waypoint, searching for those in task // now draw normal waypoints in order of range (furthest away last) // without writing over each other (or the task ones) for (j=0; j<MapWaypointLabelListCount; j++) { MapWaypointLabel_t *E = &MapWaypointLabelList[j]; if (!E->inTask && !E->isLandable ) { if ( TextInBox(hdc, &rc, E->Name, E->Pos.x, E->Pos.y, 0, &(E->Mode), true) == true) { // If we are at low zoom, use a dot for icons, so we dont clutter the screen if(MapWindow::zoom.RealScale() > 4) { if (BlackScreen) SelectObject(hDCTemp,hInvSmall); else SelectObject(hDCTemp,hSmall); } else { // We switch all styles in the correct order, to force a jump table by the compiler // It would be much better to use an array of bitmaps, but no time to do it for 3.0 switch(E->style) { case STYLE_NORMAL: goto turnpoint; break; // These are not used here in fact case STYLE_AIRFIELDGRASS: case STYLE_OUTLANDING: case STYLE_GLIDERSITE: case STYLE_AIRFIELDSOLID: goto turnpoint; break; case STYLE_MTPASS: SelectObject(hDCTemp,hMountpass); break; case STYLE_MTTOP: SelectObject(hDCTemp,hMountop); break; case STYLE_SENDER: SelectObject(hDCTemp,hSender); break; case STYLE_VOR: goto turnpoint; break; case STYLE_NDB: SelectObject(hDCTemp,hNdb); break; case STYLE_COOLTOWER: goto turnpoint; break; case STYLE_DAM: SelectObject(hDCTemp,hDam); break; case STYLE_TUNNEL: goto turnpoint; break; case STYLE_BRIDGE: SelectObject(hDCTemp,hBridge); break; case STYLE_POWERPLANT: case STYLE_CASTLE: goto turnpoint; break; case STYLE_INTERSECTION: SelectObject(hDCTemp,hIntersect); break; case STYLE_TRAFFIC: goto turnpoint; break; case STYLE_THERMAL: SelectObject(hDCTemp,hLKThermal); break; case STYLE_MARKER: SelectObject(hDCTemp,hBmpMarker); break; default: turnpoint: if (BlackScreen) SelectObject(hDCTemp,hInvTurnPoint); else SelectObject(hDCTemp,hTurnPoint); break; } // switch estyle } // below zoom threshold // We dont do stretching here. We are using different bitmaps for hi res. // The 20x20 size is large enough to make much bigger icons than the old ones. DrawBitmapX(hdc, E->Pos.x-10, E->Pos.y-10, 20,20, hDCTemp,0,0,SRCPAINT,false); DrawBitmapX(hdc, E->Pos.x-10, E->Pos.y-10, 20,20, hDCTemp,20,0,SRCAND,false); } } } } // end DrawWaypoint
void MapWindow::DrawWaypointsNew(HDC hdc, const RECT rc) { unsigned int i; int bestwp=-1; TCHAR Buffer[LKSIZEBUFFER]; TCHAR Buffer2[LKSIZEBUFFER]; TCHAR sAltUnit[LKSIZEBUFFERUNIT]; TextInBoxMode_t TextDisplayMode; static int resizer[10]={ 20,20,20,3,5,8,10,12,0 }; // if pan mode, show full names int pDisplayTextType = DisplayTextType; if (!WayPointList) return; _tcscpy(sAltUnit, Units::GetAltitudeName()); MapWaypointLabelListCount = 0; int arrivalcutoff=0, foundairport=0; bool isairport; bool islandpoint; #ifndef MAP_ZOOM if (MapScale <=20) for(i=0;i<NumberOfWayPoints;i++) { #else /* MAP_ZOOM */ if (MapWindow::zoom.Scale() <=20) for(i=0;i<NumberOfWayPoints;i++) { #endif /* MAP_ZOOM */ if (WayPointList[i].Visible != TRUE ) continue; // false may not be FALSE? if (WayPointCalc[i].IsAirport) { if (WayPointList[i].Reachable == FALSE) { SelectObject(hDCTemp,hBmpAirportUnReachable); } else { SelectObject(hDCTemp,hBmpAirportReachable); if ( arrivalcutoff < (int)(WayPointList[i].AltArivalAGL)) { arrivalcutoff = (int)(WayPointList[i].AltArivalAGL); bestwp=i; foundairport++; } } } else { if ( WayPointCalc[i].IsOutlanding ) { // outlanding if (WayPointList[i].Reachable == FALSE) SelectObject(hDCTemp,hBmpFieldUnReachable); else { SelectObject(hDCTemp,hBmpFieldReachable); // get the outlanding as bestwp only if no other choice if (foundairport == 0) { // do not set arrivalcutoff: any next reachable airport is better than an outlanding if ( arrivalcutoff < (int)(WayPointList[i].AltArivalAGL)) bestwp=i; } } } else continue; // do not draw icons for normal turnpoints here } DrawBitmapX(hdc, WayPointList[i].Screen.x-NIBLSCALE(10), WayPointList[i].Screen.y-NIBLSCALE(10), 20,20, hDCTemp,0,0,SRCPAINT); DrawBitmapX(hdc, WayPointList[i].Screen.x-NIBLSCALE(10), WayPointList[i].Screen.y-NIBLSCALE(10), 20,20, hDCTemp,20,0,SRCAND); } // for all waypoints if (foundairport==0 && bestwp>=0) arrivalcutoff = (int)WayPointList[bestwp].AltArivalAGL; for(i=0;i<NumberOfWayPoints;i++) { if(WayPointList[i].Visible ) { #ifdef HAVEEXCEPTIONS __try{ #endif bool irange = false; bool intask = false; bool islandable; // isairport+islandpoint bool excluded=false; bool dowrite; intask = WaypointInTask(i); dowrite = intask; // initially set only for intask TextDisplayMode.AsInt = 0; // airports are also landpoints. should be better handled isairport=((WayPointList[i].Flags & AIRPORT) == AIRPORT); islandpoint=((WayPointList[i].Flags & LANDPOINT) == LANDPOINT); islandable=WayPointCalc[i].IsLandable; // always in range if MapScale <=10 since no zoom in waypoints is documented and .Zoom is always 0. irange = WaypointInRange(i); #ifndef MAP_ZOOM if(MapScale > 20) { #else /* MAP_ZOOM */ if(MapWindow::zoom.Scale() > 20) { #endif /* MAP_ZOOM */ SelectObject(hDCTemp,hInvSmall); irange=false; goto NiklausWirth; // with compliments } if( islandable ) { if(WayPointList[i].Reachable){ TextDisplayMode.AsFlag.Reachable = 1; if ( isairport ) SelectObject(hDCTemp,hBmpAirportReachable); else SelectObject(hDCTemp,hBmpFieldReachable); if ((DeclutterLabels<MAPLABELS_ALLOFF)||intask) { dowrite = true; // exclude outlandings worst than visible airports, only when there are visible reachable airports! if ( isairport==false && islandpoint==true ) { if ( (int)WayPointList[i].AltArivalAGL >=2000 ) { // more filter excluded=true; } else { if ( (bestwp>=0) && (i==(unsigned)bestwp) && (foundairport==0) ) { // this outlanding is the best option isairport=true; islandpoint=false; // make it an airport TODO paint it as best } else { if ( foundairport >0 ) { if ( (int)WayPointList[i].AltArivalAGL <= arrivalcutoff ) { excluded=true; } } } } } else // do not display airport arrival if close to the best so far. // ex: best arrival is 1200m, include onlye below 1200/4 (prevent division by zero) // This way we only display far points, and skip closer points // WE NEED MORE INFO ABOUT LANDING POINTS: THE .CUP FORMAT WILL LET US KNOW WHAT IS // BEST TO SHOW AND WHAT IS NOT. Winpilot format is useless here. { dowrite=true;// TEST FIX not necessary probably // it's an airport if ( (bestwp>=0) && (i != (unsigned)bestwp) && (arrivalcutoff>600) ) { if ( (arrivalcutoff / ((int)WayPointList[i].AltArivalAGL+1))<4 ) { excluded=true; } } } } } else // landable waypoint is unreachable { dowrite=true; if ( isairport ) { SelectObject(hDCTemp,hBmpAirportUnReachable); } else { SelectObject(hDCTemp,hBmpFieldUnReachable); } } } else { // waypoint is an ordinary turnpoint #ifndef MAP_ZOOM if(MapScale > 4) { #else /* MAP_ZOOM */ if(MapWindow::zoom.Scale() > 4) { #endif /* MAP_ZOOM */ if (BlackScreen) SelectObject(hDCTemp,hInvSmall); else SelectObject(hDCTemp,hSmall); } else { if (BlackScreen) SelectObject(hDCTemp,hInvTurnPoint); else SelectObject(hDCTemp,hTurnPoint); } } // end landable-not landable NiklausWirth: if (intask || (OutlinedTp==(OutlinedTp_t)otAll) ) { TextDisplayMode.AsFlag.WhiteBold = 1; TextDisplayMode.AsFlag.Color=TEXTWHITE; } // No matter of how we thought to draw it, let it up to the user.. switch(NewMapDeclutter) { case 0: excluded=false; // no decluttering: show all airports and outlandings break; case 1: if ( isairport ) excluded=false; // show all airports, declutter outlandings break; default: break; // else work normally } // here come both turnpoints and landables.. if( intask || irange || dowrite) { // irange almost always set when MapScale <=10 bool draw_alt = TextDisplayMode.AsFlag.Reachable && ((DeclutterLabels<MAPLABELS_ONLYTOPO) || intask); // 100711 reachable landing point! if (excluded==true) draw_alt=false; // exclude close outlandings switch(pDisplayTextType) { case DISPLAYNAME: case DISPLAYFIRSTTHREE: case DISPLAYFIRSTFIVE: case DISPLAYFIRST8: case DISPLAYFIRST10: case DISPLAYFIRST12: dowrite = (DeclutterLabels<MAPLABELS_ONLYTOPO) || intask || islandable; // 100711 #ifndef MAP_ZOOM if ( (islandable && !isairport) && MapScale >=10 ) dowrite=0; // FIX then no need to go further #else /* MAP_ZOOM */ if ( (islandable && !isairport) && MapWindow::zoom.Scale() >=10 ) dowrite=0; // FIX then no need to go further #endif /* MAP_ZOOM */ // 101215 if (DisplayTextType == DISPLAYNAME) { _tcscpy(Buffer2,WayPointList[i].Name); } else { _tcsncpy(Buffer2, WayPointList[i].Name, resizer[DisplayTextType]); Buffer2[resizer[DisplayTextType]] = '\0'; } // ConvToUpper(Buffer2); if (draw_alt) { if ( ArrivalValue == (ArrivalValue_t) avAltitude ) { if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) ) wsprintf(Buffer, TEXT("%s:%d"), Buffer2, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY)); else wsprintf(Buffer, TEXT("%s:%d%s"), Buffer2, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit); } else wsprintf(Buffer, TEXT("%s:%d"), Buffer2, (int)WayPointCalc[i].GR); if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.AsFlag.Border = 1; TextDisplayMode.AsFlag.WhiteBold = 0; } else TextDisplayMode.AsFlag.WhiteBold = 1; // outlined TextDisplayMode.AsFlag.Color=TEXTWHITE; } else { //wsprintf(Buffer, TEXT("%s"),Buffer2); _tcscpy(Buffer,Buffer2); if (islandable && isairport) { TextDisplayMode.AsFlag.WhiteBold = 1; // outlined TextDisplayMode.AsFlag.Color=TEXTWHITE; } } break; case DISPLAYNUMBER: dowrite = (DeclutterLabels<MAPLABELS_ONLYTOPO) || intask || islandable; // 100620 #ifndef MAP_ZOOM if ( (islandable && !isairport) && MapScale >=10 ) dowrite=0; // FIX then no need to go further #else /* MAP_ZOOM */ if ( (islandable && !isairport) && MapWindow::zoom.Scale() >=10 ) dowrite=0; // FIX then no need to go further #endif /* MAP_ZOOM */ if (draw_alt) { if ( ArrivalValue == (ArrivalValue_t) avAltitude ) { if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) ) wsprintf(Buffer, TEXT("%d:%d"), WayPointList[i].Number, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY)); else wsprintf(Buffer, TEXT("%d:%d%s"), WayPointList[i].Number, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit); } else wsprintf(Buffer, TEXT("%d:%d"), WayPointList[i].Number, (int)(WayPointCalc[i].GR)); if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.AsFlag.Border = 1; TextDisplayMode.AsFlag.WhiteBold = 0; } else TextDisplayMode.AsFlag.WhiteBold = 1; // outlined TextDisplayMode.AsFlag.Color=TEXTWHITE; } else { wsprintf(Buffer, TEXT("%d"),WayPointList[i].Number); if (islandable && isairport) { TextDisplayMode.AsFlag.WhiteBold = 1; // outlined TextDisplayMode.AsFlag.Color=TEXTWHITE; } } break; case DISPLAYNAMEIFINTASK: dowrite = intask; if (intask) { if (draw_alt) { if ( ArrivalValue == (ArrivalValue_t) avAltitude ) { if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) ) wsprintf(Buffer, TEXT("%s:%d"), WayPointList[i].Name, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY)); else wsprintf(Buffer, TEXT("%s:%d%s"), WayPointList[i].Name, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit); } else wsprintf(Buffer, TEXT("%s:%d"), WayPointList[i].Name, (int)(WayPointCalc[i].GR)); if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.AsFlag.Border = 1; TextDisplayMode.AsFlag.WhiteBold = 0; } else TextDisplayMode.AsFlag.WhiteBold = 1; // outlined TextDisplayMode.AsFlag.Color=TEXTWHITE; } else { wsprintf(Buffer, TEXT("%s"),WayPointList[i].Name); // TODO CHECK THIS, UNTESTED.. if (islandable && isairport) { TextDisplayMode.AsFlag.WhiteBold = 1; // outlined TextDisplayMode.AsFlag.Color=TEXTWHITE; } } } else { wsprintf(Buffer, TEXT(" ")); dowrite=true; } break; case DISPLAYNONE: dowrite = (DeclutterLabels<MAPLABELS_ONLYTOPO) || intask || islandable; // 100711 if (draw_alt) { if ( ArrivalValue == (ArrivalValue_t) avAltitude ) { if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) ) wsprintf(Buffer, TEXT("%d"), (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY)); else wsprintf(Buffer, TEXT("%d%s"), (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit); } else wsprintf(Buffer, TEXT("%d"), (int)(WayPointCalc[i].GR) ); if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.AsFlag.Border = 1; TextDisplayMode.AsFlag.WhiteBold = 0; } else TextDisplayMode.AsFlag.WhiteBold = 1; // outlined TextDisplayMode.AsFlag.Color=TEXTWHITE; } else { wsprintf(Buffer, TEXT(" ")); } break; default: #if (WINDOWSPC<1) ASSERT(0); #endif break; } // end intask/irange/dowrite #ifndef MAP_ZOOM if (MapScale<20 && islandable && dowrite) { #else /* MAP_ZOOM */ if (MapWindow::zoom.Scale()<20 && islandable && dowrite) { #endif /* MAP_ZOOM */ TextInBox(hdc, Buffer, WayPointList[i].Screen.x+5, WayPointList[i].Screen.y, 0, TextDisplayMode, true); dowrite=false; // do not pass it along } // Do not show takeoff for gliders, check TakeOffWayPoint if (i==RESWP_TAKEOFF) { if (TakeOffWayPoint) { intask=false; // 091031 let TAKEOFF be decluttered WayPointList[i].Visible=TRUE; } else { WayPointList[i].Visible=FALSE; dowrite=false; } } if (dowrite) { MapWaypointLabelAdd( Buffer, WayPointList[i].Screen.x+5, WayPointList[i].Screen.y, TextDisplayMode, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), intask,islandable,isairport,excluded,i); } } // end if intask #ifdef HAVEEXCEPTIONS }__finally #endif { ; } } // if visible } // for all waypoints qsort(&MapWaypointLabelList, MapWaypointLabelListCount, sizeof(MapWaypointLabel_t), MapWaypointLabelListCompare); int j; // now draw task/landable waypoints in order of range (closest last) // writing unconditionally for (j=MapWaypointLabelListCount-1; j>=0; j--){ MapWaypointLabel_t *E = &MapWaypointLabelList[j]; // draws if they are in task unconditionally, // otherwise, does comparison if ( E->inTask || (E->isLandable && !E->isExcluded) ) { TextInBox(hdc, E->Name, E->Pos.x, E->Pos.y, 0, E->Mode, false); } } // now draw normal waypoints in order of range (furthest away last) // without writing over each other (or the task ones) for (j=0; j<MapWaypointLabelListCount; j++) { MapWaypointLabel_t *E = &MapWaypointLabelList[j]; if (!E->inTask && !E->isLandable ) { if ( TextInBox(hdc, E->Name, E->Pos.x, E->Pos.y, 0, E->Mode, true) == true) { #ifndef MAP_ZOOM if(MapScale > 4) { #else /* MAP_ZOOM */ if(MapWindow::zoom.Scale() > 4) { #endif /* MAP_ZOOM */ if (BlackScreen) // 091109 SelectObject(hDCTemp,hInvSmall); else SelectObject(hDCTemp,hSmall); } else { if (BlackScreen) // 091109 SelectObject(hDCTemp,hInvTurnPoint); else SelectObject(hDCTemp,hTurnPoint); } DrawBitmapX(hdc, E->Pos.x-NIBLSCALE(10), E->Pos.y-NIBLSCALE(10), 20,20, hDCTemp,0,0,SRCPAINT); DrawBitmapX(hdc, E->Pos.x-NIBLSCALE(10), E->Pos.y-NIBLSCALE(10), 20,20, hDCTemp,20,0,SRCAND); } } } } // end DrawWaypoint