예제 #1
0
void MapWindow::DrawBestCruiseTrack(LKSurface& Surface, const POINT& Orig)
{
  if (OvertargetMode>OVT_TASK) return;

  if (!ValidTaskPoint(ActiveTaskPoint)) return;

  if (DerivedDrawInfo.WaypointDistance < 0.010) return;

  // dont draw bestcruise indicator if not needed
  if (fabs(DerivedDrawInfo.BestCruiseTrack-DerivedDrawInfo.WaypointBearing)<2) { // 091202 10 to 2
	return;
  } 


  const auto hpOld = Surface.SelectObject(LKPen_Blue_N1);
  const auto hbOld = Surface.SelectObject(LKBrush_Blue);

  if (Appearance.BestCruiseTrack == ctBestCruiseTrackDefault){

    int dy = (long)(70); 
    POINT Arrow[7] = { {-1,-40}, {1,-40}, {1,0}, {6,8}, {-6,8}, {-1,0}, {-1,-40}};

    Arrow[2].y -= dy;
    Arrow[3].y -= dy;
    Arrow[4].y -= dy;
    Arrow[5].y -= dy;

    PolygonRotateShift(Arrow, 7, Orig.x, Orig.y, 
                       DerivedDrawInfo.BestCruiseTrack-DisplayAngle);

    Surface.Polygon(Arrow,7);

  } else
  if (Appearance.BestCruiseTrack == ctBestCruiseTrackAltA){

    POINT Arrow[] = { {-1,-40}, {-1,-62}, {-6,-62}, {0,-70}, {6,-62}, {1,-62}, {1,-40}, {-1,-40}};

    PolygonRotateShift(Arrow, sizeof(Arrow)/sizeof(Arrow[0]),
                       Orig.x, Orig.y, 
                       DerivedDrawInfo.BestCruiseTrack-DisplayAngle);
    Surface.Polygon(Arrow, (sizeof(Arrow)/sizeof(Arrow[0])));
  }

  Surface.SelectObject(hpOld);
  Surface.SelectObject(hbOld);
}
예제 #2
0
void Statistics::DrawFilledLineGraph(LKSurface& Surface, const RECT& rc,
				     LeastSquares* lsdata,
				     const LKColor& color) {

  POINT line[4];

  for (int i=0; i<lsdata->sum_n-1; i++) {
    line[0].x = (int)((lsdata->xstore[i]-x_min)*xscale)+rc.left+BORDER_X;
    line[0].y = (int)((y_max-lsdata->ystore[i])*yscale)+rc.top;
    line[1].x = (int)((lsdata->xstore[i+1]-x_min)*xscale)+rc.left+BORDER_X;
    line[1].y = (int)((y_max-lsdata->ystore[i+1])*yscale)+rc.top;
    line[2].x = line[1].x;
    line[2].y = rc.bottom-BORDER_Y;
    line[3].x = line[0].x;
    line[3].y = rc.bottom-BORDER_Y;
    Surface.Polygon(line, 4);
  }
}
예제 #3
0
// This is painting traffic icons on the screen.
void MapWindow::LKDrawFLARMTraffic(LKSurface& Surface, const RECT& rc, const ScreenProjection& _Proj, const POINT& Orig_Aircraft) {

  if (!EnableFLARMMap) return;

  if (!DrawInfo.FLARM_Available) return;

  // init scaled coords for traffic icon
static int	iCircleSize = 7;
static int	iRectangleSize = 4;
  static short tscaler=0;
  if (DoInit[MDI_DRAWFLARMTRAFFIC]) {

	switch (ScreenSize) {
		case ss480x640:
		case ss480x800:
		case ss800x480:
		case ss640x480:
			iCircleSize = 9;
			iRectangleSize = 5;
			tscaler=NIBLSCALE(7)-2;
			break;
		case ss240x320:
		case ss272x480:
		case ss320x240:
		case ss480x272:
		case ss480x234:
		case ss400x240:
			iCircleSize = 7;
			iRectangleSize = 4;
			tscaler=NIBLSCALE(13)-2;
			break;
		default:
			iCircleSize = 7;
			iRectangleSize = 4;
			tscaler=NIBLSCALE(7);
			break;
	}


	DoInit[MDI_DRAWFLARMTRAFFIC]=false;
  }

  POINT Arrow[5];

  TCHAR lbuffer[50];

  const auto hpold = Surface.SelectObject(LKPen_Black_N1);

  int i;
  int painted=0;

//  double dX, dY;

  TextInBoxMode_t displaymode = {0};
  displaymode.NoSetFont = 1;

  #if 0
  double screenrange = GetApproxScreenRange();
  double scalefact = screenrange/6000.0; // FIX 100820
  #endif




  const auto oldfont = Surface.SelectObject(LK8MapFont);

  for (i=0,painted=0; i<FLARM_MAX_TRAFFIC; i++) {

	// limit to 10 icons map traffic
	if (painted>=10) {
		i=FLARM_MAX_TRAFFIC;
		continue;
	}

	if ( (DrawInfo.FLARM_Traffic[i].ID !=0) && (DrawInfo.FLARM_Traffic[i].Status != LKT_ZOMBIE) ) {

		painted++;

		double target_lon;
		double target_lat;

		target_lon = DrawInfo.FLARM_Traffic[i].Longitude;
		target_lat = DrawInfo.FLARM_Traffic[i].Latitude;

		#if (0) // No scaling, wrong
		if ((EnableFLARMMap==2)&&(scalefact>1.0)) {

			double distance;
			double bearing;

			DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, target_lat, target_lon, &distance, &bearing);
			FindLatitudeLongitude(DrawInfo.Latitude, DrawInfo.Longitude, bearing, distance*scalefact, &target_lat, &target_lon);
		}
		#endif
      
		POINT sc, sc_name, sc_av;
		sc = _Proj.LonLat2Screen(target_lon, target_lat);

		sc_name = sc;

		sc_name.y -= NIBLSCALE(16);
		sc_av = sc_name;

		_tcscpy(lbuffer,_T(""));
		if (DrawInfo.FLARM_Traffic[i].Cn && DrawInfo.FLARM_Traffic[i].Cn[0]!=_T('?')) { // 100322
			_tcscat(lbuffer,DrawInfo.FLARM_Traffic[i].Cn);
		}
		if (DrawInfo.FLARM_Traffic[i].Average30s>=0.1) {
                  size_t len = _tcslen(lbuffer);
                  if (len > 0)
                    _stprintf(lbuffer + len,_T(":%.1f"),LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s);
                  else
                    _stprintf(lbuffer,_T("%.1f"),LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s);
		}

		displaymode.Border=1;

		if (_tcslen(lbuffer)>0)
		TextInBox(Surface, &rc, lbuffer, sc.x+tscaler, sc.y+tscaler, &displaymode, false);

		// red circle
		if ((DrawInfo.FLARM_Traffic[i].AlarmLevel>0) && (DrawInfo.FLARM_Traffic[i].AlarmLevel<4)) {
			DrawBitmapIn(Surface, sc, hFLARMTraffic,true);
		}
#if 1 // 1
		Arrow[0].x = -4;
		Arrow[0].y = 5;
		Arrow[1].x = 0;
		Arrow[1].y = -6;
		Arrow[2].x = 4;
		Arrow[2].y = 5;
		Arrow[3].x = 0;
		Arrow[3].y = 2;
		Arrow[4].x = -4;
		Arrow[4].y = 5;

		for (int q=0; q < 5; q++)
		{
			Arrow[q].x  = (LONG) ((double)Arrow[q].x * 1.7);
			Arrow[q].y  = (LONG) ((double)Arrow[q].y * 1.7);
		}
#else

		Arrow[0].x = scaler[0];
		Arrow[0].y = scaler[1];
		Arrow[1].x = 0;
		Arrow[1].y = scaler[2];
		Arrow[2].x = scaler[3];
		Arrow[2].y = scaler[1];
		Arrow[3].x = 0;
		Arrow[3].y = scaler[4];
		Arrow[4].x = scaler[0];
		Arrow[4].y = scaler[1];
#endif


/*
		switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321
			case LKT_GHOST:
				Surface.SelectObject(yellowBrush);
				break;
			case LKT_ZOMBIE:
				Surface.SelectObject(redBrush);
				break;
			default:
				Surface.SelectObject(greenBrush);
				break;
		}
*/
		  /*************************************************************************
		   * calculate climb color
		   *************************************************************************/

		  int iVarioIdx = (int)(2*DrawInfo.FLARM_Traffic[i].Average30s  -0.5)+NO_VARIO_COLORS/2;
		  if(iVarioIdx < 0) iVarioIdx =0;
		  if(iVarioIdx >= NO_VARIO_COLORS) iVarioIdx =NO_VARIO_COLORS-1;
		  Surface.SelectObject(*variobrush[iVarioIdx]);

		  switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321
			case LKT_GHOST:
				Surface.Rectangle(sc.x-iRectangleSize,  sc.y-iRectangleSize,sc.x+iRectangleSize, sc.y+iRectangleSize);
				break;
			case LKT_ZOMBIE:
				Surface.DrawCircle(sc.x,  sc.x, iCircleSize, rc, true );
				break;
			default:
				PolygonRotateShift(Arrow, 5, sc.x, sc.y, DrawInfo.FLARM_Traffic[i].TrackBearing - DisplayAngle);
				Surface.Polygon(Arrow,5);
				break;
		  }

	}
  }

  Surface.SelectObject(oldfont);
  Surface.SelectObject(hpold);

}
예제 #4
0
void Topology::Paint(LKSurface& Surface, const RECT& rc) {

  if (!shapefileopen) return;
  bool nolabels=false;
  // 130217 scaleCat 5 and 10 are the same! So careful..
  if (scaleCategory==10||scaleCategory==5) {
	// for water areas, use scaleDefault
	if ( MapWindow::zoom.RealScale()>scaleDefaultThreshold) {
		return;
	}
	// since we just checked category 10, if we are over scale we set nolabels
	if ( MapWindow::zoom.RealScale()>scaleThreshold) nolabels=true;
  } else 
  if (MapWindow::zoom.RealScale() > scaleThreshold) return;

  // TODO code: only draw inside screen!
  // this will save time with rendering pixmaps especially
  // checkVisible does only check lat lon , not screen pixels..
  // We need to check also screen.


  const auto hpOld = Surface.SelectObject(hPen);

  LKSurface::OldBrush hbOld {};
  if (hbBrush) {
    hbOld = Surface.SelectObject(hbBrush);
  }

  const auto hfOld = Surface.SelectObject(MapTopologyFont);

  // get drawing info
  int iskip = 1;
 
  // attempt to bugfix 100615 polyline glitch with zoom over 33Km
  // do not skip points, if drawing coast lines which have a scaleThreshold of 100km!
  // != 5 and != 10
  if (scaleCategory>10) { 
  if (MapWindow::zoom.RealScale()>0.25*scaleThreshold) {
    iskip = 2;
  } 
  if (MapWindow::zoom.RealScale()>0.5*scaleThreshold) {
    iskip = 3;
  }
  if (MapWindow::zoom.RealScale()>0.75*scaleThreshold) {
    iskip = 4;
  }
  }

  // use the already existing screenbounds_latlon, calculated by CalculateScreenPositions in MapWindow2
  rectObj screenRect = MapWindow::screenbounds_latlon;

  static POINT pt[MAXCLIPPOLYGON];

  for (int ixshp = 0; ixshp < shpfile.numshapes; ixshp++) {
    
    XShape *cshape = shpCache[ixshp];

    if (!cshape || cshape->hide) continue;    

    shapeObj *shape = &(cshape->shape);

    switch(shape->type) {


      case(MS_SHAPE_POINT):{

	#if 101016
	// -------------------------- NOT PRINTING ICONS ---------------------------------------------
	bool dobitmap=false;
	if (scaleCategory<90 || (MapWindow::zoom.RealScale()<2)) dobitmap=true;
	// first a latlon overlap check, only approximated because of fastcosine in latlon2screen
	if (checkVisible(*shape, screenRect))
		for (int tt = 0; tt < shape->numlines; tt++) {
			for (int jj=0; jj< shape->line[tt].numpoints; jj++) {
				POINT sc;
				MapWindow::LatLon2Screen(shape->line[tt].point[jj].x, shape->line[tt].point[jj].y, sc);
				if (dobitmap) {
					// bugfix 101212 missing case for scaleCategory 0 (markers)
					if (scaleCategory==0||cshape->renderSpecial(Surface, sc.x, sc.y, rc))
						MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true);
				} else {
					cshape->renderSpecial(Surface, sc.x, sc.y, rc);
				}
			}
		}
	}

	#else
	// -------------------------- PRINTING ICONS ---------------------------------------------
	// no bitmaps for small town over a certain zoom level and no bitmap if no label at all levels
	bool nobitmap=false, noiconwithnolabel=false;
	if (scaleCategory==90 || scaleCategory==100) {
		noiconwithnolabel=true;
		if (MapWindow::MapScale>4) nobitmap=true;
	}

	if (checkVisible(*shape, screenRect))
		for (int tt = 0; tt < shape->numlines; tt++) {
			for (int jj=0; jj< shape->line[tt].numpoints; jj++) {
				POINT sc;
				MapWindow::LatLon2Screen(shape->line[tt].point[jj].x, shape->line[tt].point[jj].y, sc);
	
				if (!nobitmap)
				#if 101016
				// only paint icon if label is printed too
				if (noiconwithnolabel) {
					if (cshape->renderSpecial(Surface, sc.x, sc.y,labelprinted))
						MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true);
				} else {
					MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true);
					cshape->renderSpecial(Surface, sc.x, sc.y,labelprinted);
				}
				#else
				MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true);
				cshape->renderSpecial(Surface, sc.x, sc.y);
				#endif
			}
		}

	}
	#endif // Use optimized point icons 1.23e
	break;

    case(MS_SHAPE_LINE):

      if (checkVisible(*shape, screenRect))
        for (int tt = 0; tt < shape->numlines; ++tt) {
          
          int minx = rc.right;
          int miny = rc.bottom;
          int msize = min(shape->line[tt].numpoints, MAXCLIPPOLYGON);

          MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize, 1);
          for (int jj=0; jj< msize; ++jj) {
            if (pt[jj].x<=minx) {
              minx = pt[jj].x;
              miny = pt[jj].y;
            }
	      }
          Surface.Polyline(pt, msize, rc);
          cshape->renderSpecial(Surface,minx,miny,rc);
        }
      break;
      
    case(MS_SHAPE_POLYGON):

	// if it's a water area (nolabels), print shape up to defaultShape, but print
	// labels only up to custom label levels
	if ( nolabels ) {
		if (checkVisible(*shape, screenRect)) {
			for (int tt = 0; tt < shape->numlines; ++tt) {
				int msize = min(shape->line[tt].numpoints/iskip, MAXCLIPPOLYGON);
				MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize*iskip, iskip);
				Surface.Polygon(pt, msize, rc);
			}
		}
	} else 
	if (checkVisible(*shape, screenRect)) {
		for (int tt = 0; tt < shape->numlines; ++tt) {
			int minx = rc.right;
			int miny = rc.bottom;
			int msize = min(shape->line[tt].numpoints/iskip, MAXCLIPPOLYGON);
			MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize*iskip, iskip);
			for (int jj=0; jj< msize; ++jj) {
				if (pt[jj].x<=minx) {
					minx = pt[jj].x;
					miny = pt[jj].y;
				}
			}
			Surface.Polygon(pt, msize, rc);
			cshape->renderSpecial(Surface,minx,miny,rc);
		}
	}
	break;
      
    default:
      break;
    }
  }
예제 #5
0
void MapWindow::DrawRunway(LKSurface& Surface, const WAYPOINT* wp, const RECT& rc, const ScreenProjection* _Proj, double fScaleFact, BOOL picto)
{
  if(!picto && !_Proj) {
      // if we don't draw picto ScreenProjection parameter are mandatory.
      assert(false);
      return;
  }

  int solid= false;
  bool bGlider = false;
  bool bOutland = false;
  bool bRunway = false;
  static double rwl = 8;
  static double rwb = 1;
  static double cir = 6;
  static double scale_drawradio=0;
  static double scale_bigfont=0;
  static double scale_fullinfos=0;

  RasterPoint Center;
  if(picto) {
	  Center.x = rc.left+ (rc.right- rc.left)/2;
	  Center.y = rc.bottom +(rc.top-rc.bottom)/2;
  } else {
      Center =  _Proj->ToRasterPoint(wp->Latitude, wp->Longitude);
  }

  int l,p,b;

  if(picto)
	fScaleFact /=2000;
  else
        fScaleFact /=1600;

  if (DoInit[MDI_MAPWPVECTORS])
  {
    //
    // How long and thick is the runway drawn, and how big is the circle.
    // No rule possible, it depends on how we are dealing with many other
    // custom things on screen, because LK is drawing differently depending
    // on geometry, resolution, orientation. We dont split bits.
    //
    switch(ScreenSize)
    {
     case ss240x320: rwl = 9.0; rwb = 2.0;cir = 4.0; break; // 43
     case ss240x400: rwl = 9.0; rwb = 1.0;cir = 4.0; break; // 53
     case ss272x480: rwl = 9.0; rwb = 2.5;cir = 4.0; break; // 169
     case ss480x640: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 43
     case ss600x800: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 43
     case ss480x800: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 53
     case sslandscape: rwl = 6.0; rwb = 1.0;cir = 5.0; break; // sslandscape is never assigned!
     case ss320x240: rwl = 9.0; rwb = 2.0;cir = 4.0; break; // 43
     case ss400x240: rwl = 9.0; rwb = 1.0;cir = 4.0; break; // 53
     case ss480x234: rwl = 9.0; rwb = 1.0;cir = 4.0; break; // 21
     case ss480x272: rwl = 9.0; rwb = 2.5;cir = 4.0; break; // 169
     case ss640x480: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 43
     case ss800x600: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 43
     case ss800x480: rwl = 6.0; rwb = 2.5;cir = 5.0; break; // 53
     case ssnone:
#if defined(ANDROID) || defined(KOBO)
                 rwl = 6.0; rwb = 2.5; cir = 5.0; break;
#else
      //   the line above is only a workaround to avoid runaway to be tool long on  Anrtoid and Kobo
      //   waiting  for a definitive and more elegant solution.
      //

         #define X ScreenSizeX==
	 #define Y ScreenSizeY==
         // Ok this doesnt look nice, but lets remember we are inside a DoInit.
         // Generally the generic setup is good for everyone, but in case we
         // can make it custom for any resolution.
         if (X 1024 && Y 768) {; rwl = 4.5; rwb = 2.5; cir = 5.0; } else
         if (X 1014 && Y 758) {; rwl = 4.5; rwb = 2.5; cir = 5.0; } else
         if (X 720 && Y 408) {; rwl = 10.0; rwb = 6.0; cir = 5.0; } else
         if (X 720 && Y 432) {; rwl = 10.0; rwb = 4.0; cir = 5.0; } else

         // .. and this is the rule of thumb, I could not find a better idea
         // I think it is easier to redesign the drawing approach and make it
         // really scalable.
         //
         // This hack works for: 800x600 960x540 1280x720 (and relative portrait modes)
         // These are the screen resolutions used by kobo, samsung s4 mini and s5 mini
         //
         if (ScreenLandscape) {
             if (ScreenSizeX<=480) {
		 // testlk> Ok: t5     Bad for: -
                 rwl = 9.0*(480.0/ScreenSizeX); rwb = 2.5*(480.0/ScreenSizeX); cir = 4.0;
             } else {
		 // testlk> Ok:  3,13,14,22    Bad: t4, t15, t23
                 rwl = 6.0; rwb = 2.5; cir = 5.0;
             }
         } else {
             if (ScreenSizeX<480) {
		 // testlk> Ok: 10,19     Bad for: 20
                 rwl = 6.0*(480.0/ScreenSizeX); rwb = 2.5*(480.0/ScreenSizeX); cir = 4.0;
             } else {
		 // testlk> Ok: 8,28     Bad for: -
                 rwl = 6.0; rwb = 2.5; cir = 5.0;
             }
         }
         break;
#endif

    }


    //
    // These are the (absolute) scale thresholds for painting informations
    // For example, paint just radio starting from 5.0km (3.6abs) etc.
    // There is no rule possible, it matters only testing.
    //
    switch(ScreenSize)
    {

	case ss480x272:
		scale_drawradio=2.6;
		scale_bigfont=1.1;
		scale_fullinfos=0.8;
		break;
	case ss800x480:
		scale_drawradio=2.6;
		scale_bigfont=1.5;
		scale_fullinfos=1.5;
		break;
	case ss640x480:
		scale_drawradio=3.6;
		scale_bigfont=1.5;
		scale_fullinfos=1.5;
		break;

	default:

                scale_drawradio=3.6;
                scale_bigfont=1.5;
                scale_fullinfos=1.5;
                break;
    }


    DoInit[MDI_MAPWPVECTORS]=false;
  }

  if( wp->RunwayLen > 100) /* square if no runway defined */
  {
    if (picto)
       l = (int) (rwl);
    else {
#ifndef __linux__
       // We cant rescale runways , no method found.
       if (ScreenSize==ssnone)
           l = (int) (rwl * (1.0+ (680.0/800.0-1.0)/4.0)); // wtf..!
       else
#endif
           l = (int) (rwl * (1.0+ ((double)wp->RunwayLen/800.0-1.0)/4.0));
    }

    b = (int) (rwb/1.5 );
  } else
  {
    l = (int)( rwl*0.5);
    b = l ;
  }

#if defined(ANDROID) || defined(KOBO)
  l = (int)(l * 2.0 * fScaleFact / ScreenScale); if(l==0) l=1;
  b = (int)(b * 2.0 * fScaleFact / ScreenScale); if(b==0) b=1;
  p = (int)(cir * 2.0 * fScaleFact); if(p==0) p=1;
#else
  l = (int)(l * fScaleFact); if(l==0) l=1;
  b = (int)(b * fScaleFact); if(b==0) b=1;
  p = (int)(cir * 2.0 * fScaleFact); if(p==0) p=1;
#endif

  switch(wp->Style) {
	case STYLE_AIRFIELDSOLID: solid = true;  bRunway  = true;  bOutland = false;  bGlider  = false;	break;
	case STYLE_AIRFIELDGRASS: solid = false; bRunway  = true;  bOutland = false;  bGlider  = false;	break;
	case STYLE_OUTLANDING	: solid = false; bRunway  = true;  bOutland = true;   bGlider  = false; b*=2; break;
	case STYLE_GLIDERSITE	: solid = false; bRunway  = true;  bOutland = false;  bGlider  = true;	break;
	default: return; break;
  }

  // Do not print glidersite at low zoom levels, in any case
  // not useful on some resolutions
  // if( !picto && (MapWindow::zoom.RealScale() > 3) )
  //	bGlider=false;

  const auto oldPen = Surface.SelectObject(LK_BLACK_PEN);
  const auto oldBrush = Surface.SelectObject(LKBrush_Red);

  if( wp->Reachable == TRUE)
    Surface.SelectObject(LKBrush_Green);


  if(!bOutland)
  {
	if (picto)
		Surface.DrawCircle(Center.x, Center.y, p, true);
	else
		Surface.DrawCircle(Center.x, Center.y, p,  rc, true);
  }

  if(bRunway)
  {
	POINT Runway[5] = {
		  { b, l },  // 1
		  {-b, l },  // 2
		  {-b,-l },  // 3
		  { b,-l },  // 4
		  { b,l  }   // 5
	};
	if(!bOutland)
	{
            #ifndef DITHER
	    if(solid)
		  Surface.SelectObject(LKBrush_DarkGrey );
	    else
		  Surface.SelectObject(LKBrush_White);
            #else
	    if(solid)
		  Surface.SelectObject(LKBrush_Black);
	    else
		  Surface.SelectObject(LKBrush_White);
            #endif
	}
	if(picto) {
	  threadsafePolygonRotateShift(Runway, 5,  Center.x, Center.y,  wp->RunwayDir);
	} else {
	  PolygonRotateShift(Runway, 5,  Center.x, Center.y,  wp->RunwayDir- (int)MapWindow::GetDisplayAngle());
	}
	Surface.Polygon(Runway ,5 );

  } // bRunway


  if(fScaleFact >= 0.9) {
    if(bGlider)
    {
	    int iScale = (int)(fScaleFact*2.0);
		    double fFact = 0.04*fScaleFact/1.5;
            if(iScale==0) iScale=1;
	    POINT WhiteWing [17]  = {
		  { (long)(-228  * fFact ) , (long)(13  * fFact)}, //1
		  { (long) (-221 * fFact ) , (long)(-5  * fFact)}, //2
		  { (long) (-102 * fFact ) , (long)(-50 * fFact)}, //3
		  { (long) (8	 * fFact ) , (long)( 5  * fFact)}, //4
		  { (long) (149  * fFact ) , (long)(-55 * fFact)}, //5
		  { (long) (270  * fFact ) , (long)(-12 * fFact)}, //6
		  { (long) (280  * fFact ) , (long)( 5  * fFact)}, //7
		  { (long) (152  * fFact ) , (long)(-30 * fFact)}, //8
		  { (long) (48	 * fFact ) , (long)( 27 * fFact)}, //9
		  { (long) (37	 * fFact ) , (long)( 44 * fFact)}, //10
		  { (long)(-20	 * fFact ) , (long)( 65 * fFact)}, //11
		  { (long)(-29	 * fFact ) , (long)( 80 * fFact)}, //12
		  { (long)(-56	 * fFact ) , (long)( 83 * fFact)}, //13
		  { (long)(-50	 * fFact ) , (long)( 40 * fFact)}, //14
		  { (long)(-30	 * fFact ) , (long)( 27 * fFact)}, //15
		  { (long)(-103  * fFact ) , (long)(-26 * fFact)}, //16
		  { (long)(-228  * fFact ) , (long)( 13 * fFact)}  //17
	    };

	    if (picto)
	       threadsafePolygonRotateShift(WhiteWing, 17,  Center.x, Center.y,  0/*+ wp->RunwayDir-Brg*/);
	    else
	       PolygonRotateShift(WhiteWing, 17,  Center.x, Center.y,  0/*+ wp->RunwayDir-Brg*/);

	    Surface.Polygon(WhiteWing ,17 );
    }
  }

  // StartupStore(_T(".......fscale=%f *1600=%f realscale = %f\n"), fScaleFact, fScaleFact*1600, MapWindow::zoom.RealScale());


  if( !picto && (MapWindow::zoom.RealScale() <= scale_drawradio)  )
  {

	const auto hfOld = Surface.SelectObject(MapWindow::zoom.RealScale() <= scale_bigfont
                                                ? LK8PanelUnitFont
                                                : LK8GenericVar02Font);
        #ifndef DITHER
	if (INVERTCOLORS)
		Surface.SelectObject(LKBrush_Petrol);
	else
		Surface.SelectObject(LKBrush_LightCyan);
        #else
	if (INVERTCOLORS)
		Surface.SelectObject(LKBrush_Black);
	else
		Surface.SelectObject(LKBrush_White);
        #endif

	unsigned int offset = p + NIBLSCALE(1) ;
	{
		if ( _tcslen(wp->Freq)>0 ) {
			MapWindow::LKWriteBoxedText(Surface,rc,wp->Freq, Center.x- offset, Center.y -offset, WTALIGN_RIGHT, RGB_WHITE, RGB_BLACK);
		}

		//
		// Full infos! 1.5km scale
		//
		if (MapWindow::zoom.RealScale() <=scale_fullinfos) {
			if ( _tcslen(wp->Code)==4 ) {
				MapWindow::LKWriteBoxedText(Surface,rc,wp->Code,Center.x + offset, Center.y - offset, WTALIGN_LEFT, RGB_WHITE,RGB_BLACK);
			}

			if (wp->Altitude >0) {
				TCHAR tAlt[20];
				_stprintf(tAlt,_T("%.0f %s"),wp->Altitude*ALTITUDEMODIFY,Units::GetUnitName(Units::GetUserAltitudeUnit()));
				MapWindow::LKWriteBoxedText(Surface,rc,tAlt, Center.x + offset, Center.y + offset, WTALIGN_LEFT, RGB_WHITE, RGB_BLACK);
			}

		}
	}
	Surface.SelectObject(hfOld);

  }



  Surface.SelectObject(oldPen);
  Surface.SelectObject(oldBrush);

}
예제 #6
0
// draw aircraft
void RenderPlaneSideview(LKSurface& Surface, double fDist, double fAltitude,double brg, DiagrammStruct* psDia )
{
//BOOL bInvCol = true ; //INVERTCOLORS
  #define NO_AP_PTS 17
  int deg = DEG_TO_INT(AngleLimit360(brg));
  double fCos = COSTABLE[deg];
  double fSin = SINETABLE[deg];

  int TAIL   = 6;
  int PROFIL = 1;
  int FINB   = 3;
  int BODY   = 2;
  int NOSE   = 7;
  int WING   = (int) (22.0 );
  int TUBE   = (int) (14.0  ) ;
  int FINH   = 6+BODY;

  POINT Start;
  int HEAD = TUBE / 2;
  TUBE =  3 * TUBE/ 2;
  POINT AircraftSide
  [8] = {
      {(int)(fSin * (HEAD+0   )    ), -BODY-1},  // 1
      {(int)(fSin * (HEAD+NOSE)    ),  0},       // 2
      {(int)(fSin * (HEAD+0   )    ),  BODY+1},  // 3
      {(int)(fSin * (-TUBE)        ),  BODY},    // 4   -1
      {(int)(fSin * -TUBE          ), -FINH},    // 5
      {(int)(fSin * (-TUBE+FINB)   ), -FINH},    // 6
      {(int)(fSin * (-TUBE+FINB+3) ), -BODY+1},  // 7  +1
      {(int)(fSin * (HEAD+0)       ), -BODY-1}     // 8
  };

  #define  FACT 2

  BODY = (int)((double)(BODY+1) * fCos * fCos);

  int DIA = (BODY + PROFIL);

  /* both wings */
  POINT AircraftWing
  [13] = {
      {(int)(fCos * BODY              ) ,  -DIA},    // 1
      {(int)(fCos * (int)( FACT*BODY) ), -PROFIL},    // 2
      {(int)(fCos * WING              ) ,  -PROFIL},    // 3
      {(int)(fCos * WING              ), 0* PROFIL},    // 4
      {(int)(fCos * (int)( FACT*BODY) ) , PROFIL},    // 5
      {(int)(fCos *  BODY             ), DIA},    // 6
      {(int)(fCos * -BODY             ) , DIA},    // 7
      {(int)(fCos * (int)( -FACT*BODY)), PROFIL},    // 8
      {(int)(fCos * -WING             ), 0* PROFIL  },    // 9
      {(int)(fCos * -WING             ) , -PROFIL}  ,    // 10
      {(int)(fCos * (int)( -FACT*BODY)), -PROFIL},    // 11
      {(int)(fCos * -BODY             ) , -DIA},    // 12
      {(int)(fCos *  BODY             ), -DIA}    // 13
  };


  POINT AircraftWingL
  [7] = {

      {(int)(0 * -BODY                ),  DIA       },    // 1
      {(int)(fCos * (int)( -FACT*BODY)),  PROFIL    },    // 2
      {(int)(fCos * -WING             ),  0* PROFIL },    // 3
      {(int)(fCos * -WING             ), -PROFIL    },    // 4
      {(int)(fCos * (int)( -FACT*BODY)), -PROFIL    },    // 5
      {(int)(0 * -BODY                ), -DIA       },    // 6
      {(int)(0 * -BODY                ),  DIA       }     // 7
  };


  POINT AircraftWingR
  [7] = {
      {(int)(0 * BODY                 ) ,  -DIA    },   // 1
      {(int)(fCos * (int)( FACT*BODY) ) , -PROFIL  },   // 2
      {(int)(fCos * WING              ) ,  -PROFIL },   // 3
      {(int)(fCos * WING              ) , 0* PROFIL},   // 4
      {(int)(fCos * (int)( FACT*BODY) ) , PROFIL   },   // 5
      {(int)(0 *  BODY                ) , DIA      },   // 6
      {(int)(0 *  BODY                ) , -DIA     }    // 7
  };



  POINT AircraftTail
  [5] = {
      {(int)(fCos *  TAIL - fSin*TUBE), -FINH},            // 1
      {(int)(fCos *  TAIL - fSin*TUBE), -FINH +PROFIL},    // 2
      {(int)(fCos * -TAIL - fSin*TUBE), -FINH +PROFIL},    // 3
      {(int)(fCos * -TAIL - fSin*TUBE), -FINH },           // 4
      {(int)(fCos *  TAIL - fSin*TUBE), -FINH},            // 5

  };

  Start.x = CalcDistanceCoordinat(fDist,  psDia);
  Start.y = CalcHeightCoordinat(fAltitude, psDia);

  const auto oldPen = Surface.SelectObject(LK_BLACK_PEN);
  const auto oldBrush = Surface.SelectObject(LKBrush_White);

  PolygonRotateShift(AircraftWing, 13,  Start.x, Start.y,  0);
  PolygonRotateShift(AircraftSide, 8,   Start.x, Start.y,  0);
  PolygonRotateShift(AircraftTail, 5,   Start.x, Start.y,  0);
  PolygonRotateShift(AircraftWingL, 7,   Start.x, Start.y,  0);
  PolygonRotateShift(AircraftWingR, 7,   Start.x, Start.y,  0);

  #ifndef UNDITHER
  LKBrush GreenBrush(RGB_GREEN);
  LKBrush RedBrush(RGB_RED);
  #else
  LKBrush GreenBrush(RGB_WHITE);
  LKBrush RedBrush(RGB_BLACK);
  #endif
  if((brg < 180))
  {
    Surface.SelectObject(RedBrush);
    Surface.Polygon(AircraftWingL ,7 );

    Surface.SelectObject(LKBrush_White);
    Surface.Polygon(AircraftSide  ,8 );

    Surface.SelectObject(GreenBrush);
    Surface.Polygon(AircraftWingR ,7 );

    Surface.SelectObject(oldBrush);
  }
  else
  {
    Surface.SelectObject(GreenBrush);
    Surface.Polygon(AircraftWingR ,7 );

    Surface.SelectObject(LKBrush_White);
    Surface.Polygon(AircraftSide  ,8 );

    Surface.SelectObject(RedBrush);
    Surface.Polygon(AircraftWingL ,7 );

    Surface.SelectObject(oldBrush);
  }
  if((brg < 90)|| (brg > 270)) {
    Surface.Polygon(AircraftTail  ,5 );
  }

  Surface.SelectObject(oldPen);
  Surface.SelectObject(oldBrush);
} //else !asp_heading_task
예제 #7
0
int RenderFAISector (LKSurface& Surface, const RECT& rc , double lat1, double lon1, double lat2, double lon2, int iOpposite , const LKColor& fillcolor)
{

POINT Pt1;
float fFAI_Percentage = FAI_NORMAL_PERCENTAGE;
double fDist_a, fDist_b, fDist_c, fAngle;
int i;

int iPolyPtr=0;
double lat_d,lon_d;
double alpha, fDistTri, cos_alpha=0;
POINT apSectorPolygon[MAX_FAI_SECTOR_PTS+1];
DistanceBearing(lat1, lon1, lat2, lon2, &fDist_c, &fAngle);

if(fabs(fDist_c) < 1000.0)  /* distance too short for a FAI sector */
	return -1;


double fDistMax = fDist_c/FAI_NORMAL_PERCENTAGE;
double fDistMin = fDist_c/(1.0-2.0*FAI28_45Threshold);
double fDelta_Dist = 2.0* fDist_c*fFAI_Percentage / (double)(FAI_SECTOR_STEPS-1);
double fA, fB;
double fMinLeg, fMaxLeg,fDiff=0;
double dir = -1.0;
BOOL bBigFAISector = false;

if(fDistMax > FAI28_45Threshold)
{
  bBigFAISector = true;
  fDistMax = fDist_c/FAI_BIG_PERCENTAGE;
}

if(fDistMin < FAI28_45Threshold)
{
  fDistMin = fDist_c/(1.0-2.0*FAI_NORMAL_PERCENTAGE);
}


if (iOpposite >0)
{
  dir = 1.0;
}

//#define  HELP_LINES
#ifdef HELP_LINES
  int x2,y2, style;
  FindLatitudeLongitude(lat1, lon1, AngleLimit360 (fAngle), fDist_c/2, &lat_d, &lon_d);
  x1 = (lon_d - lon_c)*fastcosine(lat_d);
  y1 = (lat_d - lat_c);
  FindLatitudeLongitude(lat_d, lon_d, AngleLimit360 (fAngle-90.0), fDist_c, &lat_d, &lon_d);
  x2 = (lon_d - lon_c)*fastcosine(lat_d);
  y2 = (lat_d - lat_c);
  Surface.DrawLine(rc, x1, y1, x2, y2, style);
#endif

  /********************************************************************
   * right below threshold 1
   ********************************************************************/
  fA = 	fDistMin;
  if(fDistMax > FAI28_45Threshold)
    fB = FAI28_45Threshold;
  else
	fB = fDistMax ;


  if(fA<fB)
  {
	fDelta_Dist =(fB-fA)/ (double)(FAI_SECTOR_STEPS-1);
	fDistTri = fA;
    for(i =0 ;i < FAI_SECTOR_STEPS; i++)
    {
	  fDist_a = FAI_NORMAL_PERCENTAGE * fDistTri;
	  fDist_b = fDistTri - fDist_a - fDist_c;

	  LKASSERT(fDist_c*fDist_b!=0);
	  cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	  alpha = acos(cos_alpha)*180/PI * dir;
	  FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);

	  MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
	  LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS);
	  apSectorPolygon[iPolyPtr++] = Pt1;


      fDistTri += fDelta_Dist;
    }
  }

  /********************************************************************
   * right  threshold extender 2
   ********************************************************************/
if(fDistMin < FAI28_45Threshold)
  if(bBigFAISector && (fDistMin < FAI28_45Threshold))
  {
	fMaxLeg = FAI28_45Threshold*FAI_BIG_MAX_PERCENTAGE;
	fMinLeg = FAI28_45Threshold*FAI_BIG_PERCENTAGE;
	fA = FAI28_45Threshold*FAI_NORMAL_PERCENTAGE;
	fB = FAI28_45Threshold-fMaxLeg-fDist_c;

	if(fB < fMinLeg)
	  fB = fMinLeg;

	fDist_a = fA;
	fDelta_Dist =  (fB-fA) / (double)(FAI_SECTOR_STEPS-1);
    for(i =0 ;i < FAI_SECTOR_STEPS; i++)
    {
	  fDist_b = FAI28_45Threshold - fDist_a - fDist_c;
  	  LKASSERT(fDist_c*fDist_b!=0);
	  cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	  alpha = acos(cos_alpha)*180/PI * dir;
	  FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);
	  MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
	  LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS);
	  apSectorPolygon[iPolyPtr++] = Pt1;

	  fDist_a += fDelta_Dist;
    }
  }
  /********************************************************************
   * right  above threshold  3
   ********************************************************************/
  if(bBigFAISector)
  {
    fA = 	FAI28_45Threshold;
    if(fDistMin > fA)
	  fA= fDistMin;
    fB =fDist_c/(1- FAI_BIG_PERCENTAGE-FAI_BIG_MAX_PERCENTAGE);

    if(fA < fB)
    {
      fDelta_Dist =(fB-fA)/ (double)(FAI_SECTOR_STEPS-1);
      fDistTri = fA;
      for(i =0 ;i < FAI_SECTOR_STEPS; i++)
      {
  	    fMaxLeg = fDistTri*FAI_BIG_MAX_PERCENTAGE;
	    fMinLeg = fDistTri*FAI_BIG_PERCENTAGE;
	    fDist_a = fDistTri-fMinLeg-fDist_c;;
	    fDist_b = fMinLeg;

	    if(fDist_a > fMaxLeg)
	    {
	      fDiff =  fDist_a - fMaxLeg;
	      fDist_b+=fDiff;
	      fDist_a-=fDiff;
	    }

	    LKASSERT(fDist_c*fDist_b!=0);
	    cos_alpha = ( fDist_a*fDist_a + fDist_c*fDist_c - fDist_b*fDist_b )/(2.0*fDist_c*fDist_a);
	    alpha = acos(cos_alpha)*180/PI * dir;
	    FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_a, &lat_d, &lon_d);
		MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
		LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS);
	    apSectorPolygon[iPolyPtr++] = Pt1;


	    fDistTri += fDelta_Dist;
      }
    }
  }
/********************************************************************
 * TOP limited round 4
 ********************************************************************/
  if(fDistMax <= FAI28_45Threshold)
	fDist_b = fDistMax*(1.0-2*FAI_NORMAL_PERCENTAGE);
  else
	fDist_b = fDistMax*FAI_BIG_MAX_PERCENTAGE;

  fDist_a = fDistMax-fDist_b-fDist_c;
  fDelta_Dist =  (fDist_a-fDist_b) / (double)(FAI_SECTOR_STEPS-1);
  for(i =0 ;i < FAI_SECTOR_STEPS; i++)
  {
	LKASSERT(fDist_c*fDist_b!=0);
	cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	alpha = acos(cos_alpha)*180/PI * dir;
	FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);

	MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
	LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS);
    apSectorPolygon[iPolyPtr++] = Pt1;


    fDist_a -= fDelta_Dist;
    fDist_b += fDelta_Dist;
  }

/********************************************************************
 * calc left leg
 ********************************************************************/

/********************************************************************
 * LEFT above threshold 5
 ********************************************************************/
  if(bBigFAISector)
  {
    fB = FAI28_45Threshold;
    if( fB < fDistMin)
	  fB = fDistMin;

    fA =fDist_c/(1- FAI_BIG_PERCENTAGE-FAI_BIG_MAX_PERCENTAGE);

    if(fA >= fB)
    {
      fDelta_Dist =(fA-fB)/ (double)(FAI_SECTOR_STEPS-1);
      fDistTri = fA;
      for(i =0 ;i < FAI_SECTOR_STEPS; i++)
      {
	    fMaxLeg = fDistTri*FAI_BIG_MAX_PERCENTAGE;
	    fMinLeg = fDistTri*FAI_BIG_PERCENTAGE;
	    fDist_a = fDistTri-fMinLeg-fDist_c;
	    fDist_b = fMinLeg;

	    if(fDist_a > fMaxLeg)
	    {
	      fDiff =  fDist_a - fMaxLeg;
	      fDist_b+=fDiff;
	      fDist_a-=fDiff;
  	    }

	    LKASSERT(fDist_c*fDist_b!=0);
	    cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	    alpha = acos(cos_alpha)*180/PI * dir;
	    FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);
		MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
		LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS);
	    apSectorPolygon[iPolyPtr++] = Pt1;


	    fDistTri -= fDelta_Dist;
     }
    }
  }

  /********************************************************************
   * LEFT threshold extender 6
   ********************************************************************/
if(fDistMin < FAI28_45Threshold)
  if((fDistMin < FAI28_45Threshold) && (FAI28_45Threshold < fDistMax))
  {
	fMaxLeg = FAI28_45Threshold*FAI_BIG_MAX_PERCENTAGE;
	fMinLeg = FAI28_45Threshold*FAI_BIG_PERCENTAGE;
	fA = FAI28_45Threshold*FAI_NORMAL_PERCENTAGE;
	fB = FAI28_45Threshold-fMaxLeg-fDist_c;

	if(fB < fMinLeg)
	  fB = fMinLeg;

	fDist_b = fB;
	fDelta_Dist =  (fA-fB) / (double)(FAI_SECTOR_STEPS-1);

    for(i =0 ;i < FAI_SECTOR_STEPS; i++)
    {
	  fDist_a = FAI28_45Threshold - fDist_b - fDist_c;
	  LKASSERT(fDist_c*fDist_b!=0);
	  cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	  alpha = acos(cos_alpha)*180/PI * dir;
	  FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);
	  MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
	  LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS);
	  apSectorPolygon[iPolyPtr++] = Pt1;

	  fDist_b += fDelta_Dist;
    }
  }


  /********************************************************************
   * LEFT below threshold 7
   ********************************************************************/
  fA = 	fDistMin;
  if(fDistMax > FAI28_45Threshold)
    fB = FAI28_45Threshold;
  else
	fB = fDistMax ;

  if(fA<fB)
  {
	fDelta_Dist =(fB-fA)/ (double)(FAI_SECTOR_STEPS-1);
	fDistTri = fB;
    for(i =0 ;i < FAI_SECTOR_STEPS; i++)
    {
	  fDist_b = FAI_NORMAL_PERCENTAGE * fDistTri;
	  fDist_a = fDistTri - fDist_b - fDist_c;

	  LKASSERT(fDist_c*fDist_b!=0);
	  cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	  alpha = acos(cos_alpha)*180/PI * dir;
	  FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);
	  MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
	  LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS);
	  apSectorPolygon[iPolyPtr++] = Pt1;
      fDistTri -= fDelta_Dist;
    }
  }

  /********************************************************************
   * low open PEAK round 8
   ********************************************************************/
  if(fDistMin >FAI28_45Threshold)
  {
	fDist_b = fDistMin*FAI_BIG_PERCENTAGE;
	fDist_a = fDistMin-fDist_b-fDist_c;
	fDelta_Dist =  (fDist_b-fDist_a) / (double)(FAI_SECTOR_STEPS-1);

	for(i =0 ;i < FAI_SECTOR_STEPS; i++)
	{
		LKASSERT(fDist_c*fDist_b!=0);
		cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
		alpha = acos(cos_alpha)*180/PI * dir;
		FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);
		MapWindow::LatLon2Screen(lon_d, lat_d,  Pt1);
		LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS);
	    apSectorPolygon[iPolyPtr++] = Pt1;

	    fDist_a += fDelta_Dist;
	    fDist_b -= fDelta_Dist;
	}
  }

  /********************************************************************
   * draw polygon
   ********************************************************************/
  LKPen   hpSectorPen(PEN_SOLID, IBLSCALE(2),  fillcolor );

  LKPen hpOldPen = Surface.SelectObject(hpSectorPen);
  LKBrush hpOldBrush = Surface.SelectObject(LKBrush_Hollow);

  Surface.Polygon(apSectorPolygon,iPolyPtr,rc);

  Surface.SelectObject(hpOldPen);
  Surface.SelectObject(hpOldBrush);
  hpSectorPen.Release();

  /********************************************************************
   * calc round leg grid
   ********************************************************************/
  hpSectorPen.Create(PEN_SOLID, (1), RGB_BLACK );
  Surface.SelectObject(hpSectorPen);
  Surface.SetTextColor(RGB_BLACK);
  double fTic= 1/DISTANCEMODIFY;
  if(fDist_c > 5/DISTANCEMODIFY)   fTic = 10/DISTANCEMODIFY;
  if(fDist_c > 50/DISTANCEMODIFY)  fTic = 25/DISTANCEMODIFY;
  if(fDist_c > 100/DISTANCEMODIFY) fTic = 50/DISTANCEMODIFY;
//  if(fDist_c > 200/DISTANCEMODIFY) fTic = 100/DISTANCEMODIFY;
  if(fDist_c > 500/DISTANCEMODIFY) fTic = 250/DISTANCEMODIFY;
  POINT line[2];
  BOOL bFirstUnit = true;
  LKASSERT(fTic!=0);
  fDistTri = ((int)(fDistMin/fTic)+1) * fTic ;
  LKFont hfOld = Surface.SelectObject(LK8PanelUnitFont);

int iCnt = 0;

  while(fDistTri <= fDistMax)
  {
    TCHAR text[180]; SIZE tsize;
	if(bFirstUnit)
	  _stprintf(text, TEXT("%i%s"), (int)(fDistTri*DISTANCEMODIFY), Units::GetUnitName(Units::GetUserDistanceUnit()));
	else
	  _stprintf(text, TEXT("%i"), (int)(fDistTri*DISTANCEMODIFY));
	bFirstUnit = false;
	Surface.GetTextSize(text, _tcslen(text), &tsize);

    int j=0;

	if(fDistTri < FAI28_45Threshold)
	{
	  fDist_b = fDistTri*FAI_NORMAL_PERCENTAGE;
	  fDist_a = fDistTri-fDist_b-fDist_c;
	  fDelta_Dist =  (fDist_a-fDist_b) / (double)(FAI_SECTOR_STEPS-1);
	}
	else
	{
      fMaxLeg = fDistTri*FAI_BIG_MAX_PERCENTAGE;
      fMinLeg = fDistTri*FAI_BIG_PERCENTAGE;
	  fA = fMaxLeg;
	  fB = fDistTri-fA-fDist_c;
	  fDist_a = fA;
	  fDist_b = fB;
	  if(fB < fMinLeg)
	  {
		  fDiff = fMinLeg-fB;
		  fB+=2*fDiff;
		  fDist_b += fDiff;
		  fDist_a -= fDiff;
	  }
	  if(fB > fMaxLeg)
	  {
		  fDiff =  fB - fMaxLeg;
		  fB+=2*fDiff;
		  fDist_b-=fDiff;
		  fDist_a+=fDiff;
	  }
	  fFAI_Percentage =  FAI_BIG_PERCENTAGE;
	  fDelta_Dist =  (fA-fB) / (double)(FAI_SECTOR_STEPS-1);
	}


    for(i =0 ;i < FAI_SECTOR_STEPS; i++)
    {
	  LKASSERT(fDist_c*fDist_b!=0);
	  cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b);
	  alpha = acos(cos_alpha)*180/PI * dir;
	  FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d);
	  MapWindow::LatLon2Screen(lon_d, lat_d,  line[0]);

      if(j> 0)
      {
  		ForcedClipping=true;
  		Surface.DrawLine(PEN_DASH, NIBLSCALE(1), line[0] , line[1] , RGB_BLACK, rc);
  		ForcedClipping=false;
      }


      if(j==0)
      {
    	Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text));
    	j=1;

      }

//      TCHAR text[180]; SIZE tsize;
      if(iCnt==0)
        _stprintf(text, TEXT("%i%s"), (int)(fDistTri*DISTANCEMODIFY), Units::GetUnitName(Units::GetUserDistanceUnit()));
      else
        _stprintf(text, TEXT("%i"), (int)(fDistTri*DISTANCEMODIFY));
      Surface.GetTextSize(text, _tcslen(text), &tsize);
      if(i == 0)
        Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text));

      if(iCnt > 1)
  	    if(i == FAI_SECTOR_STEPS-1)
  	      Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text));

      if(iCnt > 2)
  	    if((i== (FAI_SECTOR_STEPS/2)))
  	      Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text));

      line[1] =  line[0];



	  fDist_a -= fDelta_Dist;
	  fDist_b += fDelta_Dist;
    }
    fDistTri+=fTic;iCnt++;
 //   if((iCnt %2) ==0)
  //    DrawText(hdc, line[0].x, line[0].y, ETO_OPAQUE, NULL, text, _tcslen(text), NULL);
  }

Surface.SelectObject(hfOld);
Surface.SelectObject(hpOldPen);

return 0;
}
예제 #8
0
void MapWindow::DrawWindAtAircraft2(LKSurface& Surface, const POINT& Orig, const RECT& rc) {
  int i;
  POINT Start;
  TCHAR sTmp[12];
  static SIZE tsize = {0,0};
  
  if (DerivedDrawInfo.WindSpeed<1) {
    return; // JMW don't bother drawing it if not significant
  }
  
  if (tsize.cx == 0){

    const auto oldFont = Surface.SelectObject(MapWindowBoldFont);
    Surface.GetTextSize(TEXT("99"), 2, &tsize);
    Surface.SelectObject(oldFont);
    tsize.cx = tsize.cx/2;
  }

  int wmag = iround(4.0*DerivedDrawInfo.WindSpeed);
  
  Start.y = Orig.y;
  Start.x = Orig.x;

  int kx = tsize.cx/ScreenScale/2;

  POINT Arrow[7] = { {0,-20}, {-6,-26}, {0,-20}, 
                     {6,-26}, {0,-20}, 
                     {8+kx, -24}, 
                     {-8-kx, -24}};

  for (i=1;i<4;i++)
    Arrow[i].y -= wmag;

  PolygonRotateShift(Arrow, 7, Start.x, Start.y, 
		     DerivedDrawInfo.WindBearing-DisplayAngle);

  //
  // Draw Wind Arrow
  //
  POINT Tail[2] = {{0,-20}, {0,-26-min(20,wmag)*3}};
  double angle = AngleLimit360(DerivedDrawInfo.WindBearing-DisplayAngle);
  for(i=0; i<2; i++) {
    if (ScreenScale>1) {
      Tail[i].x *= ScreenScale;
      Tail[i].y *= ScreenScale;
    }
    protateshift(Tail[i], angle, Start.x, Start.y);
  }
  // optionally draw dashed line for wind arrow
  Surface.DrawLine(PEN_DASH, 1, Tail[0], Tail[1], LKColor(0,0,0), rc);

  // Paint wind value only while circling
  if ( (mode.Is(Mode::MODE_CIRCLING)) ) {

    _stprintf(sTmp, _T("%d"), iround(DerivedDrawInfo.WindSpeed * SPEEDMODIFY));

    TextInBoxMode_t TextInBoxMode = {0};
    TextInBoxMode.AlligneCenter = true;   // { 16 | 32 }; // JMW test {2 | 16};
    TextInBoxMode.WhiteBorder = true;
    if (Arrow[5].y>=Arrow[6].y) {
      TextInBox(Surface, &rc, sTmp, Arrow[5].x-kx, Arrow[5].y, 0, &TextInBoxMode);
    } else {
      TextInBox(Surface, &rc, sTmp, Arrow[6].x-kx, Arrow[6].y, 0, &TextInBoxMode);
    }
  }
  const auto hpOld = Surface.SelectObject(LKPen_Black_N2);
  const auto hbOld = Surface.SelectObject(LKBrush_Grey);
  Surface.Polygon(Arrow,5);

  Surface.SelectObject(hbOld);
  Surface.SelectObject(hpOld);
}
예제 #9
0
void RenderAirspaceTerrain(LKSurface& Surface, double PosLat, double PosLon, double brg, DiagrammStruct* psDiag) {
    RECT rc = psDiag->rc;
    //rc.bottom +=BORDER_Y;
    double range = psDiag->fXMax - psDiag->fXMin; // km
    double hmax = psDiag->fYMax;
    double lat, lon;
    int i, j;

    if (!IsDithered() && IsMultimapTerrain()) {
        RenderSky(Surface, rc, SKY_HORIZON_COL, SKY_SPACE_COL, GC_NO_COLOR_STEPS);
    } else {
        Surface.FillRect(&rc, MapWindow::hInvBackgroundBrush[BgMapColor]);
    }
    FindLatitudeLongitude(PosLat, PosLon, brg, psDiag->fXMin, &lat, &lon);
    POINT apTerrainPolygon[AIRSPACE_SCANSIZE_X + 4] = {};
    double d_lat[AIRSPACE_SCANSIZE_X] = {};
    double d_lon[AIRSPACE_SCANSIZE_X] = {};
    double d_h[AIRSPACE_SCANSIZE_X] = {};

#define   FRAMEWIDTH 2
    RasterTerrain::Lock(); // want most accurate rounding here
    RasterTerrain::SetTerrainRounding(0, 0);
    double fj;
    for (j = 0; j < AIRSPACE_SCANSIZE_X; j++) { // scan range
        fj = (double) j * 1.0 / (double) (AIRSPACE_SCANSIZE_X - 1);
        FindLatitudeLongitude(lat, lon, brg, range*fj, &d_lat[j], &d_lon[j]);
        d_h[j] = RasterTerrain::GetTerrainHeight(d_lat[j], d_lon[j]);
        if (d_h[j] == TERRAIN_INVALID) d_h[j] = 0; //@ 101027 BUGFIX
        hmax = max(hmax, d_h[j]);
    }

    RasterTerrain::Unlock();


    /********************************************************************************
     * scan line
     ********************************************************************************/
    if (IsMultimapAirspace())
        Sideview_iNoHandeldSpaces = CAirspaceManager::Instance().ScanAirspaceLineList(d_lat, d_lon, d_h, Sideview_pHandeled, MAX_NO_SIDE_AS); //  Sideview_pHandeled[GC_MAX_NO];
    else
        Sideview_iNoHandeldSpaces = 0;
#if BUGSTOP
    LKASSERT(Sideview_iNoHandeldSpaces < MAX_NO_SIDE_AS);
#endif
    if (Sideview_iNoHandeldSpaces >= MAX_NO_SIDE_AS) Sideview_iNoHandeldSpaces = MAX_NO_SIDE_AS - 1;

    /********************************************************************************
     * bubble sort to start with biggest airspaces
     ********************************************************************************/
    int iSizeLookupTable[MAX_NO_SIDE_AS];
    for (i = 0; i < Sideview_iNoHandeldSpaces; i++)
        iSizeLookupTable[i] = i;

    for (i = 0; i < Sideview_iNoHandeldSpaces; i++) {
#if BUGSTOP
        LKASSERT(iSizeLookupTable[i] < MAX_NO_SIDE_AS);
#endif
        for (j = i; j < Sideview_iNoHandeldSpaces; j++) {
#if BUGSTOP
            LKASSERT(iSizeLookupTable[j] < MAX_NO_SIDE_AS);
#endif
            if (iSizeLookupTable[i] >= MAX_NO_SIDE_AS) continue;
            if (iSizeLookupTable[j] >= MAX_NO_SIDE_AS) continue;

            if (Sideview_pHandeled[iSizeLookupTable[i]].iAreaSize < Sideview_pHandeled[iSizeLookupTable[j]].iAreaSize) {
                int iTmp = iSizeLookupTable[i];
                iSizeLookupTable[i] = iSizeLookupTable[j];
                iSizeLookupTable[j] = iTmp;
            }
        }
    }
    /**********************************************************************************
     * transform into diagram coordinates
     **********************************************************************************/
    double dx1 = (double) (rc.right) / (double) (AIRSPACE_SCANSIZE_X - 1);
    int x0 = rc.left;
    LKASSERT(Sideview_iNoHandeldSpaces < MAX_NO_SIDE_AS);
    for (i = 0; i < Sideview_iNoHandeldSpaces; i++) {
        Sideview_pHandeled[i].rc.left = (long) ((Sideview_pHandeled[i].rc.left) * dx1) + x0 - FRAMEWIDTH / 2;
        Sideview_pHandeled[i].rc.right = (long) ((Sideview_pHandeled[i].rc.right) * dx1) + x0 + FRAMEWIDTH / 2;

        Sideview_pHandeled[i].rc.bottom = CalcHeightCoordinat((double) Sideview_pHandeled[i].rc.bottom, psDiag) + FRAMEWIDTH / 2;
        Sideview_pHandeled[i].rc.top = CalcHeightCoordinat((double) Sideview_pHandeled[i].rc.top, psDiag) - FRAMEWIDTH / 2;

        Sideview_pHandeled[i].iMaxBase = Sideview_pHandeled[i].rc.bottom;
        Sideview_pHandeled[i].iMinTop = Sideview_pHandeled[i].rc.top;

        int iN = Sideview_pHandeled[i].iNoPolyPts;
#if BUGSTOP
        LKASSERT(iN < GC_MAX_POLYGON_PTS);
#endif
        if (iN >= GC_MAX_POLYGON_PTS) iN = GC_MAX_POLYGON_PTS - 1;

        if (Sideview_pHandeled[i].bRectAllowed == false) {
            for (j = 0; j < iN; j++) {
                Sideview_pHandeled[i].apPolygon[j].x = (long) (((Sideview_pHandeled[i].apPolygon[j].x) * dx1) + x0);
                Sideview_pHandeled[i].apPolygon[j].y = CalcHeightCoordinat((double) Sideview_pHandeled[i].apPolygon[j].y, psDiag);
                if (j != iN - 1) {
                    if ((j < iN / 2)) {
                        Sideview_pHandeled[i].iMaxBase = min((long) Sideview_pHandeled[i].iMaxBase, (long) Sideview_pHandeled[i].apPolygon[j].y);
                    } else {
                        Sideview_pHandeled[i].iMinTop = max((long) Sideview_pHandeled[i].iMinTop, (long) Sideview_pHandeled[i].apPolygon[j].y);
                    }
                }
            }
        }
    }
    /**********************************************************************************
     * draw airspaces
     **********************************************************************************/
    const auto oldpen = Surface.SelectObject(LK_NULL_PEN);
    _TCHAR text [80];
    LKASSERT(Sideview_iNoHandeldSpaces < MAX_NO_SIDE_AS);
    for (int m = 0; m < Sideview_iNoHandeldSpaces; m++) {
        int iSizeIdx = iSizeLookupTable[m];
#if BUGSTOP
        LKASSERT(iSizeIdx < MAX_NO_SIDE_AS && iSizeIdx >= 0);
#endif
        if (iSizeIdx >= MAX_NO_SIDE_AS) iSizeIdx = MAX_NO_SIDE_AS - 1;

        int type = Sideview_pHandeled[iSizeIdx].iType;
        RECT rcd = Sideview_pHandeled[iSizeIdx].rc;
        LKColor FrameColor;
        double fFrameColFact;
        if (Sideview_pHandeled[iSizeIdx].bEnabled) {
            Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(type));
            Surface.SetTextColor(MapWindow::GetAirspaceColourByClass(type));
            fFrameColFact = 0.8;
            FrameColor = MapWindow::GetAirspaceColourByClass(type);
        } else {
            Surface.SelectObject(LKBrush_Hollow);
            Surface.SetTextColor(RGB_GGREY);
            FrameColor = RGB_GGREY;
            fFrameColFact = 1.2;
        }
        if (INVERTCOLORS)
            fFrameColFact *= 0.8;
        else
            fFrameColFact *= 1.2;
        LKColor Color = FrameColor.ChangeBrightness(fFrameColFact);
        LKPen mpen2(PEN_SOLID, FRAMEWIDTH, Color);
        const auto oldpen2 = Surface.SelectObject(mpen2);

        if (Sideview_pHandeled[iSizeIdx].bRectAllowed == true)
            Surface.Rectangle(rcd.left + 1, rcd.top, rcd.right, rcd.bottom);
        else
            Surface.Polygon(Sideview_pHandeled[iSizeIdx].apPolygon, Sideview_pHandeled[iSizeIdx].iNoPolyPts);

        Surface.SelectObject(oldpen2);

        if (Sideview_pHandeled[iSizeIdx].bEnabled)
            Surface.SetTextColor(Sideview_TextColor); // RGB_MENUTITLEFG
        else
            Surface.SetTextColor(RGB_GGREY);

        /***********************************************
         * build view overlap for centering text
         ***********************************************/
        rcd.bottom = min(rcd.bottom, Sideview_pHandeled[iSizeIdx].iMaxBase);
        rcd.top = max(rcd.top, Sideview_pHandeled[iSizeIdx].iMinTop);

        rcd.left = max(rcd.left, rc.left);
        rcd.right = min(rcd.right, rc.right);
        rcd.bottom = min(rcd.bottom, rc.bottom);
        rcd.top = max(rcd.top, rc.top);
        SIZE textsize;
        SIZE aispacesize = {rcd.right - rcd.left, rcd.bottom - rcd.top};

        LK_tcsncpy(text, Sideview_pHandeled[iSizeIdx].szAS_Name, NAME_SIZE - 1/* sizeof(text)/sizeof(text[0])*/);
        Surface.GetTextSize(text, &textsize);

        int x = rcd.left + aispacesize.cx / 2;
        ;
        int y = rcd.top + aispacesize.cy / 2;
        //  int iTextheight =  tsize.cy;
        int iOffset = 0;
        BOOL blongtext = false;
        if (aispacesize.cy > (2 * textsize.cy) && (textsize.cx < aispacesize.cx)) {
            iOffset = textsize.cy / 2;
        }


        if ((textsize.cx < aispacesize.cx) && (textsize.cy < aispacesize.cy)) {
            Surface.DrawText(x - textsize.cx / 2, y - iOffset - textsize.cy / 2, text);
            blongtext = true;
        }

        LK_tcsncpy(text, CAirspaceManager::Instance().GetAirspaceTypeShortText(Sideview_pHandeled[iSizeIdx].iType), NAME_SIZE);
        Surface.GetTextSize(text, &textsize);
        if (textsize.cx < aispacesize.cx) {
            if (2 * textsize.cy < aispacesize.cy) {
                Surface.DrawText(x - textsize.cx / 2, y + iOffset - textsize.cy / 2, text);
            } else {
                if ((textsize.cy < aispacesize.cy) && (!blongtext))
                    Surface.DrawText(x - textsize.cx / 2, y - iOffset - textsize.cy / 2, text);
            }
        }
    }
    Surface.SelectObject(oldpen);

    /**********************************************************************************
     * draw airspace frames in reversed order
     **********************************************************************************/
#ifdef OUTLINE_2ND
    for (int m = 0; m < Sideview_iNoHandeldSpaces; m++) {
        int iSizeIdx = iSizeLookupTable[Sideview_iNoHandeldSpaces - m - 1];
        if (Sideview_pHandeled[iSizeIdx].bEnabled) {
#if BUGSTOP
            LKASSERT(iSizeIdx < MAX_NO_SIDE_AS);
#endif
            if (iSizeIdx >= MAX_NO_SIDE_AS) iSizeIdx = MAX_NO_SIDE_AS - 1;

            int type = Sideview_pHandeled[iSizeIdx].iType;
            RECT rcd = Sideview_pHandeled[iSizeIdx].rc;
            LKColor FrameColor = MapWindow::GetAirspaceColourByClass(type);
            double fFrameColFact;
            Surface.SelectObject(LKBrush_Hollow);
            if (Sideview_pHandeled[iSizeIdx].bEnabled) {
                //		Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(type));
                Surface.SetTextColor(MapWindow::GetAirspaceColourByClass(type));
                fFrameColFact = 0.8;
            } else {
                Surface.SetTextColor(RGB_GGREY);
                FrameColor = RGB_GGREY;
                fFrameColFact = 1.2;
            }

            if (INVERTCOLORS)
                fFrameColFact *= 0.8;
            else
                fFrameColFact *= 1.2;
            LKColor lColor = FrameColor.ChangeBrightness(fFrameColFact);
            LKPen mpen2(PEN_SOLID, FRAMEWIDTH, lColor);
            const auto oldpen2 = Surface.SelectObject(mpen2);

            if (Sideview_pHandeled[iSizeIdx].bRectAllowed == true)
                Surface.Rectangle(rcd.left + 1, rcd.top, rcd.right, rcd.bottom);
            else
                Surface.Polygon(Sideview_pHandeled[iSizeIdx].apPolygon, Sideview_pHandeled[iSizeIdx].iNoPolyPts);


            Surface.SelectObject(oldpen2);
        }
    }
#endif

    /*************************************************************
     * draw ground
     *************************************************************/

    // draw ground

    /*********************************************************************
     * draw terrain
     *********************************************************************/
    LKPen hpHorizonGround(PEN_SOLID, IBLSCALE(1) + 1, LKColor(126, 62, 50));
    LKBrush hbHorizonGround(GROUND_COLOUR);
    const auto oldPen = Surface.SelectObject(hpHorizonGround);
    const auto oldBrush = Surface.SelectObject(hbHorizonGround);

    for (j = 0; j < AIRSPACE_SCANSIZE_X; j++) { // scan range
        apTerrainPolygon[j].x = iround(j * dx1) + x0;
        apTerrainPolygon[j].y = CalcHeightCoordinat(d_h[j], psDiag);
    }

    apTerrainPolygon[AIRSPACE_SCANSIZE_X].x = iround(AIRSPACE_SCANSIZE_X * dx1) + x0;
    ; // x0;
    apTerrainPolygon[AIRSPACE_SCANSIZE_X].y = CalcHeightCoordinat(0, psDiag); //iBottom;

    apTerrainPolygon[AIRSPACE_SCANSIZE_X + 1].x = iround(0 * dx1) + x0; //iround(j*dx1)+x0;
    apTerrainPolygon[AIRSPACE_SCANSIZE_X + 1].y = CalcHeightCoordinat(0, psDiag); //iBottom;
    apTerrainPolygon[AIRSPACE_SCANSIZE_X + 2] = apTerrainPolygon[0];
    
    static_assert(array_size(apTerrainPolygon) >= AIRSPACE_SCANSIZE_X + 3, "wrong array size");
    Surface.Polygon(apTerrainPolygon, AIRSPACE_SCANSIZE_X + 3);

    Surface.SelectObject(oldPen);
    Surface.SelectObject(oldBrush);

    /*********************************************************************
     * draw sea
     *********************************************************************/
#ifdef MSL_SEA_DRAW
    // draw sea
    if (psDiag->fYMin < GC_SEA_LEVEL_TOLERANCE) {
        RECT sea = {rc.left, rc.bottom, rc.right, rc.bottom + SV_BORDER_Y};
        #ifndef UNDITHER
        RenderSky(Surface, sea, RGB_STEEL_BLUE, RGB_ROYAL_BLUE, 7);
        #else
        RenderSky(Surface, sea, RGB_BLACK, RGB_BLACK, 2);
        #endif
    }
#else
    if (psDiag->fYMin < GC_SEA_LEVEL_TOLERANCE)
        Rectangle(hdc, rc.left, rc.bottom, rc.right, rc.bottom + BORDER_Y);
#endif

    Surface.SetTextColor(Sideview_TextColor); // RGB_MENUTITLEFG
}