void Statistics::RenderClimb(HDC hdc, RECT rc) { ResetScale(); ScaleYFromData(rc, &flightstats.ThermalAverage); ScaleYFromValue(rc, MACCREADY); ScaleYFromValue(rc, 0); ScaleXFromValue(rc, 0); ScaleXFromValue(rc, flightstats.ThermalAverage.sum_n+1); DrawYGrid(hdc, rc, 1.0/LIFTMODIFY, 0, STYLE_THINDASHPAPER); DrawBarChart(hdc, rc, &flightstats.ThermalAverage); DrawLine(hdc, rc, 0, MACCREADY, flightstats.ThermalAverage.sum_n+1, MACCREADY, STYLE_REDTHICK); DrawTrendN(hdc, rc, &flightstats.ThermalAverage, STYLE_BLUETHIN); DrawXLabel(hdc, rc, TEXT("n")); DrawYLabel(hdc, rc, TEXT("w")); }
void Statistics::RenderGlidePolar(HDC hdc, RECT rc) { ResetScale(); ScaleYFromValue(rc, 0); ScaleYFromValue(rc, GlidePolar::SinkRateFast(0,(int)(SAFTEYSPEED-1))); ScaleXFromValue(rc, 0); // GlidePolar::Vminsink); ScaleXFromValue(rc, SAFTEYSPEED); DrawXGrid(hdc, rc, 10.0/SPEEDMODIFY, 0, STYLE_THINDASHPAPER); DrawYGrid(hdc, rc, 1.0/LIFTMODIFY, 0, STYLE_THINDASHPAPER); int i; double sinkrate0, sinkrate1; for (i= GlidePolar::Vminsink; i< SAFTEYSPEED-1; i++) { sinkrate0 = GlidePolar::SinkRateFast(0,i); sinkrate1 = GlidePolar::SinkRateFast(0,i+1); DrawLine(hdc, rc, i, sinkrate0 , i+1, sinkrate1, STYLE_MEDIUMBLACK); } DrawXLabel(hdc, rc, TEXT("V")); DrawYLabel(hdc, rc, TEXT("w")); }
void qp_graph_grid_draw(struct qp_graph *gr, struct qp_plot *p, cairo_t *cr, int width, int height) { int64_t xmin_mat, xmax_mat, xinc, ymin_mat, ymax_mat, yinc; double xpow_part, ypow_part; PangoLayout *pangolayout = NULL; int view_width, view_height; ASSERT(gr); ASSERT(p); ASSERT(gr->drawing_area); ASSERT(gr->qp); ASSERT(gr->qp->window); if(!gr->show_grid) return; PreDrawGrid(gr, p, &xmin_mat, &xmax_mat, &xinc, &xpow_part, &ymin_mat, &ymax_mat, &yinc, &ypow_part, width, height); view_width = gtk_widget_get_allocated_width(gr->drawing_area); view_height = gtk_widget_get_allocated_height(gr->drawing_area); if(gr->grid_numbers) pangolayout = get_pangolayout(gr, cr); #if 0 DEBUG("\nxmin=%g xmax=%g\n", qp_plot_get_xval(p, 0), qp_plot_get_xval(p, width)); APPEND("ymin=%g ymax=%g\n", qp_plot_get_yval(p, height), qp_plot_get_yval(p, 0)); APPEND("xmin_mat=%ld xmax_mat=%ld xinc=%ld xpow_part=%g \n", xmin_mat, xmax_mat, xinc, xpow_part); APPEND("ymin_mat=%ld ymax_mat=%ld yinc=%ld ypow_part=%g \n", ymin_mat, ymax_mat, yinc, ypow_part); APPEND("delta_x pixels between lines=%d\n", qp_plot_get_xpixel(p, xpow_part*(xmin_mat + xinc)) - qp_plot_get_xpixel(p, xpow_part*(xmin_mat))); APPEND("delta_y pixels between lines=%d\n", qp_plot_get_ypixel(p, ypow_part*ymin_mat) - qp_plot_get_ypixel(p, ypow_part*(ymin_mat + yinc))); #endif if(gr->same_x_scale) DrawXGrid(cr, pangolayout, gr, p, xmin_mat, xmax_mat, xinc, xpow_part, ymin_mat, ymax_mat, yinc, ypow_part, width, height, view_height); if(gr->same_y_scale) DrawYGrid(cr, pangolayout, gr, p, xmin_mat, xmax_mat, xinc, xpow_part, ymin_mat, ymax_mat, yinc, ypow_part, width, height, view_width); }
void Statistics::RenderBarograph(HDC hdc, RECT rc) { ResetScale(); ScaleXFromData(rc, &flightstats.Altitude); ScaleYFromData(rc, &flightstats.Altitude); ScaleXFromData(rc, &flightstats.Altitude_Base); ScaleYFromData(rc, &flightstats.Altitude_Base); ScaleXFromData(rc, &flightstats.Altitude_Ceiling); ScaleYFromData(rc, &flightstats.Altitude_Ceiling); DrawXGrid(hdc, rc, 0.25, flightstats.Altitude.x_min, STYLE_THINDASHPAPER); DrawYGrid(hdc, rc, 1000/ALTITUDEMODIFY, 0, STYLE_THINDASHPAPER); DrawLineGraph(hdc, rc, &flightstats.Altitude, STYLE_MEDIUMBLACK); LockTaskData(); for(int j=0;j<MAXTASKPOINTS;j++) { if (ValidTaskPoint(j) && (LegStartTime[j]>=0)) { double xx = (LegStartTime[j]-Calculated->TakeOffTime)/3600; if (xx>=0) { DrawLine(hdc, rc, xx, flightstats.Altitude.y_min, xx, flightstats.Altitude.y_max, STYLE_THINDASHPAPER); } } } UnlockTaskData(); DrawTrend(hdc, rc, &flightstats.Altitude_Base, STYLE_BLUETHIN); DrawTrend(hdc, rc, &flightstats.Altitude_Ceiling, STYLE_BLUETHIN); DrawXLabel(hdc, rc, TEXT("t")); DrawYLabel(hdc, rc, TEXT("h")); }
/*--------------------------------------------------------------------------*/ void PegChart::Draw() { BeginDraw(); StandardBorder(muColors[PCI_NORMAL]); if(mwExStyle & CS_DRAWXGRID && (mwMajorXScale > 0 || mwMinorXScale > 0)) { DrawXGrid(); } if(mwExStyle & CS_DRAWYGRID && (mwMajorYScale > 0 || mwMinorYScale > 0)) { DrawYGrid(); } if(mwExStyle & CS_DRAWXTICS && (mwMajorXScale > 0 || mwMinorXScale > 0)) { DrawXTics(); } if(mwExStyle & CS_DRAWYTICS && (mwMajorYScale > 0 || mwMinorYScale > 0)) { DrawYTics(); } if(mwExStyle & CS_DRAWXLABELS && mwXLabelScale > 0) { DrawXLabels(); } if(mwExStyle & CS_DRAWYLABELS && mwYLabelScale > 0) { DrawYLabels(); } DrawChildren(); EndDraw(); }
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); }
void Statistics::RenderWind(HDC hdc, RECT rc) { int numsteps=10; int i; double h; Vector wind; bool found=true; double mag; LeastSquares windstats_mag; if (fabs(flightstats.Altitude_Ceiling.y_max -flightstats.Altitude_Base.y_min)<1) return; for (i=0; i<numsteps ; i++) { h = (flightstats.Altitude_Ceiling.y_max-flightstats.Altitude_Base.y_min)* i/(double)(numsteps-1)+flightstats.Altitude_Base.y_min; wind = windanalyser->windstore.getWind(h, &found); mag = sqrt(wind.x*wind.x+wind.y*wind.y); windstats_mag.least_squares_update(mag, h); } // ResetScale(); ScaleXFromValue(rc, 0); ScaleXFromData(rc, &windstats_mag); ScaleYFromData(rc, &windstats_mag); DrawYGrid(hdc, rc, 1000/ALTITUDEMODIFY, 0, STYLE_THINDASHPAPER); DrawXGrid(hdc, rc, 5/LIFTMODIFY, 0, STYLE_THINDASHPAPER); DrawLineGraph(hdc, rc, &windstats_mag, STYLE_MEDIUMBLACK); #define WINDVECTORMAG 25 numsteps = (int)((rc.bottom-rc.top)/WINDVECTORMAG)-1; // draw direction vectors POINT wv[4]; double dX, dY; double angle; double hfact; for (i=0; i<numsteps ; i++) { hfact = (i+1)/(double)(numsteps+1); h = (flightstats.Altitude_Ceiling.y_max-flightstats.Altitude_Base.y_min)* hfact+flightstats.Altitude_Base.y_min; wind = windanalyser->windstore.getWind(h, &found); if (windstats_mag.x_max == 0) windstats_mag.x_max=1; // prevent /0 problems wind.x /= windstats_mag.x_max; wind.y /= windstats_mag.x_max; mag = sqrt(wind.x*wind.x+wind.y*wind.y); if (mag<= 0.0) continue; angle = atan2(wind.x,-wind.y)*RAD_TO_DEG; wv[0].y = (int)((1-hfact)*(rc.bottom-rc.top))+rc.top; wv[0].x = (rc.right+rc.left)/2; dX = (mag*WINDVECTORMAG); dY = 0; rotate(dX,dY,angle); wv[1].x = (int)(wv[0].x + dX); wv[1].y = (int)(wv[0].y + dY); StyleLine(hdc, wv[0], wv[1], STYLE_MEDIUMBLACK); dX = (mag*WINDVECTORMAG-5); dY = -3; rotate(dX,dY,angle); wv[2].x = (int)(wv[0].x + dX); wv[2].y = (int)(wv[0].y + dY); StyleLine(hdc, wv[1], wv[2], STYLE_MEDIUMBLACK); dX = (mag*WINDVECTORMAG-5); dY = 3; rotate(dX,dY,angle); wv[3].x = (int)(wv[0].x + dX); wv[3].y = (int)(wv[0].y + dY); StyleLine(hdc, wv[1], wv[3], STYLE_MEDIUMBLACK); } DrawXLabel(hdc, rc, TEXT("w")); DrawYLabel(hdc, rc, TEXT("h")); }
void Statistics::RenderSpeed(LKSurface& Surface, const RECT& rc) { if ((flightstats.Task_Speed.sum_n<2) || !ValidTaskPoint(ActiveTaskPoint)) { DrawNoData(Surface, rc); return; } ResetScale(); ScaleXFromData(rc, &flightstats.Task_Speed); ScaleYFromData(rc, &flightstats.Task_Speed); ScaleYFromValue(rc, 0); ScaleXFromValue(rc, flightstats.Task_Speed.x_min+1.0); // in case no data ScaleXFromValue(rc, flightstats.Task_Speed.x_min); for(int j=1;j<MAXTASKPOINTS;j++) { if (ValidTaskPoint(j) && (flightstats.LegStartTime[j]>=0)) { double xx = (flightstats.LegStartTime[j]-CALCULATED_INFO.TaskStartTime)/3600.0; if (xx>=0) { DrawLine(Surface, rc, xx, y_min, xx, y_max, STYLE_REDTHICK); } } } DrawXGrid(Surface, rc, 0.5, flightstats.Task_Speed.x_min, STYLE_THINDASHPAPER, 0.5, true); /* DrawYGrid(hdc, rc, 10/TASKSPEEDMODIFY, 0, STYLE_THINDASHPAPER, 10, true);*/ if(Units::GetUserHorizontalSpeedUnit() == unStatuteMilesPerHour) { DrawYGrid(Surface, rc, 5.0/TASKSPEEDMODIFY, 0, STYLE_THINDASHPAPER, 5.0, true); } else { DrawYGrid(Surface, rc, 10/TASKSPEEDMODIFY, 0, STYLE_THINDASHPAPER, 10, true); } DrawLineGraph(Surface, rc, &flightstats.Task_Speed,STYLE_MEDIUMBLACK); DrawTrend(Surface, rc, &flightstats.Task_Speed, STYLE_BLUETHIN); if(INVERTCOLORS || IsDithered()) Surface.SetTextColor(RGB_DARKGREEN); else Surface.SetTextColor(RGB_GREEN); Surface.SetBackgroundOpaque(); TCHAR text[80]; DrawXLabel(Surface, rc, TEXT(" t/h ")); _stprintf(text,TEXT(" v/%s "),Units::GetHorizontalSpeedName()); DrawYLabel(Surface, rc, text); // DrawXLabel(hdc, rc, TEXT("t")); // DrawYLabel(hdc, rc, TEXT("V")); }
void ChartRenderer::DrawYGrid(const double tic_step, ChartLook::Style style, const double unit_step, bool draw_units) { DrawYGrid(tic_step, look.GetPen(style), unit_step, draw_units); }
void PD_2DXYPS::DrawPlotAxes() { if (!plotAnnotation.DoAnno()) { SetClipPlanes(); return; } SetIncrFont(); ClearClipPlanes(); SetAxesLocals(); SetLineSolid(); xAxis.SetMajorIncs(); xAxis.SetMinorIncs(); yAxis.SetMajorIncs(); yAxis.SetMinorIncs(); SC_DoubleArray xMajorIncs, xMinorIncs, yMajorIncs, yMinorIncs; xAxis.GetAxesMajorIncs(xMajorIncs); xAxis.GetAxesMinorIncs(xMinorIncs); yAxis.GetAxesMajorIncs(yMajorIncs); yAxis.GetAxesMinorIncs(yMinorIncs); Point2D axesOffComp, labelOffComp; bool dummy; GetAxesOffsets(axesOffComp, labelOffComp, dummy); Point2D majorTicLength = GetPixelComponents(plotAnnotation.majorTicLength); Point2D minorTicLength = GetPixelComponents(plotAnnotation.minorTicLength); Point2D majorTicOffset = GetPixelComponents(plotAnnotation.majorTicOffset); Point2D minorTicOffset = GetPixelComponents(plotAnnotation.minorTicOffset); // set Z val SetAnnoLow(); if (plotAnnotation.drawAxesLines) { AxesDrawSetup(); HardCopyBlockStart(24); // 4 axes + 2 caps per axes * 2 // x axis if (plotAnnotation.DoXAxis()) { DrawXAxes(convYaxisMin, -axesOffComp.pY); if (plotAnnotation.framePlot) DrawXAxes(convYaxisMax, axesOffComp.pY); } // y axis if (plotAnnotation.DoYAxis()) { DrawYAxes(convXaxisMin, -axesOffComp.pX); if (plotAnnotation.framePlot) DrawYAxes(convXaxisMax, axesOffComp.pX); } if (plotAnnotation.axesOffset > 0) { // slight kluge -- tic routines require untransformed X&Ys double xmin, xmax, ymin, ymax; xAxis.GetAxisLimits(xmin, xmax); yAxis.GetAxisLimits(ymin, ymax); // draw caps on axes if (plotAnnotation.DoXAxis()) { DrawXTic(xmin, convYaxisMin, -axesOffComp.pY, axesOffComp.pY, 0.0); DrawXTic(xmax, convYaxisMin, -axesOffComp.pY, axesOffComp.pY, 0.0); if (plotAnnotation.framePlot) { DrawXTic(xmin, convYaxisMax, axesOffComp.pY, -axesOffComp.pY, 0.0); DrawXTic(xmax, convYaxisMax, axesOffComp.pY, -axesOffComp.pY, 0.0); } } if (plotAnnotation.DoYAxis()) { DrawYTic(convXaxisMin, ymin, -axesOffComp.pX, axesOffComp.pX, 0.0); DrawYTic(convXaxisMin, ymax, -axesOffComp.pX, axesOffComp.pX, 0.0); if (plotAnnotation.framePlot) { DrawYTic(convXaxisMax, ymin, axesOffComp.pX, -axesOffComp.pX, 0.0); DrawYTic(convXaxisMax, ymax, axesOffComp.pX, -axesOffComp.pX, 0.0); } } } HardCopyBlockEnd(); SetAnnoLow(); } double axmaxOffset = 0.0; if (plotAnnotation.DoXAxis() && (xAxis.axisMajorIncs != PC_Axes::aitNone)) if (xAxis.axisMajorIncs == PC_Axes::aitGrid) { MajorGridDrawSetup(); HardCopyBlockStart(xMajorIncs.Size() * 2); if (plotAnnotation.framePlot) axmaxOffset = axesOffComp.pY; for (int i = 0; i < xMajorIncs.Size(); i++) DrawXGrid(xMajorIncs[i], -axesOffComp.pY, axmaxOffset, majorTicOffset.pY); HardCopyBlockEnd(); SetAnnoLow(); } else { MajorTicDrawSetup(); HardCopyBlockStart(xMajorIncs.Size() * 4); int i; for (i = 0; i < xMajorIncs.Size(); i++) { DrawXTic(xMajorIncs[i], convYaxisMin, -axesOffComp.pY, majorTicLength.pY, majorTicOffset.pY); if (plotAnnotation.framePlot) DrawXTic(xMajorIncs[i], convYaxisMax, axesOffComp.pY, -majorTicLength.pY, -majorTicOffset.pY); } HardCopyBlockEnd(); } if (plotAnnotation.DoYAxis() && (yAxis.axisMajorIncs != PC_Axes::aitNone)) if (yAxis.axisMajorIncs == PC_Axes::aitGrid) { MajorGridDrawSetup(); if (plotAnnotation.framePlot) axmaxOffset = axesOffComp.pX; HardCopyBlockStart(yMajorIncs.Size() * 2); for (int i = 0; i < yMajorIncs.Size(); i++) { DrawYGrid(yMajorIncs[i], -axesOffComp.pX, axmaxOffset, majorTicOffset.pX); } HardCopyBlockEnd(); SetAnnoLow(); } else { MajorTicDrawSetup(); HardCopyBlockStart(yMajorIncs.Size() * 4); for (int i = 0; i < yMajorIncs.Size(); i++) { DrawYTic(convXaxisMin, yMajorIncs[i], -axesOffComp.pX, majorTicLength.pX, majorTicOffset.pX); if (plotAnnotation.framePlot) DrawYTic(convXaxisMax, yMajorIncs[i], axesOffComp.pX, -majorTicLength.pX, -majorTicOffset.pX); } HardCopyBlockEnd(); } if (plotAnnotation.DoXAxis() && (xAxis.axisMinorIncs != PC_Axes::aitNone)) if (xAxis.axisMinorIncs == PC_Axes::aitGrid) { MinorGridDrawSetup(); if (plotAnnotation.framePlot) axmaxOffset = axesOffComp.pY; HardCopyBlockStart((xMajorIncs.Size() + 1) * xMinorIncs.Size() * 2); for (int i = -1; i < xMajorIncs.Size(); i++) for (int j = 0; j < xMinorIncs.Size(); j++) DrawXGrid(GetMinorIncVal(xMajorIncs, xMinorIncs, i, j, doLogX, convXaxisMax < convXaxisMin), -axesOffComp.pY, axmaxOffset, minorTicOffset.pX); HardCopyBlockEnd(); SetAnnoLow(); } else { MinorTicDrawSetup(); HardCopyBlockStart((xMajorIncs.Size() + 1) * xMinorIncs.Size() * 4); for (int i = -1; i < xMajorIncs.Size(); i++) for (int j = 0; j < xMinorIncs.Size(); j++) { double incVal = GetMinorIncVal(xMajorIncs, xMinorIncs, i, j, doLogX, convXaxisMax < convXaxisMin); DrawXTic(incVal, convYaxisMin, -axesOffComp.pY, minorTicLength.pY, minorTicOffset.pY); if (plotAnnotation.framePlot) DrawXTic(incVal, convYaxisMax, axesOffComp.pY, -minorTicLength.pY, -minorTicOffset.pY); } HardCopyBlockEnd(); } if (plotAnnotation.DoYAxis() && (yAxis.axisMinorIncs != PC_Axes::aitNone)) if (yAxis.axisMinorIncs == PC_Axes::aitGrid) { MinorGridDrawSetup(); if (plotAnnotation.framePlot) axmaxOffset = axesOffComp.pX; HardCopyBlockStart((yMajorIncs.Size() + 1) * yMinorIncs.Size() * 2); for (int i = -1; i < yMajorIncs.Size(); i++) for (int j = 0; j < yMinorIncs.Size(); j++) DrawYGrid(GetMinorIncVal(yMajorIncs, yMinorIncs, i, j, doLogY, convYaxisMax < convYaxisMin), -axesOffComp.pX, axmaxOffset, minorTicOffset.pX); HardCopyBlockEnd(); SetAnnoLow(); } else { MinorTicDrawSetup(); HardCopyBlockStart((yMajorIncs.Size() + 1) * yMinorIncs.Size() * 4); for (int i = -1; i < yMajorIncs.Size(); i++) for (int j = 0; j < yMinorIncs.Size(); j++) { double incVal = GetMinorIncVal(yMajorIncs, yMinorIncs, i, j, doLogY, convYaxisMax < convYaxisMin); DrawYTic(convXaxisMin, incVal, -axesOffComp.pX, minorTicLength.pX, minorTicOffset.pX); if (plotAnnotation.framePlot) DrawYTic(convXaxisMax, incVal, axesOffComp.pX, -minorTicLength.pX, -minorTicOffset.pX); } HardCopyBlockEnd(); } double maxHeight = 0.0; double xaxYpos = convYaxisMin - axesOffComp.pY - labelOffComp.pY - majorTicOffset.pY; double maxWidth = 0.0; double yaxXpos = convXaxisMin - axesOffComp.pX - labelOffComp.pX - majorTicOffset.pX; if (plotAnnotation.labelIncrements) { SetDrawColor(defaultPenSet->GetColor(plotAnnotation.axesDataPen)); char labStr[80]; ExtendedLabelData labInfo; if (plotAnnotation.DoXAxis()) { // need to go through all labels once to calc over top on exponents if horiz double exponentShift = 0.0; for (int i = 0; i < xMajorIncs.Size(); i++) { double xTran = TransformX(xMajorIncs[i]); if (Limit::WithinOneLimit(convXaxisMin, convXaxisMax, xTran)) { xAxis.axisIncFormat.RealToString(xMajorIncs[i], labStr, 80); if (xAxis.incrFont.fontRotation == PSC_Font::fr_Horiz) { if (GetExtendedStringSizeInfo(xAxis.incrFont, labStr, labInfo)) { if (labInfo.aboveTop > exponentShift) exponentShift = labInfo.aboveTop; double totHeight = labInfo.height + labInfo.aboveTop; if ((fabs(totHeight) > fabs(maxHeight))) maxHeight = totHeight; } } else { double w, h; if (GetStringSizeInfo(xAxis.incrFont, labStr, w, h)) { if (fabs(w) > fabs(maxHeight)) maxHeight = w; } } } } //set alignment for printing HorizontalTextAlignment halign; VerticalTextAlignment valign; if (xAxis.incrFont.fontRotation == PSC_Font::fr_Horiz) { halign = hta_Center; valign = vta_Top; } else { valign = vta_Center; if (xAxis.incrFont.fontRotation == PSC_Font::fr_VertLeft) halign = hta_Right; else halign = hta_Left; } // now print label double xincLabYPos = xaxYpos - exponentShift; for (int i = 0; i < xMajorIncs.Size(); i++) { double xTran = TransformX(xMajorIncs[i]); if (Limit::WithinOneLimit(convXaxisMin, convXaxisMax, xTran)) { xAxis.axisIncFormat.RealToString(xMajorIncs[i], labStr, 80); PrintString(xAxis.incrFont, labStr, halign, valign, xTran, xincLabYPos); } } } if (plotAnnotation.DoYAxis()) { // need to go through all labels once to calc over top on exponents if not horiz double exponentShift = 0.0; for (int i = 0; i < yMajorIncs.Size(); i++) { double yTran = TransformY(yMajorIncs[i]); if (Limit::WithinOneLimit(convYaxisMin, convYaxisMax, yTran)) { yAxis.axisIncFormat.RealToString(yMajorIncs[i], labStr, 80); if (yAxis.incrFont.fontRotation != PSC_Font::fr_Horiz) { if (GetExtendedStringSizeInfo(yAxis.incrFont, labStr, labInfo)) { if (labInfo.aboveTop > exponentShift) exponentShift = labInfo.aboveTop; double totHeight = labInfo.height + labInfo.aboveTop; if ((fabs(totHeight) > fabs(maxWidth))) maxWidth = totHeight; } } else { double w, h; if ((GetStringSizeInfo(yAxis.incrFont, labStr, w, h)) && (fabs(w) > fabs(maxWidth))) maxWidth = w; } } } //set alignment for printing HorizontalTextAlignment halign; VerticalTextAlignment valign; if (yAxis.incrFont.fontRotation == PSC_Font::fr_Horiz) { halign = hta_Right; valign = vta_Center; } else { halign = hta_Center; if (yAxis.incrFont.fontRotation == PSC_Font::fr_VertLeft) valign = vta_Bottom; else valign = vta_Top; } for (int i = 0; i < yMajorIncs.Size(); i++) { double yTran = TransformY(yMajorIncs[i]); if (Limit::WithinOneLimit(convYaxisMin, convYaxisMax, yTran)) { yAxis.axisIncFormat.RealToString(yMajorIncs[i], labStr, 80); PrintString(yAxis.incrFont, labStr, halign, valign, yaxXpos, yTran); } } } } plotAnnotation.xaxesLabelPos.pX = (convXaxisMin + convXaxisMax) / 2.0; plotAnnotation.xaxesLabelPos.pY = xaxYpos - maxHeight - labelOffComp.pY; plotAnnotation.yaxesLabelPos.pX = yaxXpos - maxWidth - labelOffComp.pX * 2.0; plotAnnotation.yaxesLabelPos.pY = (convYaxisMin + convYaxisMax) / 2.0; if (plotAnnotation.labelAxes) { if (plotAnnotation.DoXAxis() && IsNotNull(plotAnnotation.xaxesLabel)) { PrintString(plotAnnotation.labelFont, plotAnnotation.xaxesLabel, hta_Center, vta_Top, plotAnnotation.xaxesLabelPos.pX, plotAnnotation.xaxesLabelPos.pY); } if (plotAnnotation.DoYAxis() && IsNotNull(plotAnnotation.yaxesLabel)) { PSC_Font yLabFont(plotAnnotation.labelFont); yLabFont.fontRotation = PSC_Font::fr_VertLeft; PrintString(yLabFont, plotAnnotation.yaxesLabel, hta_Center, vta_Bottom, plotAnnotation.yaxesLabelPos.pX, plotAnnotation.yaxesLabelPos.pY); } } SetClipPlanes(); }
/***************************************************************** * 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); } } }
void MapWindow::RenderNearAirspace(LKSurface& Surface, const RECT rci) { RECT rc = rci; /* rectangle for sideview */ RECT rct = rc; /* rectangle for topview */ rc.top = (int)((double)(rci.bottom-rci.top )*fSplitFact); rct.bottom = rc.top ; // Expose the topview rect size in use.. Current_Multimap_TopRect=rct; LKFont hfOldFnt = Surface.SelectObject(LK8PanelUnitFont/* Sender->GetFont()*/); int *iSplit = &Multimap_SizeY[Get_Current_Multimap_Type()]; int k; static double fHeigtScaleFact = 1.0; double GPSlat, GPSlon, GPSalt, GPSbrg; double calc_terrainalt; double calc_altitudeagl; // double alt; TCHAR text[TBSIZE+1]; TCHAR buffer[TBSIZE+1]; CAirspaceBase near_airspace; CAirspace *found = NULL; // bool bFound = false; DiagrammStruct sDia; bool bAS_Inside=false; int iAS_Bearing=0; int iAS_HorDistance=15000; int iABS_AS_HorDistance=0; int iAS_VertDistance=0; bool bValid; static bool bHeightScale = false; long wpt_brg = 0; POINT line[2]; POINT TxYPt; POINT TxXPt; SIZE tsize; LKColor GREEN_COL = RGB_GREEN; LKColor BLUE_COL = RGB_BLUE; LKColor LIGHTBLUE_COL = RGB_LIGHTBLUE; BOOL bInvCol = true; //INVERTCOLORS unsigned short getsideviewpage=GetSideviewPage(); LKASSERT(getsideviewpage<3); if(bInvCol) Sideview_TextColor = INV_GROUND_TEXT_COLOUR; else Sideview_TextColor = RGB_WHITE; switch(LKevent) { case LKEVENT_NEWRUN: // CALLED ON ENTRY: when we select this page coming from another mapspace bHeightScale = false; // fZOOMScale[getsideviewpage] = 1.0; fHeigtScaleFact = 1.0; if (IsMultimapTopology()) ForceVisibilityScan=true; break; case LKEVENT_UP: // click on upper part of screen, excluding center if(bHeightScale) fHeigtScaleFact /= ZOOMFACTOR; else fZOOMScale[getsideviewpage] /= ZOOMFACTOR; if (IsMultimapTopology()) ForceVisibilityScan=true; break; case LKEVENT_DOWN: // click on lower part of screen, excluding center if(bHeightScale) fHeigtScaleFact *= ZOOMFACTOR; else fZOOMScale[getsideviewpage] *= ZOOMFACTOR; if (IsMultimapTopology()) ForceVisibilityScan=true; break; case LKEVENT_LONGCLICK: for (k=0 ; k <= Sideview_iNoHandeldSpaces; k++) { if( Sideview_pHandeled[k].psAS != NULL) { if (PtInRect(&(Sideview_pHandeled[k].rc), startScreen)) { #if 1 // MULTISELECT dlgAddMultiSelectListItem((long*) Sideview_pHandeled[k].psAS, 0, IM_AIRSPACE, 0); #else if (EnableSoundModes)PlayResource(TEXT("IDR_WAV_BTONE4")); dlgAirspaceDetails(Sideview_pHandeled[k].psAS); // dlgA #endif LKevent=LKEVENT_NONE; } } } dlgMultiSelectListShowModal(); if ( LKevent != LKEVENT_NONE ) { if (PtInRect(&rc, startScreen)) bHeightScale = !bHeightScale; if (PtInRect(&rct, startScreen)) bHeightScale = false; } break; case LKEVENT_PAGEUP: #ifdef OFFSET_SETP if(bHeightScale) fOffset -= OFFSET_SETP; else #endif { if(*iSplit == SIZE1) *iSplit = SIZE0; if(*iSplit == SIZE2) *iSplit = SIZE1; if(*iSplit == SIZE3) *iSplit = SIZE2; } break; case LKEVENT_PAGEDOWN: #ifdef OFFSET_SETP if(bHeightScale) fOffset += OFFSET_SETP; else #endif { if(*iSplit == SIZE2) *iSplit = SIZE3; if(*iSplit == SIZE1) *iSplit = SIZE2; if(*iSplit == SIZE0) *iSplit = SIZE1; } break; } LKASSERT(((*iSplit==SIZE0)||(*iSplit==SIZE1)||(*iSplit==SIZE2)||(*iSplit==SIZE3)||(*iSplit==SIZE4))); LKevent=LKEVENT_NONE; // Current_Multimap_SizeY is global, and must be used by all multimaps! // It is defined in Multimap.cpp and as an external in Multimap.h // It is important that it is updated, because we should resize terrain // only if needed! Resizing terrain takes some cpu and some time. // So we need to know when this is not necessary, having the same size of previous // multimap, if we are switching. // The current implementation is terribly wrong by managing resizing of sideview in // each multimap: it should be done by a common layer. // CAREFUL: // If for any reason DrawTerrain() is called after resizing to 0 (full sideview) // LK WILL CRASH with no hope to recover. if(Current_Multimap_SizeY != *iSplit) { Current_Multimap_SizeY=*iSplit; SetSplitScreenSize(*iSplit); rc.top = (long)((double)(rci.bottom-rci.top )*fSplitFact); rct.bottom = rc.top ; } if(bInvCol) { GREEN_COL = GREEN_COL.ChangeBrightness(0.6); BLUE_COL = BLUE_COL.ChangeBrightness(0.6);; LIGHTBLUE_COL = LIGHTBLUE_COL.ChangeBrightness(0.4);; } GPSlat = DrawInfo.Latitude; GPSlon = DrawInfo.Longitude; GPSalt = DrawInfo.Altitude; GPSbrg = DrawInfo.TrackBearing; calc_terrainalt = DerivedDrawInfo.TerrainAlt; calc_altitudeagl = DerivedDrawInfo.AltitudeAGL; GPSalt = DerivedDrawInfo.NavAltitude; bValid = false; iAS_HorDistance = 5000; iAS_Bearing = (int)GPSbrg; iAS_VertDistance= 0; found = CAirspaceManager::Instance().GetNearestAirspaceForSideview(); if(found != NULL) { near_airspace = CAirspaceManager::Instance().GetAirspaceCopy(found); bValid = near_airspace.GetDistanceInfo(bAS_Inside, iAS_HorDistance, iAS_Bearing, iAS_VertDistance); } iABS_AS_HorDistance = abs( iAS_HorDistance); wpt_brg = (long)AngleLimit360(GPSbrg - iAS_Bearing + 90.0); // Variables from ASP system here contain the following informations: // fAS_HorDistance - always contains horizontal distance from the asp, negative if horizontally inside (This does not mean that we're inside vertically as well!) // fAS_Bearing - always contains bearing to the nearest horizontal point // bValid - true if bAS_Inside, iAS_HorDistance, iAS_Bearing, iAS_VertDistance contains valid informations // this will be true if the asp border is close enough to be tracked by the warning system // bAS_Inside - current position is inside in the asp, calculated by the warning system // iAS_HorDistance - horizontal distance to the nearest horizontal border, negative if horizontally inside, calculated by the warning system // iAS_Bearing - bearing to the nearest horizontal border, calculated by the warning system // iAS_VertDistance - vertical distance to the nearest asp border, negative if the border is above us, positive if the border below us, calculated by the warning system // near_airspace.WarningLevel(): // awNone - no warning condition exists // awYellow - current position is near to a warning position // awRed - current posisiton is forbidden by asp system, we are in a warning position /********************************************************************* * calc the horizontal zoom *********************************************************************/ sDia.fXMin = -5000.0; sDia.fXMax = 5000.0; /* even when invalid the horizontal distance is calculated correctly */ if(bValid) { double fScaleDist = iABS_AS_HorDistance; sDia.fXMin = min(-2500.0 , fScaleDist * 1.5 ); sDia.fXMax = max( 2500.0 , fScaleDist * 1.5 ); #ifdef NEAR_AS_ZOOM_1000M if(((iABS_AS_HorDistance) < 900) && (bValid)) // 1km zoom { sDia.fXMin = min(-900.0, fScaleDist * 1.5 ); sDia.fXMax = max( 900.0, fScaleDist * 1.5 ); } #endif #ifdef NEAR_AS_ZOOM_1000FT if((abs(iABS_AS_HorDistance) < 333)) // 1000ft zoom { sDia.fXMin = min(-333.0, fScaleDist * 1.5 ); sDia.fXMax = max( 333.0, fScaleDist * 1.5 ); } #endif } #define RND_FACT 10.0 if( ( sDia.fXMax *fZOOMScale[getsideviewpage]) > 100000) fZOOMScale[getsideviewpage] /= ZOOMFACTOR; if(( sDia.fXMax *fZOOMScale[getsideviewpage]) < 500) { fZOOMScale[getsideviewpage] *= ZOOMFACTOR; } double fOldZoomScale=-1; if(fZOOMScale[getsideviewpage] != fOldZoomScale) { fOldZoomScale = fZOOMScale[getsideviewpage]; sDia.fXMax = sDia.fXMax *fZOOMScale[getsideviewpage]; sDia.fXMin = -sDia.fXMax /5; } /********************************************************************* * calc the vertical zoom *********************************************************************/ sDia.fYMin = max(0.0, GPSalt-2300); sDia.fYMax = max(MAXALTTODAY, GPSalt+1000); if(bValid) { double fBottom = near_airspace.Base()->Altitude; sDia.fYMin = min(fBottom*0.8, sDia.fYMin ); sDia.fYMin = max(0.0, sDia.fYMin ); if(sDia.fYMin < 300) sDia.fYMin =0; sDia.fYMax = max((fBottom*1.2f), sDia.fYMax ); if(abs(iAS_VertDistance) < 250) { sDia.fYMax = ((int)((GPSalt+abs(iAS_VertDistance))/400) + 2) *400 ; sDia.fYMin = ((int)((GPSalt-abs(iAS_VertDistance))/400) - 1) *400 ; if(sDia.fYMin-MIN_ALTITUDE < 0) sDia.fYMin = 0; } #ifdef VERTICAL_ZOOM_50 if(abs(iAS_VertDistance) < 50) { sDia.fYMax = ((int)((GPSalt+abs(iAS_VertDistance))/100) + 2) *100 ; sDia.fYMin = ((int)((GPSalt-abs(iAS_VertDistance))/100) - 1) *100 ; if(sDia.fYMin-MIN_ALTITUDE < 0) sDia.fYMin = 0; } #endif sDia.fYMin = max((double)0.0f,(double) sDia.fYMin); #ifdef OFFSET_SETP if(( sDia.fYMax + fOffset) > MAX_ALTITUDE) fOffset -= OFFSET_SETP; if(( sDia.fYMin + fOffset) < 0.0) fOffset += OFFSET_SETP; sDia.fYMin += fOffset; sDia.fYMax += fOffset; #endif // if(fHeigtScaleFact * sDia.fYMax > MAX_ALTITUDE ) // fHeigtScaleFact /=ZOOMFACTOR; if(fHeigtScaleFact * sDia.fYMax < MIN_ALTITUDE ) fHeigtScaleFact *=ZOOMFACTOR; sDia.fYMax *= fHeigtScaleFact; } /**************************************************************************************************** * draw topview first ****************************************************************************************************/ if(fSplitFact > 0.0) { sDia.rc = rct; sDia.rc.bottom-=1; SharedTopView(Surface, &sDia, (double) iAS_Bearing, (double) wpt_brg); } /**************************************************************************************************** * draw airspace and terrain elements ****************************************************************************************************/ RECT rcc = rc; /* rc corrected */ if(sDia.fYMin < GC_SEA_LEVEL_TOLERANCE) rcc.bottom -= SV_BORDER_Y; /* scale witout sea */ sDia.rc = rcc; RenderAirspaceTerrain(Surface, GPSlat, GPSlon, iAS_Bearing, &sDia ); LKFont hfOld = Surface.SelectObject(LK8InfoNormalFont); if(bValid) { LKASSERT(_tcslen(near_airspace.Name())<TBSIZE); // Diagnostic only in 3.1j, to be REMOVED LK_tcsncpy(Sideview_szNearAS, near_airspace.Name(), TBSIZE ); } else { _stprintf(text,TEXT("%s"), MsgToken(1259)); // LKTOKEN _@M1259_ "Too far, not calculated" Surface.GetTextSize(text, _tcslen(text), &tsize); TxYPt.x = (rc.right-rc.left-tsize.cx)/2; TxYPt.y = (rc.bottom-rc.top)/2; Surface.SetBkMode(TRANSPARENT); Surface.DrawText(TxYPt.x, TxYPt.y-20, text, _tcslen(text)); _stprintf(Sideview_szNearAS,TEXT("%s"), text); } Surface.SelectObject(hfOld); /**************************************************************************************************** * draw airspace and terrain elements ****************************************************************************************************/ /**************************************************************************************************** * draw diagram ****************************************************************************************************/ double xtick = 1.0; double fRange =fabs(sDia.fXMax - sDia.fXMin) ; if (fRange>3.0*1000.0) xtick = 2.0; if (fRange>15*1000.0) xtick = 5.0; if (fRange>50.0*1000.0) xtick = 10.0; if (fRange>100.0*1000.0) xtick = 20.0; if (fRange>200.0*1000.0) xtick = 25.0; if (fRange>250.0*1000.0) xtick = 50.0; if (fRange>500.0*1000.0) xtick = 100.0; if (fRange>1000.0*1000.0) xtick = 1000.0; if(bInvCol) { Surface.SelectObject(LK_BLACK_PEN); Surface.SelectObject(LKBrush_Black); } else { Surface.SelectObject(LK_WHITE_PEN); Surface.SelectObject(LKBrush_White); } LKColor txtCol = GROUND_TEXT_COLOUR; if(bInvCol) if(sDia.fYMin > GC_SEA_LEVEL_TOLERANCE) txtCol = INV_GROUND_TEXT_COLOUR; Surface.SetBkMode(TRANSPARENT); Surface.SetTextColor(txtCol); _stprintf(text, TEXT("%s"),Units::GetUnitName(Units::GetUserDistanceUnit())); switch(GetMMNorthUp(getsideviewpage)) { case NORTHUP: default: DrawXGrid(Surface, rc , xtick/DISTANCEMODIFY, xtick, 0,TEXT_ABOVE_LEFT, RGB_BLACK, &sDia,text); break; case TRACKUP: DrawXGrid(Surface, rci, xtick/DISTANCEMODIFY, xtick, 0,TEXT_ABOVE_LEFT, RGB_BLACK, &sDia,text); break; } Surface.SetTextColor(Sideview_TextColor); double fHeight = (sDia.fYMax-sDia.fYMin); double ytick = 100.0; if (fHeight >500.0) ytick = 200.0; if (fHeight >1000.0) ytick = 500.0; if (fHeight >2000.0) ytick = 1000.0; if (fHeight >4000.0) ytick = 2000.0; if (fHeight >8000.0) ytick = 4000.0; if(Units::GetUserAltitudeUnit() == unFeet) ytick = ytick * FEET_FACTOR; _stprintf(text, TEXT("%s"),Units::GetUnitName(Units::GetUserAltitudeUnit())); if(sDia.fYMin < GC_SEA_LEVEL_TOLERANCE) rc.bottom -= SV_BORDER_Y; /* scale witout sea */ DrawYGrid(Surface, rc, ytick/ALTITUDEMODIFY,ytick, 0,TEXT_UNDER_RIGHT ,Sideview_TextColor, &sDia, text); if(!bInvCol) Surface.SetBkMode(OPAQUE); /**************************************************************************************************** * draw AGL ****************************************************************************************************/ if(calc_altitudeagl - sDia.fYMin > 500) { Surface.SetTextColor(LIGHTBLUE_COL); Units::FormatUserAltitude(calc_altitudeagl, buffer, 7); LK_tcsncpy(text, MsgToken(1742), TBSIZE-_tcslen(buffer)); // AGL: _tcscat(text,buffer); Surface.GetTextSize(text, _tcslen(text), &tsize); TxYPt.x = CalcDistanceCoordinat(0, &sDia)- tsize.cx/2; TxYPt.y = CalcHeightCoordinat( (calc_terrainalt + calc_altitudeagl )*0.8, &sDia ); if((tsize.cy) < ( CalcHeightCoordinat( calc_terrainalt, &sDia )- TxYPt.y )) { Surface.DrawText(TxYPt.x+IBLSCALE(1), TxYPt.y , text, _tcslen(text)); } } Surface.SetBkMode(TRANSPARENT); /**************************************************************************************************** * Print current Elevation ****************************************************************************************************/ Surface.SetTextColor(RGB_BLACK); int x,y; if((calc_terrainalt- sDia.fYMin) > 0) { Units::FormatUserAltitude(calc_terrainalt, buffer, 7); LK_tcsncpy(text, MsgToken(1743), TBSIZE-_tcslen(buffer)); // ELV: _tcscat(text,buffer); Surface.GetTextSize(text, _tcslen(text), &tsize); x = CalcDistanceCoordinat(0, &sDia) - tsize.cx/2; y = CalcHeightCoordinat( calc_terrainalt, &sDia ); if ((ELV_FACT*tsize.cy) < abs(rc.bottom - y)) { Surface.DrawText(x, rc.bottom -(int)(ELV_FACT * tsize.cy), text, _tcslen(text)); } } /**************************************************************************************************** * draw side elements ****************************************************************************************************/ Surface.SetTextColor(Sideview_TextColor); Surface.SetBkMode(OPAQUE); LKFont hfOld2 = Surface.SelectObject(LK8InfoNormalFont); // DrawTelescope ( hdc, iAS_Bearing-90.0, rc.right - NIBLSCALE(13), rc.top + NIBLSCALE(58)); Surface.SelectObject(hfOld2); Surface.SetBkMode(TRANSPARENT); Surface.SelectObject(hfOld); Surface.SetTextColor(GROUND_TEXT_COLOUR); if(bInvCol) if(sDia.fYMin > GC_SEA_LEVEL_TOLERANCE) Surface.SetTextColor(INV_GROUND_TEXT_COLOUR); /****************************************************************************************************/ /****************************************************************************************************/ /**************************************************************************************************** * draw distances to next airspace ****************************************************************************************************/ /****************************************************************************************************/ /****************************************************************************************************/ if (bValid) { /**************************************************************************************************** * draw horizontal distance to next airspace ****************************************************************************************************/ Surface.SetTextColor(Sideview_TextColor); Surface.SetBkMode(OPAQUE); LKFont hfOldU = Surface.SelectObject(LK8InfoNormalFont); // horizontal distance line[0].x = CalcDistanceCoordinat(0, &sDia); line[0].y = CalcHeightCoordinat( GPSalt, &sDia ); line[1].x = CalcDistanceCoordinat(iABS_AS_HorDistance, &sDia); line[1].y = line[0].y; Surface.DrawDashLine(THICK_LINE, line[0], line[1], Sideview_TextColor, rc); if(iAS_HorDistance < 0) { line[0].y = CalcHeightCoordinat( GPSalt - (double)iAS_VertDistance, &sDia ); line[1].y = line[0].y; Surface.DrawDashLine(THICK_LINE, line[0], line[1], Sideview_TextColor, rc); } bool bLeft = false; if( line[0].x < line[1].x) bLeft = false; else bLeft = true; Units::FormatUserDistance(iABS_AS_HorDistance, buffer, 7); _stprintf(text,_T(" %s"),buffer); Surface.GetTextSize(text, _tcslen(text), &tsize); if((GPSalt- sDia.fYMin /*-calc_terrainalt */) < 300) TxXPt.y = CalcHeightCoordinat( GPSalt, &sDia ) - tsize.cy; else TxXPt.y = CalcHeightCoordinat( GPSalt, &sDia ) + NIBLSCALE(3); if(tsize.cx > (line[1].x - line[0].x) ) TxXPt.x = CalcDistanceCoordinat( iABS_AS_HorDistance ,&sDia) -tsize.cx- NIBLSCALE(3); else TxXPt.x = CalcDistanceCoordinat( iABS_AS_HorDistance / 2.0, &sDia) -tsize.cx/2; Surface.DrawText(TxXPt.x, TxXPt.y, text, _tcslen(text)); /**************************************************************************************************** * draw vertical distance to next airspace ****************************************************************************************************/ line[0].x = CalcDistanceCoordinat( iABS_AS_HorDistance , &sDia); line[0].y = CalcHeightCoordinat( GPSalt, &sDia ); line[1].x = line[0].x; line[1].y = CalcHeightCoordinat( GPSalt - (double)iAS_VertDistance, &sDia ); Surface.DrawDashLine(THICK_LINE, line[0], line[1], Sideview_TextColor, rc); Units::FormatUserAltitude( (double)abs(iAS_VertDistance), buffer, 7); _stprintf(text,_T(" %s"),buffer); Surface.GetTextSize(text, _tcslen(text), &tsize); if ( bLeft ) TxYPt.x = CalcDistanceCoordinat(iABS_AS_HorDistance, &sDia)- tsize.cx - NIBLSCALE(3); else TxYPt.x = CalcDistanceCoordinat(iABS_AS_HorDistance, &sDia)+ NIBLSCALE(5); if( abs( line[0].y - line[1].y) > tsize.cy) TxYPt.y = CalcHeightCoordinat( GPSalt - (double)iAS_VertDistance/2.0, &sDia) -tsize.cy/2 ; else TxYPt.y = min( line[0].y , line[1].y) - tsize.cy ; Surface.DrawText(TxYPt.x, TxYPt.y , text, _tcslen(text)); Surface.SelectObject(hfOldU); } /**************************************************************************************************** * draw plane sideview at least ****************************************************************************************************/ RenderPlaneSideview(Surface, 0.0 , GPSalt,wpt_brg, &sDia ); hfOldFnt = Surface.SelectObject(LK8InfoNormalFont/* Sender->GetFont()*/); DrawMultimap_SideTopSeparator(Surface,rct); /**************************************************************************************************** * draw selection frame ****************************************************************************************************/ if(bHeightScale) DrawSelectionFrame(Surface, rc); #ifdef TOP_SELECTION_FRAME else DrawSelectionFrame(hdc, rci); #endif Surface.SelectObject(hfOldFnt/* Sender->GetFont()*/); Surface.SetBkMode(TRANSPARENT); Surface.SelectObject(hfOldFnt/* Sender->GetFont()*/); }