/** * @brief Sets a result for points based contests * * @param type The type of the contest * @param traceResult The result data to set */ void CContestMgr::PointsResult(TType type, const CTrace &traceResult) { // prepare result CPointGPSArray pointArray; const CTrace::CPoint *point = traceResult.Front(); unsigned distance = 0; while(point) { if(pointArray.size()) distance += point->GPS().Distance(pointArray.back()); pointArray.push_back(point->GPS()); point = point->Next(); } // store result if(distance > _resultArray[type].Distance()) { float score; switch(type) { case TYPE_OLC_CLASSIC: case TYPE_OLC_CLASSIC_PREDICTED: score = distance / 1000.0 * 100 / _handicap; break; case TYPE_OLC_LEAGUE: score = distance / 1000.0 / 2.5 * 200 / (_handicap + 100); break; default: score = 0; } _resultArray[type] = CResult(type, distance, score, pointArray); } }
void Statistics::RenderTask(LKSurface& Surface, const RECT& rc, const bool olcmode) { int i, j; unsigned int ui; double fXY_Scale = 1.5; double lat1 = 0; double lon1 = 0; double lat2 = 0; double lon2 = 0; double x1, y1, x2=0, y2=0; double lat_c, lon_c; double aatradius[MAXTASKPOINTS]; // find center ResetScale(); if ( (!ValidTaskPoint(0) || !ValidTaskPoint(1)) && !olcmode) { DrawNoData(Surface,rc); return; } for (i=0; i<MAXTASKPOINTS; i++) { aatradius[i]=0; } bool nowaypoints = true; for (i=0; i<MAXTASKPOINTS; i++) { if (ValidTaskPoint(i)) { lat1 = WayPointList[Task[i].Index].Latitude; lon1 = WayPointList[Task[i].Index].Longitude; ScaleYFromValue(rc, lat1); ScaleXFromValue(rc, lon1); nowaypoints = false; } } if (nowaypoints ) { DrawNoData(Surface, rc); return; } CPointGPSArray trace; CContestMgr::Instance().Trace(trace); for(ui=0; ui<trace.size(); ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); ScaleYFromValue(rc, lat1); ScaleXFromValue(rc, lon1); } const auto hfOldU = Surface.SelectObject(LK8InfoNormalFont); lat_c = (y_max+y_min)/2; lon_c = (x_max+x_min)/2; int nwps = 0; // find scale ResetScale(); lat1 = GPS_INFO.Latitude; lon1 = GPS_INFO.Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); for (i=0; i<MAXTASKPOINTS; i++) { if (ValidTaskPoint(i)) { nwps++; lat1 = WayPointList[Task[i].Index].Latitude; lon1 = WayPointList[Task[i].Index].Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); if (AATEnabled) { double aatlat; double aatlon; double bearing; double radius; if (ValidTaskPoint(i+1)) { if (Task[i].AATType == SECTOR) radius = Task[i].AATSectorRadius; else radius = Task[i].AATCircleRadius; for (j=0; j<4; j++) { bearing = j*360.0/4; FindLatitudeLongitude(WayPointList[Task[i].Index].Latitude, WayPointList[Task[i].Index].Longitude, bearing, radius, &aatlat, &aatlon); x1 = (aatlon-lon_c)*fastcosine(aatlat); y1 = (aatlat-lat_c); ScaleXFromValue(rc, x1); ScaleYFromValue(rc, y1); if (j==0) { aatradius[i] = fabs(aatlat-WayPointList[Task[i].Index].Latitude); } } } else { aatradius[i] = 0; } } } } for(ui=0; ui<trace.size(); ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); } ScaleMakeSquare(rc); // draw aat areas if (AATEnabled) { for (i=MAXTASKPOINTS-1; i>0; i--) { if (ValidTaskPoint(i)) { lat1 = WayPointList[Task[i-1].Index].Latitude; lon1 = WayPointList[Task[i-1].Index].Longitude; lat2 = WayPointList[Task[i].Index].Latitude; lon2 = WayPointList[Task[i].Index].Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); #ifdef HAVE_HATCHED_BRUSH Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(AATASK)); #else Surface.SelectObject(LKBrush_Yellow); #endif Surface.SelectObject(LK_WHITE_PEN); if (Task[i].AATType == SECTOR) { Surface.Segment((long)((x2-x_min)*xscale+rc.left+BORDER_X),(long)((y_max-y2)*yscale+rc.top),(long)(aatradius[i]*yscale),rc, Task[i].AATStartRadial, Task[i].AATFinishRadial); } else { Surface.DrawCircle((long)((x2-x_min)*xscale+rc.left+BORDER_X), (long)((y_max-y2)*yscale+rc.top), (long)(aatradius[i]*yscale), true); } } } } if (!AATEnabled) { for (i=MAXTASKPOINTS-1; i>0; i--) { if (ValidTaskPoint(i) && ValidTaskPoint(i-1)) { lat1 = WayPointList[Task[i-1].Index].Latitude; lon1 = WayPointList[Task[i-1].Index].Longitude; if (!ValidTaskPoint(1) ) { lat2 = GPS_INFO.Latitude; lon2 = GPS_INFO.Longitude; } else { lat2 = WayPointList[Task[i].Index].Latitude; lon2 = WayPointList[Task[i].Index].Longitude; } x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); // DrawLine(hdc, rc, x1, y1, x2, y2, STYLE_DASHGREEN); if( ValidTaskPoint(4) && i <2) goto skip_FAI; #ifndef UNDITHER RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTYELLOW ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_LIGHTCYAN ); #else RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTGREY ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_GREY ); #endif skip_FAI: DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_DASHGREEN); Surface.Segment((long)((x2-x_min)*xscale+rc.left+BORDER_X),(long)((y_max-y2)*yscale+rc.top),(long)(aatradius[i]*yscale),rc, Task[i].AATStartRadial, Task[i].AATFinishRadial); } } if( ValidTaskPoint(1) && ValidTaskPoint(3)) { lat1 = WayPointList[Task[3].Index].Latitude; lon1 = WayPointList[Task[3].Index].Longitude; lat2 = WayPointList[Task[1].Index].Latitude; lon2 = WayPointList[Task[1].Index].Longitude; #ifndef UNDITHER RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTYELLOW ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_LIGHTCYAN ); #else RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTGREY ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_GREY ); #endif } } // draw task lines and label for (i=MAXTASKPOINTS-1; i>0; i--) { if (ValidTaskPoint(i) && ValidTaskPoint(i-1)) { lat1 = WayPointList[Task[i-1].Index].Latitude; lon1 = WayPointList[Task[i-1].Index].Longitude; if (!ValidTaskPoint(1) ) { lat2 = GPS_INFO.Latitude; lon2 = GPS_INFO.Longitude; } else { lat2 = WayPointList[Task[i].Index].Latitude; lon2 = WayPointList[Task[i].Index].Longitude; } x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_BLUETHIN); #if (WINDOWSPC>0) Surface.SetBackgroundOpaque(); #endif TCHAR text[100]; Surface.SetTextColor(RGB_BLUE); /* if ((i==nwps-1) && (Task[i].Index == Task[0].Index)) { _stprintf(text,TEXT("%0d"),1); DrawLabel(hdc, rc, text, x1+(x2-x1)/2, y1+(y2-y1)/2); } else */ { _stprintf(text,TEXT("%0d"),i); DrawLabel(Surface, rc, text, x1+(x2-x1)/2, y1+(y2-y1)/2); } if ((i==ActiveTaskPoint)&&(!AATEnabled)) { lat1 = GPS_INFO.Latitude; lon1 = GPS_INFO.Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_REDTHICK); } } } // draw aat task line if (AATEnabled) { for (i=MAXTASKPOINTS-1; i>0; i--) { if (ValidTaskPoint(i) && ValidTaskPoint(i-1)) { if (i==1) { lat1 = WayPointList[Task[i-1].Index].Latitude; lon1 = WayPointList[Task[i-1].Index].Longitude; } else { lat1 = Task[i-1].AATTargetLat; lon1 = Task[i-1].AATTargetLon; } lat2 = Task[i].AATTargetLat; lon2 = Task[i].AATTargetLon; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_REDTHICK); } } } DrawXGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); DrawYGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); Surface.SelectObject(hfOldU); // Draw aircraft on top lat1 = GPS_INFO.Latitude; lon1 = GPS_INFO.Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); Surface.SetBackgroundTransparent(); DrawLabel(Surface, rc, TEXT("+"), x1, y1); }
/** * @brief Solves FAI triangle based contest * * @param trace The trace to use * @param prevFront Loop front point of previous iteration * @param prevBack Loop back point of previous iteration */ void CContestMgr::SolveTriangle(const CTrace &trace, const CPointGPS *prevFront, const CPointGPS *prevBack) { CResult &result = _resultArray[TYPE_OLC_FAI]; if(trace.Size() > 2) { // check for every trace point const CTrace::CPoint *point1st = trace.Front(); while(point1st) { // check if all edges should be analysed bool skip1 = prevFront && prevBack; if(skip1 && (point1st->GPS() < *prevFront || point1st->GPS() > *prevBack)) skip1 = false; // create a map of points that may form first edge of a better triangle CDistanceMap distanceMap1st; const CTrace::CPoint *next = 0; for(next=point1st->Next(); next; next=next->Next()) { unsigned dist = point1st->GPS().Distance(next->GPS()); // check if 1st edge not too short if(!FAITriangleEdgeCheck(dist, result.Distance())) continue; distanceMap1st.insert(std::make_pair(dist, next)); } // check all possible first edges of the triangle for(CDistanceMap::reverse_iterator it1st=distanceMap1st.rbegin(); it1st!=distanceMap1st.rend(); ++it1st) { bool skip2 = skip1; if(skip2 && (it1st->second->GPS() < *prevFront || it1st->second->GPS() > *prevBack)) skip2 = false; unsigned dist1st = it1st->first; if(!FAITriangleEdgeCheck(dist1st, result.Distance())) // better solution found in the meantime break; // create a map of points that may form second edge of a better triangle CDistanceMap distanceMap2nd; const CTrace::CPoint *point2nd = it1st->second; for(next=point2nd->Next(); next; next=next->Next()) { bool skip3 = skip2; if(skip3 && (next->GPS() < *prevFront || next->GPS() > *prevBack)) skip3 = false; if(skip3) // that triangle was analysed already continue; unsigned dist = point2nd->GPS().Distance(next->GPS()); // check if 2nd edge not too long if(dist * 14 > dist1st * 20) // 45% > 25% continue; // check if 2nd edge not too short if(!FAITriangleEdgeCheck(dist, result.Distance())) continue; distanceMap2nd.insert(std::make_pair(dist, next)); } // check all possible second and third edges of the triangle for(CDistanceMap::reverse_iterator it2nd=distanceMap2nd.rbegin(); it2nd!=distanceMap2nd.rend(); ++it2nd) { unsigned dist2nd = it2nd->first; if(!FAITriangleEdgeCheck(dist2nd, result.Distance())) // better solution found in the meantime break; const CTrace::CPoint *point3rd = it2nd->second; unsigned dist3rd = point3rd->GPS().Distance(point1st->GPS()); unsigned distance = dist1st + dist2nd + dist3rd; if(distance > result.Distance()) { // check if valid FAI triangle if(FAITriangleEdgeCheck(dist1st, dist2nd, dist3rd)) { // store new result float score = distance / 1000.0 * 0.3 * 100 / _handicap; CPointGPSArray pointArray; pointArray.push_back(trace.Front()->GPS()); pointArray.push_back(point1st->GPS()); pointArray.push_back(point2nd->GPS()); pointArray.push_back(point3rd->GPS()); pointArray.push_back(trace.Back()->GPS()); _resultArray[TYPE_OLC_FAI] = CResult(TYPE_OLC_FAI, distance, score, pointArray); } } } } point1st = point1st->Next(); } } }
/***************************************************************** * Alpha Lima splitted RenderContest from Render Task for CC * adding FAI Sector display ****************************************************************/ void Statistics::RenderFAIOptimizer(LKSurface& Surface, const RECT& rc) { unsigned int ui; double fXY_Scale = 1.0; double lat0 = 0; double lon0 = 0; double lat1 = 0; double lon1 = 0; double lat2 = 0; double lon2 = 0; double x0, y0, x1, y1, x2=0, y2=0; double lat_c, lon_c; double lat_p = GPS_INFO.Latitude; double lon_p = GPS_INFO.Longitude; BOOL bFlat = false; #define DRAWPERCENT #ifdef DRAWPERCENT double fTotalPercent = 1.0; #endif ResetScale(); CContestMgr::CResult result = CContestMgr::Instance().Result(contestType, true); const CPointGPSArray &points = result.PointArray(); if(contestType == CContestMgr::TYPE_FAI_TRIANGLE) fXY_Scale = 1.5; // find center double fTotalDistance = result.Distance(); if (fTotalDistance < 1) fTotalDistance =1; CPointGPSArray trace; CContestMgr::Instance().Trace(trace); for(ui=0; ui<trace.size(); ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); ScaleYFromValue(rc, lat1); ScaleXFromValue(rc, lon1); } const auto hfOldU = Surface.SelectObject(LK8PanelUnitFont); BOOL bFAITri = CContestMgr::Instance().FAI(); double fDist, fAngle; lat_c = (y_max+y_min)/2; lon_c = (x_max+x_min)/2; double xp = (lon_p-lon_c)*fastcosine(lat_p); double yp = (lat_p-lat_c); // find scale ResetScale(); lat1 = GPS_INFO.Latitude; lon1 = GPS_INFO.Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); for(ui=0; ui<trace.size(); ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); } ScaleMakeSquare(rc); if(result.Type() == contestType) { for(ui=0; ui<points.size()-1; ui++) { lat1 = points[ui].Latitude(); lon1 = points[ui].Longitude(); lat2 = points[ui+1].Latitude(); lon2 = points[ui+1].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DistanceBearing(lat1, lon1, lat2, lon2, &fDist, &fAngle); if( (ui <points.size()-2) && !bFlat && ((fDist / fTotalDistance ) > 0.05) ) { if(fDist > 5000) { #ifndef UNDITHER LKColor rgbCol = RGB_BLUE; switch(ui) { case 0: rgbCol = RGB_LIGHTYELLOW; break; case 1: rgbCol = RGB_LIGHTCYAN ; break; case 2: rgbCol = RGB_LIGHTGREEN ; break; default: break; } #else LKColor rgbCol = RGB_DARKBLUE; switch(ui) { case 0: rgbCol = RGB_LIGHTGREY; break; case 1: rgbCol = RGB_GREY ; break; case 2: rgbCol = RGB_MIDDLEGREY ; break; default: break; } #endif RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, rgbCol ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, rgbCol ); } } if((fDist / fTotalDistance ) > 0.45) /* prevent drawing almost same sectors */ bFlat = true; } // draw track for(ui=0; trace.size() && ui<trace.size()-1; ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); lat2 = trace[ui+1].Latitude(); lon2 = trace[ui+1].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_MEDIUMBLACK); } for(ui=0; ui<points.size()-1; ui++) { lat1 = points[ui].Latitude(); lon1 = points[ui].Longitude(); lat2 = points[ui+1].Latitude(); lon2 = points[ui+1].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); int style = STYLE_REDTHICK; if((ui > 0) && (ui < 3)) { style = STYLE_BLUETHIN; DistanceBearing(lat1, lon1, lat2, lon2, &fDist, &fAngle); #ifdef DRAWPERCENT if((result.Distance()> 5000) && bFAITri) { TCHAR text[180]; SIZE tsize; fTotalPercent -= fDist/result.Distance(); _stprintf(text, TEXT("%3.1f%%"), (fDist/result.Distance()*100.0)); Surface.GetTextSize(text, _tcslen(text), &tsize); #ifndef UNDITHER Surface.SetTextColor(RGB_BLUE); #else Surface.SetTextColor(RGB_BLACK); #endif Surface.DrawText(ScaleX(rc, x1 +( x2-x1)/2)-tsize.cx/2, ScaleY(rc,y1 + (y2-y1)/2), text, _tcslen(text)); } #endif DrawLine(Surface, rc, x1, y1, x2, y2, style); } } if(bFAITri) { if(points.size() >3) { if(ISPARAGLIDER) { lat0 = CContestMgr::Instance().GetBestNearClosingPoint().Latitude(); lon0 = CContestMgr::Instance().GetBestNearClosingPoint().Longitude(); lat1 = CContestMgr::Instance().GetBestClosingPoint().Latitude(); lon1 = CContestMgr::Instance().GetBestClosingPoint().Longitude(); x1 = (lon0-lon_c)*fastcosine(lat0); y1 = (lat0-lat_c); x2 = (lon1-lon_c)*fastcosine(lat1); y2 = (lat1-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_ORANGETHIN ); //result.Predicted() ? STYLE_BLUETHIN : STYLE_REDTHICK); } lat1 = points[1].Latitude(); lon1 = points[1].Longitude(); lat2 = points[3].Latitude(); lon2 = points[3].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_THINDASHPAPER ); //result.Predicted() ? STYLE_BLUETHIN : STYLE_REDTHICK); #ifdef DRAWPERCENT TCHAR text[180]; SIZE tsize; _stprintf(text, TEXT("%3.1f%%"), (fTotalPercent*100.0)); Surface.GetTextSize(text, _tcslen(text), &tsize); #ifndef UNDITHER Surface.SetTextColor(RGB_LIGHTBLUE); #else Surface.SetTextColor(RGB_RED); #endif Surface.DrawText(ScaleX(rc, x1 +( x2-x1)/2)-tsize.cx/2, ScaleY(rc,y1 + (y2-y1)/2), text, _tcslen(text)); #endif lat0 = CContestMgr::Instance().GetClosingPoint().Latitude(); lon0 = CContestMgr::Instance().GetClosingPoint().Longitude(); x0 = (lon0-lon_c)*fastcosine(lat0); y0 = (lat0-lat_c); DrawLine(Surface, rc, xp, yp, x0, y0, STYLE_REDTHICK); } } } DrawXGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); DrawYGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); Surface.SetBackgroundTransparent(); #ifndef UNDITHER Surface.SetTextColor(RGB_MAGENTA); #else Surface.SetTextColor(RGB_BLACK); #endif DrawLabel(Surface, rc, TEXT("O"), xp, yp); Surface.SelectObject(hfOldU); }
/***************************************************************** * Alpha Lima splitted RenderContest from Render Task for CC * adding FAI Sector display ****************************************************************/ void Statistics::RenderContest(LKSurface& Surface, const RECT& rc) { if(contestType == CContestMgr::TYPE_FAI_TRIANGLE) RenderFAIOptimizer(Surface, rc); else { unsigned int ui; double fXY_Scale = 1.0; double lat1 = 0; double lon1 = 0; double lat2 = 0; double lon2 = 0; double x1, y1, x2=0, y2=0; double lat_c, lon_c; ResetScale(); CContestMgr::CResult result = CContestMgr::Instance().Result(contestType, true); const CPointGPSArray &points = result.PointArray(); // find center CPointGPSArray trace; CContestMgr::Instance().Trace(trace); for(ui=0; ui<trace.size(); ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); ScaleYFromValue(rc, lat1); ScaleXFromValue(rc, lon1); } const auto hfOldU = Surface.SelectObject(LK8PanelUnitFont); lat_c = (y_max+y_min)/2; lon_c = (x_max+x_min)/2; // find scale ResetScale(); lat1 = GPS_INFO.Latitude; lon1 = GPS_INFO.Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); for(ui=0; ui<trace.size(); ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); } ScaleMakeSquare(rc); // draw track for(ui=0; trace.size() && ui<trace.size()-1; ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); lat2 = trace[ui+1].Latitude(); lon2 = trace[ui+1].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_MEDIUMBLACK); } // Draw aircraft on top double lat_p = GPS_INFO.Latitude; double lon_p = GPS_INFO.Longitude; double xp = (lon_p-lon_c)*fastcosine(lat_p); double yp = (lat_p-lat_c); if(result.Type() == contestType) { for(ui=0; ui<points.size()-1; ui++) { lat1 = points[ui].Latitude(); lon1 = points[ui].Longitude(); lat2 = points[ui+1].Latitude(); lon2 = points[ui+1].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); int style = STYLE_REDTHICK; if((result.Type() == CContestMgr::TYPE_OLC_FAI || result.Type() == CContestMgr::TYPE_OLC_FAI_PREDICTED) && (ui==0 || ui==3)) { // triangle start and finish style = STYLE_DASHGREEN; } else if(result.Predicted() && (result.Type() == CContestMgr::TYPE_OLC_FAI_PREDICTED || ui == points.size() - 2)) { // predicted edge style = STYLE_BLUETHIN; } if((result.Type() == CContestMgr::TYPE_FAI_3_TPS) ||// TYPE_FAI_3_TPS_PREDICTED (result.Type() == CContestMgr::TYPE_FAI_3_TPS_PREDICTED) ) { } if((contestType != CContestMgr::TYPE_FAI_TRIANGLE) ) DrawLine(Surface, rc, x1, y1, x2, y2, style); } if(result.Type() == CContestMgr::TYPE_OLC_FAI || result.Type() == CContestMgr::TYPE_OLC_FAI_PREDICTED) { // draw the last edge of a triangle lat1 = points[1].Latitude(); lon1 = points[1].Longitude(); lat2 = points[3].Latitude(); lon2 = points[3].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, result.Predicted() ? STYLE_BLUETHIN : STYLE_REDTHICK); } DrawXGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); DrawYGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); Surface.SelectObject(hfOldU); #ifndef UNDITHER Surface.SetTextColor(RGB_MAGENTA); #else Surface.SetTextColor(RGB_BLACK); #endif Surface.SetBackgroundTransparent(); DrawLabel(Surface, rc, TEXT("O"), xp, yp); } } }