static void OnPaintAirspacePicto(WindowControl * Sender, LKSurface& Surface){
	  (void)Sender;

	  WndFrame  *wPicto = ((WndFrame *)wf->FindByName(TEXT("frmAirspacePicto")));
	  LKASSERT(wPicto!=NULL);
	  const RECT rc = wPicto->GetClientRect();
	  Surface.SelectObject(LKPen_Petrol_C2);

	  Surface.SelectObject(LKBrush_Petrol);
	  Surface.Rectangle(rc.left,rc.top,rc.right,rc.bottom);


	  Surface.SetBkColor(RGB_LIGHTGREY);
      /****************************************************************
       * for drawing the airspace pictorial, we need the original data.
       * copy contain only base class property, not geo data, 
       * original data are shared ressources ! 
       * for that we need to grant all called methods are thread safe
       ****************************************************************/
   {
      CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef());
      CAirspace* airspace = CAirspaceManager::Instance().GetAirspacesForDetails();
      if(airspace) {
        airspace->DrawPicto(Surface, rc);
      }
   }
}
示例#2
0
static void OnAirspacePaintListItem(WindowControl * Sender, LKSurface& Surface){

  TCHAR label[40];
  (void)Sender;
  if (DrawListIndex < AIRSPACECLASSCOUNT){
    int i = DrawListIndex;
	LK_tcsncpy(label, CAirspaceManager::Instance().GetAirspaceTypeText(i), 39);
    int w0, w1, w2, x0;
    if (ScreenLandscape) {
      w0 = 202*ScreenScale;
    } else {
      w0 = 225*ScreenScale;
    }
	// LKTOKEN  _@M789_ = "Warn"
    w1 = Surface.GetTextWidth(MsgToken(789))+ScreenScale*10;
	// LKTOKEN  _@M241_ = "Display"
    w2 = Surface.GetTextWidth(MsgToken(241))+ScreenScale*10;
    x0 = w0-w1-w2;

    Surface.SetTextColor(RGB_BLACK);
    Surface.DrawTextClip(2*ScreenScale, 2*ScreenScale,
                   label, x0-ScreenScale*10);

    if (colormode) {

      Surface.SelectObject(LK_WHITE_PEN);
      Surface.SelectObject(LKBrush_White);
      Surface.Rectangle(x0, 2*ScreenScale,w0, 22*ScreenScale);
      Surface.SetTextColor(MapWindow::GetAirspaceColourByClass(i));
      Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF));
      Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(i));
      Surface.Rectangle(x0, 2*ScreenScale,w0, 22*ScreenScale);

    } else {

      bool iswarn;
      bool isdisplay;

      iswarn = (MapWindow::iAirspaceMode[i]>=2);
      isdisplay = ((MapWindow::iAirspaceMode[i]%2)>0);
      if (iswarn) {
	// LKTOKEN  _@M789_ = "Warn"
        _tcscpy(label, MsgToken(789));
        Surface.DrawText(w0-w1-w2, 2*ScreenScale, label);
      }
      if (isdisplay) {
	// LKTOKEN  _@M241_ = "Display"
        _tcscpy(label, MsgToken(241));
        Surface.DrawText(w0-w2, 2*ScreenScale, label);
      }

    }

  }
}
static void OnAirspacePatternsPaintListItem(WindowControl * Sender, LKSurface& Surface) {
    (void) Sender;
    if ((DrawListIndex < NUMAIRSPACEBRUSHES) &&(DrawListIndex >= 0)) {
        int i = DrawListIndex;
        Surface.SelectObject(LKBrush_White);
        Surface.SelectObject(LK_BLACK_PEN);
        Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF));
        Surface.SelectObject(MapWindow::GetAirspaceBrush(i));
        Surface.SetTextColor(LKColor(0x00, 0x00, 0x00));
        Surface.Rectangle(100 * ScreenScale, 2 * ScreenScale, 180 * ScreenScale, 22 * ScreenScale);
    }
}
示例#4
0
static void OnMultiSelectListPaintListItem(WindowControl * Sender, LKSurface& Surface) {

#define PICTO_WIDTH 50

  Surface.SetTextColor(RGB_BLACK);
  if (TaskDrawListIndex < iNO_Tasks)  {
      TCHAR *pToken = NULL;
      TCHAR *pWClast = NULL;
      TCHAR *pWClast2 = NULL;
      TCHAR text[180] = {TEXT("empty")};
      TCHAR text1[180] = {TEXT("empty")};
      TCHAR text2[180] = {TEXT("empty")};

      _tcscpy(text, szTaskStrings [TaskDrawListIndex] );
    unsigned int i=0;
    while (i < _tcslen(text) )  // remove all quotations "
    {
        if(text[i]== '"')    //  quotations found ?
        {
            for (unsigned int j= i ; j < _tcslen(text); j++)
            text[j] =  text[j+1];
        }
        i++;
    }
    pToken = strsep_r(text, TEXT(","), &pWClast) ;
    _tcscpy(text1, pToken );
    if(*text1 == '\0')   _tcscpy(text1, _T("???") );

    pToken = strsep_r(pWClast, TEXT(","), &pWClast2) ;  // remove takeof point
    _tcscpy(text2, pWClast2);

      Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF));


      PixelRect rc = {
          0,
          0,
          0, // DLGSCALE(PICTO_WIDTH),
          static_cast<PixelScalar>(Sender->GetHeight())
      };

      /********************
       * show text
       ********************/
      Surface.SetBackgroundTransparent();
      Surface.SetTextColor(RGB_BLACK);
      Surface.DrawText(rc.right + DLGSCALE(2), DLGSCALE(2), text1);
      int ytext2 = Surface.GetTextHeight(text1);
      Surface.SetTextColor(RGB_DARKBLUE);
      Surface.DrawText(rc.right + DLGSCALE(2), ytext2, text2);
  }
}
示例#5
0
static void OnAirspaceColoursPaintListItem(WindowControl * Sender, LKSurface& Surface){
  (void)Sender;
  if ((DrawListIndex < NUMAIRSPACECOLORS) &&(DrawListIndex>=0)) {
    int i = DrawListIndex;
    Surface.SelectObject(LKBrush_White);
    Surface.SelectObject(LK_BLACK_PEN);
    Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF));
    Surface.SelectObject(MapWindow::GetAirspaceSldBrush(i)); // this is the solid brush
    Surface.SetTextColor(MapWindow::GetAirspaceColour(i));
    Surface.Rectangle(
              100*ScreenScale, 
              2*ScreenScale,
              180*ScreenScale,
              22*ScreenScale);
  }
}
示例#6
0
static void OnPaintAirspacePicto(WindowControl * Sender, LKSurface& Surface){

	  const RECT rc = Sender->GetClientRect();

	  Surface.SetBkColor(RGB_LIGHTGREY);
      /****************************************************************
       * for drawing the airspace pictorial, we need the original data.
       * copy contain only base class property, not geo data, 
       * original data are shared ressources ! 
       * for that we need to grant all called methods are thread safe
       ****************************************************************/
   {
      ScopeLock guard(CAirspaceManager::Instance().MutexRef());
      CAirspace* airspace = CAirspaceManager::Instance().GetAirspacesForDetails();
      if(airspace) {
        airspace->DrawPicto(Surface, rc);
      }
   }
}
示例#7
0
static void OnMultiSelectListPaintListItem(WindowControl * Sender, LKSurface& Surface) {

    #define PICTO_WIDTH 50
    
    Surface.SetTextColor(RGB_BLACK);
    if ((DrawListIndex < iNO_ELEMENTS) &&(DrawListIndex >= 0)) {
        int j;
        static CAirspaceBase airspace_copy;
        int i = DrawListIndex;
        LKASSERT(i < MAX_LIST_ITEMS);
        PixelRect rc = {
            0, 
            0, 
            DLGSCALE(PICTO_WIDTH), 
            static_cast<PixelScalar>(Sender->GetHeight())
        };

        const CAirspace* pAS = NULL;
        int HorDist, Bearing, VertDist;
        double Distance;
        unsigned int idx = 0;
        TCHAR text1[180] = {TEXT("empty")};
        TCHAR text2[180] = {TEXT("empty")};
        TCHAR Comment[80] = {TEXT("")};
        TCHAR Comment1[80] = {TEXT("")};
        Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF));
        LKASSERT(i < MAX_LIST_ITEMS);

        switch (Elements[i].type) {
        case IM_AIRSPACE:
            pAS = (CAirspace*) Elements[i].ptr;
            if (pAS) {
                /***********************************************************************
                 * here we use a local copy of the airspace, only common property exists
                 ***********************************************************************/
                airspace_copy = CAirspaceManager::Instance().GetAirspaceCopy(pAS);

                // airspace type already in name?
                if (_tcsnicmp(airspace_copy.Name(), airspace_copy.TypeName(), _tcslen(airspace_copy.TypeName())) == 0) {
                    _stprintf(text1, TEXT("%s"), airspace_copy.Name()); // yes, take name only
                } else {
                    // fixed strings max. 20 NAME_SIZE 30 => max. 30 char
                    _stprintf(text1, TEXT("%s %s"), airspace_copy.TypeName(), airspace_copy.Name());
                }

                CAirspaceManager::Instance().GetSimpleAirspaceAltText(Comment, sizeof (Comment) / sizeof (Comment[0]), airspace_copy.Top());
                CAirspaceManager::Instance().GetSimpleAirspaceAltText(Comment1, sizeof (Comment1) / sizeof (Comment1[0]), airspace_copy.Base());

                CAirspaceManager::Instance().AirspaceCalculateDistance((CAirspace*) pAS, &HorDist, &Bearing, &VertDist);
                _stprintf(text2, TEXT("%3.1f%s (%s - %s)"), (double) HorDist*DISTANCEMODIFY, Units::GetDistanceName(), Comment1, Comment); //8 + 8+3   21

                /****************************************************************
                 * for drawing the airspace pictorial, we need the original data.
                 * copy contain only base class property, not geo data,
                 * original data are shared ressources !
                 * for that we need to grant all called methods are thread safe
                 ****************************************************************/
                pAS->DrawPicto(Surface, rc);
            }
            break;


        case IM_TASK_PT:
        case IM_WAYPOINT:
            idx = -1;
            LockTaskData(); // protect from external task changes

            if (Elements[i].type == IM_TASK_PT) {
                if(ValidTaskPointFast(Elements[i].iIdx)) {
                    idx = Task[Elements[i].iIdx].Index;
                }
            } else {
                if(ValidWayPointFast(Elements[i].iIdx)) {
                    idx = Elements[i].iIdx;
                }
            }

            // This is not a solution. It will avoid a crash but the solution is to understand
            // why we are getting a wrong idx, eventually. If ever we got a wrong idx!
            // And then this "fix" should be changed to something more useful, instead of 
            // adopting a totally wrong waypoint for task.
            assert(idx < WayPointList.size());
            if(idx < WayPointList.size()) {

                if (WayPointList[idx].Comment != NULL) {
                    LK_tcsncpy(Comment, WayPointList[idx].Comment, 30);
                } else {
                    _tcscpy(Comment, TEXT(""));
                }

                DistanceBearing(GPS_INFO.Latitude, GPS_INFO.Longitude, WayPointList[idx].Latitude,
                                WayPointList[idx].Longitude, &Distance, NULL);

                if (Elements[i].type != IM_TASK_PT) {
                    if (WayPointCalc[idx].IsLandable) {
                        MapWindow::DrawRunway(Surface, &WayPointList[idx], rc, nullptr, 1.5, true);

                        if (WayPointCalc[idx].IsAirport) {
                            // remove spaces from frequency
                            for (j = 1; j < (CUPSIZE_FREQ); j++)
                                if (WayPointList[idx].Freq[CUPSIZE_FREQ - j] == ' ')
                                    WayPointList[idx].Freq[CUPSIZE_FREQ - j] = '\0';

                            if (_tcslen(WayPointList[idx].Freq) > 2)
                                _stprintf(text1, TEXT("%s %s MHz"), WayPointList[idx].Name,
                                          WayPointList[idx].Freq);
                            else
                                _stprintf(text1, TEXT("%s"), WayPointList[idx].Name);
                        } else {
                            if (WayPointList[idx].Comment != NULL)
                                _stprintf(text1, TEXT("%s %s"), WayPointList[idx].Name, Comment);
                            else
                                _stprintf(text1, TEXT("%s"), WayPointList[idx].Name);
                        }

                        if ((WayPointList[idx].RunwayLen >= 10) ||
                            (WayPointList[idx].RunwayDir > 0)) {
                            _stprintf(text2, TEXT("%3.1f%s (%i%s  %02i/%02i  %i%s)"),
                                      Distance * DISTANCEMODIFY, Units::GetDistanceName(),
                                      (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY),
                                      Units::GetAltitudeName(),
                                      (int) (WayPointList[idx].RunwayDir / 10.0 + 0.5),
                                      (int) (AngleLimit360(WayPointList[idx].RunwayDir + 180.0) /
                                             10.0 + 0.5),
                                      (int) ((double) WayPointList[idx].RunwayLen * ALTITUDEMODIFY),
                                      Units::GetAltitudeName());
                        } else {
                            _stprintf(text2, TEXT("%3.1f%s (%i%s) "), Distance * DISTANCEMODIFY,
                                      Units::GetDistanceName(),
                                      (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY),
                                      Units::GetAltitudeName());
                        }

                    }// waypoint isLandable
                    else {
                        MapWindow::DrawWaypointPicto(Surface, rc, &WayPointList[idx]);
                        _stprintf(text1, TEXT("%s %s"), WayPointList[idx].Name, Comment);

                        _stprintf(text2, TEXT("%3.1f%s (%i%s)"), Distance * DISTANCEMODIFY,
                                  Units::GetDistanceName(),
                                  (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY),
                                  Units::GetAltitudeName());
                    }

                }// Elements IM_TASK
                else {
                    int iTaskIdx = Elements[i].iIdx;
                    MapWindow::DrawTaskPicto(Surface, iTaskIdx, rc, 3000);
                    int iLastTaskPoint = 0;

                    while (ValidTaskPoint(iLastTaskPoint))
                        iLastTaskPoint++;

                    iLastTaskPoint--;

                    if (iTaskIdx == 0) {
                        // _@M2301_  "S"    # S = Start Task point
                        _stprintf(text1, TEXT("%s: (%s)"), MsgToken(2301), WayPointList[idx].Name);
                        _stprintf(text2, TEXT("Radius %3.1f%s (%i%s)"),
                                  StartRadius * DISTANCEMODIFY, Units::GetDistanceName(),
                                  (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY),
                                  Units::GetAltitudeName());
                    } else {
                        if (iTaskIdx == iLastTaskPoint) {
                            //	_@M2303_  "F"                 // max 30         30 => max 60 char
                            _stprintf(text1, TEXT("%s: (%s) "), MsgToken(2303),
                                      WayPointList[idx].Name);
                            _stprintf(text2, TEXT("Radius %3.1f%s (%i%s)"),
                                      FinishRadius * DISTANCEMODIFY, Units::GetDistanceName(),
                                      (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY),
                                      Units::GetAltitudeName());
                        } else {
                            //   _@M2302_  "T"    # F = Finish point            // max 30         30 => max 60 char
                            _stprintf(text1, TEXT("%s%i: (%s) "), MsgToken(2302), iTaskIdx,
                                      WayPointList[idx].Name);
                            double SecRadius = 0;

                            SecRadius = SectorRadius;
                            if (AATEnabled) {
                                if (Task[iTaskIdx].AATType == SECTOR)
                                    SecRadius = Task[iTaskIdx].AATSectorRadius;
                                else
                                    SecRadius = Task[iTaskIdx].AATCircleRadius;
                            }

                            _stprintf(text2, TEXT("Radius %3.1f%s (%i%s)"),
                                      SecRadius * DISTANCEMODIFY, Units::GetDistanceName(),
                                      (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY),
                                      Units::GetAltitudeName());
                        }
                    }

                }
            }
            UnlockTaskData(); // protect from external task changes
            break;
        }

        /********************
         * show text
         ********************/
        Surface.SetBackgroundTransparent();
        Surface.SetTextColor(RGB_BLACK);
        Surface.DrawText(rc.right + DLGSCALE(2), DLGSCALE(2), text1);
        int ytext2 = Surface.GetTextHeight(text1);
        Surface.SetTextColor(RGB_DARKBLUE);
        Surface.DrawText(rc.right + DLGSCALE(2), ytext2, text2);

    }
}
示例#8
0
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;

    auto hfOldFnt = Surface.SelectObject(LK8PanelUnitFont/* Sender->GetFont()*/);

    int *iSplit = &Multimap_SizeY[Get_Current_Multimap_Type()];

    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:
            if (Sideview_iNoHandeldSpaces) {
                bool bShow = false;
                for (int k = 0; k <= Sideview_iNoHandeldSpaces; k++) {
                    if (Sideview_pHandeled[k].psAS != NULL) {
                        if (PtInRect(&(Sideview_pHandeled[k].rc), startScreen)) {
                            dlgAddMultiSelectListItem((long*) Sideview_pHandeled[k].psAS, 0, IM_AIRSPACE, 0);
                            bShow = true;
                        }
                    }
                }
                if (bShow) {
                    /*
                     * we can't show dialog from Draw thread
                     * instead, new event is queued, dialog will be popup by main thread 
                     */
                    InputEvents::processGlideComputer(GCE_POPUP_MULTISELECT);

                    // reset event, otherwise Distance/height zoom mod are also triggered
                    LKevent = LKEVENT_NONE;
                }
            }

            if (LKevent != LKEVENT_NONE) {
                if (PtInRect(&rc, startScreen)) {
                    bHeightScale = !bHeightScale;
                } else 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);

    const auto 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, &tsize);
        TxYPt.x = (rc.right - rc.left - tsize.cx) / 2;
        TxYPt.y = (rc.bottom - rc.top) / 2;

        Surface.SetBackgroundTransparent();
        Surface.DrawText(TxYPt.x, TxYPt.y - 20, 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.SetBackgroundTransparent();
    Surface.SetTextColor(txtCol);
    Surface.SelectObject(LK8PanelUnitFont);
    _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);


    Surface.SetBkColor(RGB_WHITE);

    if (!bInvCol)
        Surface.SetBackgroundOpaque();
    /****************************************************************************************************
     * 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, &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);
        }
    }

    Surface.SetBackgroundTransparent();

    /****************************************************************************************************
     * 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, &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);
        }
    }


    /****************************************************************************************************
     * draw side elements
     ****************************************************************************************************/
    Surface.SetTextColor(Sideview_TextColor);
    Surface.SetBackgroundOpaque();
    const auto hfOld2 = Surface.SelectObject(LK8InfoNormalFont);

    //  DrawTelescope      ( hdc, iAS_Bearing-90.0, rc.right  - NIBLSCALE(13),  rc.top   + NIBLSCALE(58));

    Surface.SelectObject(hfOld2);
    Surface.SetBackgroundTransparent();

    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.SetBackgroundOpaque();
        const auto 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, &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);



        /****************************************************************************************************
         * 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, &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);
        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.SetBackgroundTransparent();
    Surface.SelectObject(hfOldFnt/* Sender->GetFont()*/);
}