// // Draw bearing line to target // void MapWindow::DrawGreatCircle(LKSurface& Surface, double startLon, double startLat, double targetLon, double targetLat, const RECT& rc) { POINT pt[2]; LatLon2Screen(startLon, startLat, pt[0]); LatLon2Screen(targetLon, targetLat, pt[1]); if(LKGeom::ClipLine(rc, pt[0], pt[1])) { const auto hpOld = Surface.SelectObject(LKPen_GABRG); Surface.Polyline(pt, 2); Surface.SelectObject(LK_BLACK_PEN); Surface.Polyline(pt, 2); Surface.SelectObject(hpOld); } }
void MapWindow::DrawTeammate(HDC hdc, RECT rc) { POINT point; if (TeammateCodeValid) { if(PointVisible(TeammateLongitude, TeammateLatitude) ) { LatLon2Screen(TeammateLongitude, TeammateLatitude, point); SelectObject(hDCTemp,hBmpTeammatePosition); DrawBitmapX(hdc, point.x-NIBLSCALE(10), point.y-NIBLSCALE(10), 20,20, hDCTemp,0,0,SRCPAINT,true); DrawBitmapX(hdc, point.x-NIBLSCALE(10), point.y-NIBLSCALE(10), 20,20, hDCTemp,20,0,SRCAND,true); } } }
void MapWindow::CalculateScreenPositionsThermalSources() { for (int i=0; i<MAX_THERMAL_SOURCES; i++) { if (DerivedDrawInfo.ThermalSources[i].LiftRate>0) { double dh = DerivedDrawInfo.NavAltitude -DerivedDrawInfo.ThermalSources[i].GroundHeight; if (dh<0) { DerivedDrawInfo.ThermalSources[i].Visible = false; continue; } double t = dh/DerivedDrawInfo.ThermalSources[i].LiftRate; double lat, lon; FindLatitudeLongitude(DerivedDrawInfo.ThermalSources[i].Latitude, DerivedDrawInfo.ThermalSources[i].Longitude, DerivedDrawInfo.WindBearing, -DerivedDrawInfo.WindSpeed*t, &lat, &lon); if (PointVisible(lon,lat)) { LatLon2Screen(lon, lat, DerivedDrawInfo.ThermalSources[i].Screen); DerivedDrawInfo.ThermalSources[i].Visible = PointVisible(DerivedDrawInfo.ThermalSources[i].Screen); } else { DerivedDrawInfo.ThermalSources[i].Visible = false; } } else { DerivedDrawInfo.ThermalSources[i].Visible = false; } } }
void MapWindow::CalculateScreenPositionsGroundline(void) { bool mm=IsMultiMapSharedNoMain(); if (FinalGlideTerrain) { if (mm) { LatLon2ScreenMultimap(DerivedDrawInfo.GlideFootPrint, Groundline, NUMTERRAINSWEEPS+1, 1); } else { LatLon2Screen(DerivedDrawInfo.GlideFootPrint, Groundline, NUMTERRAINSWEEPS+1, 1); } #ifdef GTL2 if (FinalGlideTerrain > 2) {// show next-WP line if (mm) { LatLon2ScreenMultimap(GlideFootPrint2, Groundline2, NUMTERRAINSWEEPS+1, 1); } else { LatLon2Screen(GlideFootPrint2, Groundline2, NUMTERRAINSWEEPS+1, 1); } } #endif } }
void MapWindow::DrawAirspaceLabels(HDC hdc, const RECT rc, const POINT Orig_Aircraft) { static short int label_sequencing_divider = 0; CAirspaceList::const_iterator it; const CAirspaceList& airspaces_to_draw = CAirspaceManager::Instance().GetAirspacesForWarningLabels(); if (label_sequencing_divider) --label_sequencing_divider; // Draw warning position and label on top of all airspaces if (1) { CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef()); for (it=airspaces_to_draw.begin(); it != airspaces_to_draw.end(); ++it) { if ((*it)->WarningLevel() > awNone) { POINT sc; double lon; double lat; int vdist; AirspaceWarningDrawStyle_t vlabeldrawstyle, hlabeldrawstyle; bool distances_ready = (*it)->GetWarningPoint(lon, lat, hlabeldrawstyle, vdist, vlabeldrawstyle); TCHAR hbuf[NAME_SIZE+16], vDistanceText[16]; TextInBoxMode_t TextDisplayMode = {0}; bool hlabel_draws = false; bool vlabel_draws = false; // Horizontal warning point if (distances_ready && (hlabeldrawstyle > awsHidden) && PointVisible(lon, lat)) { LatLon2Screen(lon, lat, sc); DrawBitmapIn(hdc, sc, hAirspaceWarning,true); Units::FormatUserAltitude(vdist, vDistanceText, sizeof(vDistanceText)/sizeof(vDistanceText[0])); _tcscpy(hbuf, (*it)->Name()); wcscat(hbuf, TEXT(" ")); wcscat(hbuf, vDistanceText); switch (hlabeldrawstyle) { default: case awsHidden: case awsBlack: TextDisplayMode.Color = RGB_BLACK; break; case awsAmber: TextDisplayMode.Color = RGB_ORANGE; break; case awsRed: TextDisplayMode.Color = RGB_RED; break; } // sw TextDisplayMode.SetTextColor = 1; TextDisplayMode.AlligneCenter = 1; if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.Border = 1; } else { if (TextDisplayMode.Color==RGB_BLACK) TextDisplayMode.WhiteBold = 0; // no black outline for black background.. else TextDisplayMode.WhiteBold = 1; // outlined } hlabel_draws = TextInBox(hdc, &rc, hbuf, sc.x, sc.y+NIBLSCALE(15), 0, &TextDisplayMode, true); } // Vertical warning point if (distances_ready && vlabeldrawstyle > awsHidden) { //DrawBitmapIn(hdc, Orig_Aircraft, hAirspaceWarning); Units::FormatUserAltitude(vdist, vDistanceText, sizeof(vDistanceText)/sizeof(vDistanceText[0])); _tcscpy(hbuf, (*it)->Name()); wcscat(hbuf, TEXT(" ")); wcscat(hbuf, vDistanceText); switch (vlabeldrawstyle) { default: case awsHidden: case awsBlack: TextDisplayMode.Color = RGB_BLACK; break; case awsAmber: TextDisplayMode.Color = RGB_ORANGE; break; case awsRed: TextDisplayMode.Color = RGB_RED; break; } // sw TextDisplayMode.SetTextColor = 1; TextDisplayMode.AlligneCenter = 1; if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) { TextDisplayMode.Border = 1; } else { if (TextDisplayMode.Color==RGB_BLACK) TextDisplayMode.WhiteBold = 0; // no black outline for black background.. else TextDisplayMode.WhiteBold = 1; // outlined } vlabel_draws = TextInBox(hdc, &rc, hbuf, Orig_Aircraft.x, Orig_Aircraft.y+NIBLSCALE(15), 0, &TextDisplayMode, true); } if (!label_sequencing_divider) CAirspaceManager::Instance().AirspaceWarningLabelPrinted(**it, hlabel_draws || vlabel_draws); }// if warnlevel>awnone }//for }// if(1) mutex if (!label_sequencing_divider) label_sequencing_divider=3; // Do label sequencing slower than update rate }
void MapWindow::DrawBearing(HDC hdc, const RECT rc) { int overindex=GetOvertargetIndex(); if (overindex<0) return; double startLat = DrawInfo.Latitude; double startLon = DrawInfo.Longitude; double targetLat; double targetLon; if (OvertargetMode>OVT_TASK) { LockTaskData(); targetLat = WayPointList[overindex].Latitude; targetLon = WayPointList[overindex].Longitude; UnlockTaskData(); DrawGreatCircle(hdc, startLon, startLat, targetLon, targetLat, rc); } else { if (!ValidTaskPoint(ActiveWayPoint)) { return; } LockTaskData(); if (AATEnabled && ( DoOptimizeRoute() || ((ActiveWayPoint>0) && ValidTaskPoint(ActiveWayPoint+1))) ) { targetLat = Task[ActiveWayPoint].AATTargetLat; targetLon = Task[ActiveWayPoint].AATTargetLon; } else { targetLat = WayPointList[Task[ActiveWayPoint].Index].Latitude; targetLon = WayPointList[Task[ActiveWayPoint].Index].Longitude; } UnlockTaskData(); DrawGreatCircle(hdc, startLon, startLat, targetLon, targetLat, rc); if (mode.Is(Mode::MODE_TARGET_PAN)) { // Draw all of task if in target pan mode startLat = targetLat; startLon = targetLon; LockTaskData(); for (int i=ActiveWayPoint+1; i<MAXTASKPOINTS; i++) { if (ValidTaskPoint(i)) { if (AATEnabled && ValidTaskPoint(i+1)) { targetLat = Task[i].AATTargetLat; targetLon = Task[i].AATTargetLon; } else { targetLat = WayPointList[Task[i].Index].Latitude; targetLon = WayPointList[Task[i].Index].Longitude; } DrawGreatCircle(hdc, startLon, startLat, targetLon, targetLat, rc); startLat = targetLat; startLon = targetLon; } } UnlockTaskData(); } } if (AATEnabled) { // draw symbol at target, makes it easier to see LockTaskData(); if(mode.Is(Mode::MODE_TARGET_PAN)) { for(int i=ActiveWayPoint+1; i<MAXTASKPOINTS; i++) { if(ValidTaskPoint(i) && ValidTaskPoint(i+1)) { if(i>= ActiveWayPoint) { POINT sct; LatLon2Screen(Task[i].AATTargetLon, Task[i].AATTargetLat, sct); DrawBitmapIn(hdc, sct, hBmpTarget,true); } } } } if(ValidTaskPoint(ActiveWayPoint+1) && (DoOptimizeRoute() || (ActiveWayPoint>0)) ) { POINT sct; LatLon2Screen(Task[ActiveWayPoint].AATTargetLon, Task[ActiveWayPoint].AATTargetLat, sct); DrawBitmapIn(hdc, sct, hBmpTarget,true); } UnlockTaskData(); } }
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); }
// This is painting traffic icons on the screen. void MapWindow::LKDrawFLARMTraffic(HDC hDC, RECT rc, 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 scaler[5]; static short tscaler=0; if (DoInit[MDI_DRAWFLARMTRAFFIC]) { switch (ScreenSize) { case ss480x640: case ss480x800: case ss896x672: case ss800x480: case ss640x480: iCircleSize = 9; iRectangleSize = 5; scaler[0]=-1*(NIBLSCALE(4)-2); scaler[1]=NIBLSCALE(5)-2; scaler[2]=-1*(NIBLSCALE(6)-2); scaler[3]=NIBLSCALE(4)-2; scaler[4]=NIBLSCALE(2)-2; tscaler=NIBLSCALE(7)-2; break; case ss240x320: case ss272x480: case ss320x240: case ss480x272: case ss720x408: case ss480x234: case ss400x240: iCircleSize = 7; iRectangleSize = 4; scaler[0]=-1*(NIBLSCALE(8)-2); scaler[1]=NIBLSCALE(10)-2; scaler[2]=-1*(NIBLSCALE(12)-2); scaler[3]=NIBLSCALE(8)-2; scaler[4]=NIBLSCALE(4)-2; tscaler=NIBLSCALE(13)-2; break; default: iCircleSize = 7; iRectangleSize = 4; scaler[0]=-1*NIBLSCALE(4); scaler[1]=NIBLSCALE(5); scaler[2]=-1*NIBLSCALE(6); scaler[3]=NIBLSCALE(4); scaler[4]=NIBLSCALE(2); tscaler=NIBLSCALE(7); break; } DoInit[MDI_DRAWFLARMTRAFFIC]=false; } HPEN hpold; HPEN thinBlackPen = LKPen_Black_N1; POINT Arrow[5]; TCHAR lbuffer[50]; hpold = (HPEN)SelectObject(hDC, thinBlackPen); 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 HFONT oldfont = (HFONT)SelectObject(hDC, 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; LatLon2Screen(target_lon, target_lat, sc); sc_name = sc; sc_name.y -= NIBLSCALE(16); sc_av = sc_name; wsprintf(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) { if (_tcslen(lbuffer) >0) _stprintf(lbuffer,_T("%s:%.1f"),lbuffer,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(hDC, lbuffer, sc.x+tscaler, sc.y+tscaler, 0, &displaymode, false); // red circle if ((DrawInfo.FLARM_Traffic[i].AlarmLevel>0) && (DrawInfo.FLARM_Traffic[i].AlarmLevel<4)) { DrawBitmapIn(hDC, sc, hFLARMTraffic,true); } #if 0 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; #endif 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]; /* switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321 case LKT_GHOST: SelectObject(hDC, yellowBrush); break; case LKT_ZOMBIE: SelectObject(hDC, redBrush); break; default: SelectObject(hDC, 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; SelectObject(hDC, *variobrush[iVarioIdx]); switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321 case LKT_GHOST: Rectangle(hDC, sc.x-iRectangleSize, sc.y-iRectangleSize,sc.x+iRectangleSize, sc.y+iRectangleSize); break; case LKT_ZOMBIE: Circle(hDC, sc.x, sc.x, iCircleSize, rc, true, true ); break; default: PolygonRotateShift(Arrow, 5, sc.x, sc.y, DrawInfo.FLARM_Traffic[i].TrackBearing - DisplayAngle); Polygon(hDC,Arrow,5); break; } } } SelectObject(hDC, oldfont); SelectObject(hDC, hpold); }
void MapWindow::DrawGlideThroughTerrain(LKSurface& Surface, const RECT& rc) { LKPen hpOld; //double h,dh; TCHAR hbuf[10]; static bool doinit=true; static TextInBoxMode_t tmode = {0}; bool wrotevalue=false; if (doinit) { memset((void*)&tmode, 0, sizeof(TextInBoxMode_t)); tmode.Border=1; doinit=false; } #ifdef GTL2 bool ValidTP = ValidTaskPoint(ActiveWayPoint); // draw glide terrain line around next WP bool DrawGTL2 = ValidTP && (FinalGlideTerrain > 2); static bool LastDrewGTL2 = false; if (DrawGTL2) { int wp_index = (DoOptimizeRoute() || ACTIVE_WP_IS_AAT_AREA) ? RESWP_OPTIMIZED : TASKINDEX; double alt_arriv = WayPointCalc[wp_index].AltArriv[AltArrivMode]; // Calculate arrival altitude at the next waypoint relative to // the "terrain height" safety setting. if (CheckSafetyAltitudeApplies(wp_index)) alt_arriv += SAFETYALTITUDEARRIVAL/10; // AGL alt_arriv -= SAFETYALTITUDETERRAIN/10; // rel. to "terrain height" if (alt_arriv <= 0) DrawGTL2 = false; } if (LastDrewGTL2 != DrawGTL2) { LastDrewGTL2 = DrawGTL2; if (!DrawGTL2) ClearGTL2(); // clear next-WP glide terrain line } #endif hpOld = Surface.SelectObject(hpTerrainLineBg); #ifdef GTL2 // Draw the wide, solid part of the glide terrain line. #else // draw a dashed perimetral line first #endif Surface.Polyline(Groundline,NUMTERRAINSWEEPS+1, rc); // draw perimeter if selected and during a flight #ifdef GTL2 if (((FinalGlideTerrain == 1) || (FinalGlideTerrain == 3)) || ((!IsMultimapTerrain() || !DerivedDrawInfo.Flying) && FinalGlideTerrain)) { #else if ((FinalGlideTerrain==1) || ((!IsMultimapTerrain() || !DerivedDrawInfo.Flying) && (FinalGlideTerrain==2))) { #endif Surface.SelectObject(hpTerrainLine); Surface.Polyline(Groundline,NUMTERRAINSWEEPS+1, rc); } #ifdef GTL2 // draw glide terrain line around next waypoint if (DrawGTL2) { // Draw a solid white line. Surface.SelectObject(LKPen_White_N2); Surface.Polyline(Groundline2, NUMTERRAINSWEEPS+1, rc); // Draw a dashed red line. Surface.DrawDashPoly(NIBLSCALE(2), RGB_RED, Groundline2, NUMTERRAINSWEEPS+1, rc); } #endif // draw red cross obstacles only if destination looks reachable! // only if using OVT_TASK of course! #ifdef GTL2 if ((OvertargetMode == OVT_TASK) && DerivedDrawInfo.Flying && ValidTP) #else if ( (OvertargetMode==OVT_TASK) && DerivedDrawInfo.Flying && ValidTaskPoint(ActiveWayPoint)) #endif if (WayPointCalc[TASKINDEX].AltArriv[AltArrivMode] >0) { POINT sc; // If calculations detected an obstacle... if ((DerivedDrawInfo.TerrainWarningLatitude != 0.0) &&(DerivedDrawInfo.TerrainWarningLongitude != 0.0)) { // only if valid position, and visible if (DerivedDrawInfo.FarObstacle_Lon >0) if (PointVisible(DerivedDrawInfo.FarObstacle_Lon, DerivedDrawInfo.FarObstacle_Lat)) { LatLon2Screen(DerivedDrawInfo.FarObstacle_Lon, DerivedDrawInfo.FarObstacle_Lat, sc); DrawBitmapIn(Surface, sc, hTerrainWarning,true); if (DerivedDrawInfo.FarObstacle_AltArriv <=-50 || DerivedDrawInfo.FarObstacle_Dist<5000 ) { _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.FarObstacle_AltArriv); TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); wrotevalue=true; } } // visible far obstacle if (PointVisible(DerivedDrawInfo.TerrainWarningLongitude, DerivedDrawInfo.TerrainWarningLatitude)) { LatLon2Screen(DerivedDrawInfo.TerrainWarningLongitude, DerivedDrawInfo.TerrainWarningLatitude, sc); DrawBitmapIn(Surface, sc, hTerrainWarning,true); #if 0 // 091203 add obstacle altitude on moving map h = max(0,RasterTerrain::GetTerrainHeight(DerivedDrawInfo.TerrainWarningLatitude, DerivedDrawInfo.TerrainWarningLongitude)); if (h==TERRAIN_INVALID) h=0; //@ 101027 FIX but unused dh = CALCULATED_INFO.NavAltitude - h - (SAFETYALTITUDETERRAIN/10); _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*dh); TextInBox(hDC,&rc,hbuf,sc.x+NIBLSCALE(10), sc.y, 0, tmode,false); #else // if far obstacle was painted with value... if (wrotevalue) { // if it is not too near the nearest.. if ( (fabs(DerivedDrawInfo.FarObstacle_Lon - DerivedDrawInfo.TerrainWarningLongitude) >0.02) && (fabs(DerivedDrawInfo.FarObstacle_Lat - DerivedDrawInfo.TerrainWarningLatitude) >0.02)) { // and it the arrival altitude is actually negative (rounding terrain errors?) if ( DerivedDrawInfo.ObstacleAltArriv <=-50) // and there is a significant difference in the numbers, then paint value also for nearest if ( fabs(DerivedDrawInfo.ObstacleAltArriv - DerivedDrawInfo.FarObstacle_AltArriv) >100 ) { _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.ObstacleAltArriv); TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); } } } else { // else paint value only if meaningful or very close to us // -1 to 10m become -1 for rounding errors if ( (DerivedDrawInfo.ObstacleAltArriv >-1) && (DerivedDrawInfo.ObstacleAltArriv <10)) DerivedDrawInfo.ObstacleAltArriv=-1; if (DerivedDrawInfo.ObstacleAltArriv <=-50 || ((DerivedDrawInfo.ObstacleAltArriv<0) && (DerivedDrawInfo.ObstacleDistance<5000)) ) { _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.ObstacleAltArriv); TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); } } #endif } // visible nearest obstacle } // obstacles detected } // within glide range Surface.SelectObject(hpOld); }
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 = SectorType; double Radius = SectorRadius; if (AATEnabled) { Type = Task[i].AATType; Radius = Task[i].AATCircleRadius; } 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 2: 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; } 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++) { bool is_first = (Task[i].Index < Task[i + 1].Index); 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[Task[i].Index].Screen; sct2 = WayPointList[Task[i + 1].Index].Screen; } if ((i >= ActiveWayPoint && DoOptimizeRoute()) || !DoOptimizeRoute()) { if (is_first) { DrawMulticolorDashLine(hdc, size_tasklines, sct1, sct2, taskcolor, RGB_BLACK,rc); } else { DrawMulticolorDashLine(hdc, size_tasklines, sct2, sct1, 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)); PolygonRotateShift(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); } } { UnlockTaskData(); } // restore original color SetTextColor(hDCTemp, origcolor); SelectObject(hdc, oldpen); SelectObject(hdc, oldbrush); }
void MapWindow::DrawProjectedTrack(HDC hdc, const RECT rc, const POINT Orig) { if ((ActiveWayPoint<=0) || !ValidTaskPoint(ActiveWayPoint) || !AATEnabled) { return; } if (DerivedDrawInfo.Circling) { // don't display in various modes return; } // TODO feature: maybe have this work even if no task? // TODO feature: draw this also when in target pan mode LockTaskData(); // protect from external task changes double startLat = DrawInfo.Latitude; double startLon = DrawInfo.Longitude; double previousLat; double previousLon; if (AATEnabled) { previousLat = Task[max(0,ActiveWayPoint-1)].AATTargetLat; previousLon = Task[max(0,ActiveWayPoint-1)].AATTargetLon; } else { previousLat = WayPointList[Task[max(0,ActiveWayPoint-1)].Index].Latitude; previousLon = WayPointList[Task[max(0,ActiveWayPoint-1)].Index].Longitude; } UnlockTaskData(); double distance_from_previous, bearing; DistanceBearing(previousLat, previousLon, startLat, startLon, &distance_from_previous, &bearing); if (distance_from_previous < 100.0) { bearing = DrawInfo.TrackBearing; // too short to have valid data } POINT pt[2] = {{0,-75},{0,-400}}; if (mode.Is(Mode::MODE_TARGET_PAN)) { double screen_range = GetApproxScreenRange(); double flow = 0.4; double fhigh = 1.5; screen_range = max(screen_range, DerivedDrawInfo.WaypointDistance); double p1Lat; double p1Lon; double p2Lat; double p2Lon; FindLatitudeLongitude(startLat, startLon, bearing, flow*screen_range, &p1Lat, &p1Lon); FindLatitudeLongitude(startLat, startLon, bearing, fhigh*screen_range, &p2Lat, &p2Lon); LatLon2Screen(p1Lon, p1Lat, pt[0]); LatLon2Screen(p2Lon, p2Lat, pt[1]); } else if (fabs(bearing-DerivedDrawInfo.WaypointBearing)<10) { // too small an error to bother return; } else { pt[1].y = (long)(-max(MapRect.right-MapRect.left, MapRect.bottom-MapRect.top)*1.2); PolygonRotateShift(pt, 2, Orig.x, Orig.y, bearing-DisplayAngle); } DrawDashLine(hdc, 2, pt[0], pt[1], RGB(0,0,0), rc); }
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; }
void MapWindow::CalculateScreenPositions(POINT Orig, RECT rc, POINT *Orig_Aircraft) { unsigned int i; Orig_Screen = Orig; if (!mode.AnyPan()) { if (GliderCenter && DerivedDrawInfo.Circling && (EnableThermalLocator==2)) { if (DerivedDrawInfo.ThermalEstimate_R>0) { PanLongitude = DerivedDrawInfo.ThermalEstimate_Longitude; PanLatitude = DerivedDrawInfo.ThermalEstimate_Latitude; // TODO enhancement: only pan if distance of center to // aircraft is smaller than one third screen width POINT screen; LatLon2Screen(PanLongitude, PanLatitude, screen); LatLon2Screen(DrawInfo.Longitude, DrawInfo.Latitude, *Orig_Aircraft); if ((fabs((double)Orig_Aircraft->x-screen.x)<(rc.right-rc.left)/3) && (fabs((double)Orig_Aircraft->y-screen.y)<(rc.bottom-rc.top)/3)) { } else { // out of bounds, center on aircraft PanLongitude = DrawInfo.Longitude; PanLatitude = DrawInfo.Latitude; } } else { PanLongitude = DrawInfo.Longitude; PanLatitude = DrawInfo.Latitude; } } else { // Pan is off PanLongitude = DrawInfo.Longitude; PanLatitude = DrawInfo.Latitude; } } LatLon2Screen(DrawInfo.Longitude, DrawInfo.Latitude, *Orig_Aircraft); // very important screenbounds_latlon = CalculateScreenBounds(0.0, rc); // Old note obsoleted 121111: // preserve this calculation for 0.0 until next round! // This is already done since screenbounds_latlon is global. Beware that DrawTrail will change it later on // to expand boundaries by 1 minute // get screen coordinates for all task waypoints LockTaskData(); if (!WayPointList.empty()) { for (i=0; i<MAXTASKPOINTS; i++) { unsigned index = Task[i].Index; if (index < WayPointList.size()) { LatLon2Screen(WayPointList[index].Longitude, WayPointList[index].Latitude, WayPointList[index].Screen); WayPointList[index].Visible = PointVisible(WayPointList[index].Screen); } else { // No need to continue. break; } } if (EnableMultipleStartPoints) { for(i=0; i<MAXSTARTPOINTS-1; i++) { unsigned index = StartPoints[i].Index; if (StartPoints[i].Active && (index < WayPointList.size())) { LatLon2Screen(WayPointList[index].Longitude, WayPointList[index].Latitude, WayPointList[index].Screen); WayPointList[index].Visible = PointVisible(WayPointList[index].Screen); } else { // No Need to continue. break; } } } // only calculate screen coordinates for waypoints that are visible // TODO 110203 OPTIMIZE THIS ! for(i=0; i<WayPointList.size(); i++) { WayPointList[i].Visible = false; if (!WayPointList[i].FarVisible) continue; if(PointVisible(WayPointList[i].Longitude, WayPointList[i].Latitude) ) { LatLon2Screen(WayPointList[i].Longitude, WayPointList[i].Latitude, WayPointList[i].Screen); WayPointList[i].Visible = PointVisible(WayPointList[i].Screen); } } } if(TrailActive) { iSnailNext = SnailNext; iLongSnailNext = LongSnailNext; // set this so that new data doesn't arrive between calculating // this and the screen updates } if (EnableMultipleStartPoints) { for(i=0; i<MAXSTARTPOINTS-1; i++) { if (StartPoints[i].Active && ValidWayPointFast(StartPoints[i].Index)) { LatLon2Screen(StartPoints[i].SectorEndLon, StartPoints[i].SectorEndLat, StartPoints[i].End); LatLon2Screen(StartPoints[i].SectorStartLon, StartPoints[i].SectorStartLat, StartPoints[i].Start); } } } for(i=0; i<MAXTASKPOINTS-1; i++) { bool this_valid = ValidTaskPointFast(i); bool next_valid = ValidTaskPointFast(i+1); if (AATEnabled && this_valid) { LatLon2Screen(Task[i].AATTargetLon, Task[i].AATTargetLat, Task[i].Target); } if(this_valid && !next_valid) { // finish LatLon2Screen(Task[i].SectorEndLon, Task[i].SectorEndLat, Task[i].End); LatLon2Screen(Task[i].SectorStartLon, Task[i].SectorStartLat, Task[i].Start); // No need to continue. break; } if(this_valid && next_valid) { LatLon2Screen(Task[i].SectorEndLon, Task[i].SectorEndLat, Task[i].End); LatLon2Screen(Task[i].SectorStartLon, Task[i].SectorStartLat, Task[i].Start); if((AATEnabled) && (Task[i].AATType == SECTOR)) { LatLon2Screen(Task[i].AATStartLon, Task[i].AATStartLat, Task[i].AATStart); LatLon2Screen(Task[i].AATFinishLon, Task[i].AATFinishLat, Task[i].AATFinish); } if (AATEnabled && (((int)i==ActiveWayPoint) || (mode.Is(Mode::MODE_TARGET_PAN) && ((int)i==TargetPanIndex)))) { for (int j=0; j<MAXISOLINES; j++) { if (TaskStats[i].IsoLine_valid[j]) { LatLon2Screen(TaskStats[i].IsoLine_Longitude[j], TaskStats[i].IsoLine_Latitude[j], TaskStats[i].IsoLine_Screen[j]); } } } } } UnlockTaskData(); }