public void HorizontalToEquatorial() { // Apparent local horizontal coordinates of Venus var hor = new CrdsHorizontal(68.0337, 15.1249); // Geographical coordinates of US Naval Observatory at Washington, DC var geo = new CrdsGeographical(new DMS("+38* 55' 17''"), new DMS("+77* 03' 56''")); // Date of observation var jd = new Date(new DateTime(1987, 4, 10, 19, 21, 0, DateTimeKind.Utc)).ToJulianDay(); // Nutation elements var nutation = Nutation.NutationElements(jd); // True obliquity var epsilon = Date.TrueObliquity(jd, nutation.deltaEpsilon); // Apparent sidereal time at Greenwich var theta0 = Date.ApparentSiderealTime(jd, nutation.deltaPsi, epsilon); Assert.AreEqual(new HMS("8h 34m 56.853s"), new HMS(theta0)); // Expected apparent equatorial coordinates of Venus var eqExpected = new CrdsEquatorial(new HMS("23h 09m 16.641s"), new DMS("-6* 43' 11.61''")); // Tested value var eqActual = hor.ToEquatorial(geo, theta0); Assert.AreEqual(eqExpected.Alpha, eqActual.Alpha, errorInHMS); Assert.AreEqual(eqExpected.Delta, eqActual.Delta, errorInDMS); }
public void GoToObject(CelestialObject body, TimeSpan animationDuration) { double sd = (body is SizeableCelestialObject) ? (body as SizeableCelestialObject).Semidiameter / 3600 : 0; double viewAngleTarget = sd == 0 ? 1 : Math.Max(sd * 10, MIN_VIEW_ANGLE); if (animationDuration.Equals(TimeSpan.Zero)) { Center.Set(body.Horizontal); ViewAngle = viewAngleTarget; } else { CrdsHorizontal centerOriginal = new CrdsHorizontal(Center); double ad = Angle.Separation(body.Horizontal, centerOriginal); double steps = Math.Round(animationDuration.TotalMilliseconds / meanRenderTime); double[] x = new double[] { 0, steps / 2, steps }; double[] y = (ad < ViewAngle) ? // linear zooming if body is already on the screen: new double[] { ViewAngle, (ViewAngle + viewAngleTarget) / 2, viewAngleTarget } : // parabolic zooming with jumping to 90 degrees view angle at the middle of path: new double[] { ViewAngle, 90, viewAngleTarget }; for (int i = 0; i <= steps; i++) { Center.Set(Angle.Intermediate(centerOriginal, body.Horizontal, i / steps)); ViewAngle = Math.Min(90, Interpolation.Lagrange(x, y, i)); } } }
/// <summary> /// Does the rendering logic /// </summary> /// <param name="map">Map instance</param> public override void Render(IMapContext map) { if (IsMeasureToolOn && map.MousePosition != null) { double coeff = map.DiagonalCoefficient(); List <PointF> points = new List <PointF>(); for (int f = 0; f <= 10; f++) { CrdsHorizontal h = Angle.Intermediate(map.MousePosition, MeasureOrigin, f / 10.0); points.Add(map.Project(h)); if (Angle.Separation(h, map.Center) > map.ViewAngle * coeff) { break; } } if (points.Count > 1) { map.Graphics.DrawCurve(new Pen(map.GetColor(Color.White)), points.ToArray()); double angle = Angle.Separation(map.MousePosition, MeasureOrigin); PointF p = map.Project(map.MousePosition); map.Graphics.DrawString(Formatters.MeasuredAngle.Format(angle), fontAngleValue, new SolidBrush(map.GetColor(Color.White)), p.X + 5, p.Y + 5); } } }
public void Intermediate() { CrdsHorizontal h1 = new CrdsHorizontal(5, 52); CrdsHorizontal h2 = new CrdsHorizontal(-120, 37); var expected = new CrdsHorizontal[] { new CrdsHorizontal(5, 52), new CrdsHorizontal(-9.924971, 59.60085), new CrdsHorizontal(-31.666402, 64.65469), new CrdsHorizontal(-58.557896, 65.51770), new CrdsHorizontal(-82.746574, 61.80095), new CrdsHorizontal(-99.938739, 54.93700), new CrdsHorizontal(-111.623334, 46.39746), new CrdsHorizontal(-120.000000, 37.00000) }; for (int i = 0; i <= 7; i++) { var h = Angle.Intermediate(h1, h2, i / 7.0); var altExpected = expected[i].Altitude; var azExpected = expected[i].Azimuth; Assert.AreEqual(altExpected, h.Altitude, 1e-5); Assert.AreEqual(azExpected, h.Azimuth, 1e-5); } }
public PointF Project(CrdsHorizontal hor) { double X, Y; double d = Angle.ToRadians(hor.Altitude); double d0 = Angle.ToRadians(Map.Center.Altitude); double da = Angle.ToRadians(hor.Azimuth - Map.Center.Azimuth); double sin_da = Math.Sin(da); double cos_da = Math.Cos(da); double sin_d = Math.Sin(d); double cos_d = Math.Cos(d); double sin_d0 = Math.Sin(d0); double cos_d0 = Math.Cos(d0); X = cos_d * sin_da; Y = sin_d * cos_d0 - cos_d * sin_d0 * cos_da; double r = Math.Sqrt(Map.Width * Map.Width + Map.Height * Map.Height); X = X * 90 / Map.ViewAngle / 2 * r; Y = Y * 90 / Map.ViewAngle / 2 * r; return(new Point((int)(Map.Width / 2.0 + X), (int)(Map.Height / 2.0 - Y))); }
public void GoToPoint(CrdsHorizontal hor, TimeSpan animationDuration, double viewAngleTarget) { if (viewAngleTarget == 0) { viewAngleTarget = ViewAngle; } if (animationDuration.Equals(TimeSpan.Zero)) { Center.Set(hor); ViewAngle = viewAngleTarget; } else { CrdsHorizontal centerOriginal = new CrdsHorizontal(Center); double ad = Angle.Separation(hor, centerOriginal); double steps = Math.Ceiling(animationDuration.TotalMilliseconds / meanRenderTime); double[] x = new double[] { 0, steps / 2, steps }; double[] y = (ad < ViewAngle) ? // linear zooming if body is already on the screen: new double[] { ViewAngle, (ViewAngle + viewAngleTarget) / 2, viewAngleTarget } : // parabolic zooming with jumping to 90 degrees view angle at the middle of path: new double[] { ViewAngle, 90, viewAngleTarget }; for (int i = 0; i <= steps; i++) { Center.Set(Angle.Intermediate(centerOriginal, hor, i / steps)); ViewAngle = Math.Min(90, Interpolation.Lagrange(x, y, i)); } } }
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); Select(); if (SkyMap != null) { bool shift = (ModifierKeys & Keys.Shift) != Keys.None; if (e.Button == MouseButtons.Left && !shift) { isMouseMoving = true; pNew.X = e.X; pNew.Y = e.Y; double dx = pNew.X - pOld.X; double dy = pNew.Y - pOld.Y; double f = SkyMap.Width / (SkyMap.ViewAngle * 2); if (Math.Abs(SkyMap.Center.Altitude) < 30 || SkyMap.ViewAngle > 80) { SkyMap.Center.Azimuth = (SkyMap.Center.Azimuth - dx / f + 360) % 360; } else { CrdsHorizontal cpNew = SkyMap.Projection.Invert(pNew); CrdsHorizontal cpOld = SkyMap.Projection.Invert(pOld); double da = Math.Abs(cpNew.Azimuth - cpOld.Azimuth); da = Math.Abs(da) * Math.Sign(dx); SkyMap.Center.Azimuth -= da; SkyMap.Center.Azimuth %= 360; } SkyMap.Center.Altitude += dy / f; if (SkyMap.Center.Altitude > 90) { SkyMap.Center.Altitude = 90; } if (SkyMap.Center.Altitude < -90) { SkyMap.Center.Altitude = -90; } if (double.IsNaN(SkyMap.Center.Azimuth)) { SkyMap.Center.Azimuth = 0; } pOld.X = pNew.X; pOld.Y = pNew.Y; Invalidate(); } } }
public PointF Project(CrdsHorizontal hor) { // ARC projection, AIPS MEMO 27 // Zenith Equidistant Projection double X, Y, L, M; double d = Angle.ToRadians(hor.Altitude); double d0 = Angle.ToRadians(Map.Center.Altitude); double da = Angle.ToRadians(hor.Azimuth - Map.Center.Azimuth); double rho = Angle.ToRadians(0); double sin_da = Math.Sin(da); double cos_da = Math.Cos(da); double sin_d = Math.Sin(d); double cos_d = Math.Cos(d); double sin_d0 = Math.Sin(d0); double cos_d0 = Math.Cos(d0); double theta = Math.Acos(sin_d * sin_d0 + cos_d * cos_d0 * cos_da); if (theta == 0 || double.IsNaN(theta)) { X = 0; Y = 0; return(new PointF((float)(Map.Width / 2.0 + X), (float)(Map.Height / 2.0 - Y))); } double k = theta / Math.Sin(theta); L = k * cos_d * sin_da; M = k * (sin_d * cos_d0 - cos_d * sin_d0 * cos_da); double sin_rho = Math.Sin(rho); double cos_rho = Math.Cos(rho); X = L * cos_rho + M * sin_rho; Y = M * cos_rho - L * sin_rho; X = Angle.ToDegrees(X) / Map.ViewAngle * Map.Width / 2; Y = Angle.ToDegrees(Y) / Map.ViewAngle * Map.Width / 2; return(new Point((int)(Map.Width / 2.0 + X), (int)(Map.Height / 2.0 - Y))); }
public PointF Project(CrdsHorizontal hor) { double X, Y; double d = (IsInverted ? -1 : 1) * Angle.ToRadians(hor.Altitude); double d0 = (IsInverted ? -1 : 1) * Angle.ToRadians(Map.Center.Altitude); double da = (IsMirrored ? -1 : 1) * Angle.ToRadians(hor.Azimuth - Map.Center.Azimuth); double sin_da = Math.Sin(da); double cos_da = Math.Cos(da); double sin_d = Math.Sin(d); double cos_d = Math.Cos(d); double sin_d0 = Math.Sin(d0); double cos_d0 = Math.Cos(d0); double theta = Math.Acos(sin_d * sin_d0 + cos_d * cos_d0 * cos_da); if (theta == 0 || double.IsNaN(theta)) { X = 0; Y = 0; return(new PointF((float)(Map.Width / 2.0 + X), (float)(Map.Height / 2.0 - Y))); } double k = theta / Math.Sin(theta); X = k * cos_d * sin_da; Y = k * (sin_d * cos_d0 - cos_d * sin_d0 * cos_da); double maxSize = Math.Sqrt(Map.Width * Map.Width + Map.Height * Map.Height); X = Angle.ToDegrees(X) / Map.ViewAngle * maxSize / 2; Y = Angle.ToDegrees(Y) / Map.ViewAngle * maxSize / 2; return(new Point((int)(Map.Width / 2.0 + X), (int)(Map.Height / 2.0 - Y))); }
public void Separation() { // Example 17.a, AA(II) { var c1 = new CrdsEquatorial(213.9154, 19.1825); var c2 = new CrdsEquatorial(201.2983, -11.1614); Assert.AreEqual(32.7930, Angle.Separation(c1, c2), 1e-4); } { var c1 = new CrdsEcliptical(213.9154, 19.1825); var c2 = new CrdsEcliptical(201.2983, -11.1614); Assert.AreEqual(32.7930, Angle.Separation(c1, c2), 1e-4); } { var c1 = new CrdsGeographical(213.9154, 19.1825); var c2 = new CrdsGeographical(201.2983, -11.1614); Assert.AreEqual(32.7930, Angle.Separation(c1, c2), 1e-4); } { var c1 = new CrdsHorizontal(213.9154, 19.1825); var c2 = new CrdsHorizontal(201.2983, -11.1614); Assert.AreEqual(32.7930, Angle.Separation(c1, c2), 1e-4); } }
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); Select(); if (SkyMap != null) { bool shift = (ModifierKeys & Keys.Shift) != Keys.None; SkyMap.MousePosition = SkyMap.Projection.Invert(new PointF(e.X, e.Y)); if (e.Button == MouseButtons.Left && !shift) { SkyMap.IsDragging = true; if (SkyMap.LockedObject == null) { if (pOld == Point.Empty) { pOld = new Point(e.X, e.Y); } pNew.X = e.X; pNew.Y = e.Y; double dx = pNew.X - pOld.X; double dy = pNew.Y - pOld.Y; SkyMap.Antialias = Math.Sqrt(dx * dx + dy * dy) < 30; double maxSize = Math.Max(SkyMap.Width, SkyMap.Height); double f = maxSize / (SkyMap.ViewAngle * 2); if (Math.Abs(SkyMap.Center.Altitude) < 30 || SkyMap.ViewAngle > 80) { SkyMap.Center.Azimuth = (SkyMap.Center.Azimuth - dx / f + 360) % 360; } else { CrdsHorizontal cpNew = SkyMap.Projection.Invert(pNew); CrdsHorizontal cpOld = SkyMap.Projection.Invert(pOld); double da = Math.Abs(cpNew.Azimuth - cpOld.Azimuth); da = Math.Abs(da) * Math.Sign(dx); SkyMap.Center.Azimuth -= da; SkyMap.Center.Azimuth %= 360; } SkyMap.Center.Altitude += dy / f; if (SkyMap.Center.Altitude > 90) { SkyMap.Center.Altitude = 90; } if (SkyMap.Center.Altitude < -90) { SkyMap.Center.Altitude = -90; } if (double.IsNaN(SkyMap.Center.Azimuth)) { SkyMap.Center.Azimuth = 0; } pOld.X = pNew.X; pOld.Y = pNew.Y; } else { if (Cursor != Cursors.No) { Cursor = Cursors.No; } } Invalidate(); } else { SkyMap.IsDragging = false; if (SkyMap.RenderOnMouseMove) { Invalidate(); } } } }
/// <summary> /// Performs a correction of inverse projection. /// Checks that horizontal coordinates of a point are correct, /// and in case if not correct, applies iterative algorithm for searching correct values. /// </summary> /// <param name="p">Point to check</param> /// <param name="hor">Horizontal coordinates of the point</param> /// <returns>Corrected horizontal coordinates</returns> private CrdsHorizontal CorrectInverse(PointF p, CrdsHorizontal hor) { PointF pLeftEdge = Project(new CrdsHorizontal(Map.Center.Azimuth - 90, hor.Altitude)); PointF pRightEdge = Project(new CrdsHorizontal(Map.Center.Azimuth + 90, hor.Altitude)); PointF pEdge; if (p.X < Map.Width / 2.0) { pEdge = pLeftEdge; } else { pEdge = pRightEdge; } Point origin = new Point((int)(Map.Width / 2.0), (int)(Map.Height / 2.0)); double edgeToCenter = Map.DistanceBetweenPoints(origin, pEdge); double currentToCenter = Map.DistanceBetweenPoints(origin, p); bool correctionNeeded = Math.Abs(Map.Center.Altitude) == 90 || currentToCenter > edgeToCenter; if (correctionNeeded) { // projected coordinates of a horizontal grid pole (zenith or nadir point) PointF pole = Project(new CrdsHorizontal(0, 90 * (Map.Center.Altitude > 0 ? 1 : -1))); double angleWhole = 360 - Map.AngleBetweenVectors(pole, pLeftEdge, pRightEdge); double angleLeft = Map.AngleBetweenVectors(pole, p, pLeftEdge); double angleRight = Map.AngleBetweenVectors(pole, p, pRightEdge); int shiftSign = angleLeft < angleRight ? -1 : 1; int poleFix = 1; if (Map.Center.Altitude == 90 && pole.Y < p.Y) { poleFix = -1; } else if (Map.Center.Altitude == -90 && pole.Y > p.Y) { poleFix = -1; } double poleAngle = Math.Min(angleLeft, angleRight); double azimuthShift = poleAngle / angleWhole * 180; PointF pCorrected = new PointF(0, 0); double distOriginal = Map.DistanceBetweenPoints(p, pEdge); double distCorrected = 0; int iterations = 0; do { hor = new CrdsHorizontal(Angle.To360(Map.Center.Azimuth + shiftSign * 90 + poleFix * shiftSign * azimuthShift), hor.Altitude); // corrected coordinates of a projected point pCorrected = Project(hor); distCorrected = Map.DistanceBetweenPoints(pCorrected, pEdge); if (distCorrected > 0) { azimuthShift *= distOriginal / distCorrected; } iterations++; }while (Map.DistanceBetweenPoints(p, pCorrected) > 2 && iterations < 5); } return(hor); }
/// <summary> /// Map should be renderer on MouseMove only if measure tool is on /// </summary> public override bool OnMouseMove(CrdsHorizontal mouse, MouseButton mouseButton) { return(IsMeasureToolOn); }
public override void Render(IMapContext map) { double coeff = map.DiagonalCoefficient(); if (settings.Get <bool>("Ground")) { const int POINTS_COUNT = 64; PointF[] hor = new PointF[POINTS_COUNT]; double step = 2 * map.ViewAngle / (POINTS_COUNT - 1); SolidBrush brushGround = new SolidBrush(map.GetColor(colorGroundNight, colorGroundDay)); // Bottom part of ground shape for (int i = 0; i < POINTS_COUNT; i++) { var h = new CrdsHorizontal(map.Center.Azimuth - map.ViewAngle + step * i, 0); hor[i] = map.Project(h); } if (hor[0].X >= 0) { hor[0].X = -1; } if (hor[POINTS_COUNT - 1].X <= map.Width) { hor[POINTS_COUNT - 1].X = map.Width + 1; } if (hor.Any(h => !map.IsOutOfScreen(h))) { GraphicsPath gp = new GraphicsPath(); gp.AddCurve(hor); gp.AddLines(new PointF[] { new PointF(map.Width + 1, map.Height + 1), new PointF(-1, map.Height + 1) }); map.Graphics.FillPath(brushGround, gp); } else if (map.Center.Altitude <= 0) { map.Graphics.FillRectangle(brushGround, 0, 0, map.Width, map.Height); } // Top part of ground shape if (map.Center.Altitude > 0) { for (int i = 0; i < POINTS_COUNT; i++) { var h = new CrdsHorizontal(map.Center.Azimuth - map.ViewAngle - step * i, 0); hor[i] = map.Project(h); } if (hor.Count(h => !map.IsOutOfScreen(h)) > 2) { GraphicsPath gp = new GraphicsPath(); gp.AddCurve(hor); gp.AddLines(new PointF[] { new PointF(map.Width + 1, -1), new PointF(-1, -1), }); map.Graphics.FillPath(brushGround, gp); } } } if (map.Schema == ColorSchema.White || (!settings.Get <bool>("Ground") && settings.Get <bool>("HorizonLine"))) { const int POINTS_COUNT = 64; PointF[] hor = new PointF[POINTS_COUNT]; double step = 2 * map.ViewAngle / (POINTS_COUNT - 1); for (int i = 0; i < POINTS_COUNT; i++) { var h = new CrdsHorizontal(map.Center.Azimuth - map.ViewAngle + step * i, 0); hor[i] = map.Project(h); } if (hor[0].X >= 0) { hor[0].X = -1; } if (hor[POINTS_COUNT - 1].X <= map.Width) { hor[POINTS_COUNT - 1].X = map.Width + 1; } if (hor.Any(h => !map.IsOutOfScreen(h))) { Pen penHorizonLine = new Pen(map.GetColor("ColorHorizon"), 2); map.Graphics.DrawCurve(penHorizonLine, hor); } } if (settings.Get <bool>("LabelCardinalDirections")) { Brush brushCardinalLabels = new SolidBrush(map.GetColor("ColorCardinalDirections")); StringFormat format = new StringFormat() { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center }; for (int i = 0; i < cardinalDirections.Length; i++) { var h = new CrdsHorizontal(i * 360 / cardinalDirections.Length, 0); if (Angle.Separation(h, map.Center) < map.ViewAngle * coeff) { PointF p = map.Project(h); p.Y += fontCardinalLabels[i % 2].Height; using (var gp = new GraphicsPath()) { map.Graphics.DrawString(Text.Get($"CardinalDirections.{cardinalDirections[i]}"), fontCardinalLabels[i % 2], brushCardinalLabels, p, format); } } } } }
public PointF Project(CrdsHorizontal hor) { return(map.Projection.Project(hor)); }
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (SkyMap != null) { switch (e.Button) { case MouseButtons.Left: SkyMap.MouseButton = MouseButton.Left; break; case MouseButtons.Right: SkyMap.MouseButton = MouseButton.Right; break; default: SkyMap.MouseButton = MouseButton.None; break; } CrdsHorizontal newMousePosition = SkyMap.Projection.Invert(new PointF(e.X, e.Y)); if (SkyMap.MouseButton == MouseButton.Left) { if (SkyMap.LockedObject == null) { if (pOld == Point.Empty) { pOld = new Point(e.X, e.Y); } pNew.X = e.X; pNew.Y = e.Y; double dx = pNew.X - pOld.X; double dy = pNew.Y - pOld.Y; SkyMap.Antialias = Math.Sqrt(dx * dx + dy * dy) < 30; double maxSize = Math.Max(SkyMap.Width, SkyMap.Height); double f = maxSize / (SkyMap.ViewAngle * 2); if (Math.Abs(SkyMap.Center.Altitude) < 30 || SkyMap.ViewAngle > 80) { SkyMap.Center.Azimuth = (SkyMap.Center.Azimuth - dx / f + 360) % 360; } else { CrdsHorizontal cpNew = SkyMap.Projection.Invert(pNew); CrdsHorizontal cpOld = SkyMap.Projection.Invert(pOld); double da = Math.Abs(cpNew.Azimuth - cpOld.Azimuth); da = Math.Abs(da) * Math.Sign(dx); SkyMap.Center.Azimuth -= da; SkyMap.Center.Azimuth %= 360; } SkyMap.Center.Altitude += dy / f; if (SkyMap.Center.Altitude > 90) { SkyMap.Center.Altitude = 90; } if (SkyMap.Center.Altitude < -90) { SkyMap.Center.Altitude = -90; } if (double.IsNaN(SkyMap.Center.Azimuth)) { SkyMap.Center.Azimuth = 0; } pOld.X = pNew.X; pOld.Y = pNew.Y; Invalidate(); } else { if (Cursor != Cursors.No) { Invalidate(); Cursor = Cursors.No; } } SkyMap.MousePosition = newMousePosition; } else { SkyMap.MousePosition = newMousePosition; } } }
/// <summary> /// The function is called each time when position of mouse is changed. /// Mouse position, converted to horizontal coordinates on map, is passed as parameter. /// The function should return true if repaint of map is required, /// otherwise it should return false (default behaviour). /// </summary> /// <param name="mouse">Current mouse position on sky map</param> /// <returns>True if repaint of map is required, otherwise false.</returns> public virtual bool OnMouseMove(CrdsHorizontal mouse, MouseButton mouseButton) { return(false); }
public void GoToPoint(CrdsHorizontal hor, TimeSpan animationDuration) { GoToPoint(hor, animationDuration, Math.Min(viewAngle, 90)); }
public void GoToPoint(CrdsHorizontal hor, double viewAngleTarget) { GoToPoint(hor, TimeSpan.Zero, viewAngleTarget); }
/// <summary> /// Creates new instance /// </summary> public Asteroid() { Horizontal = new CrdsHorizontal(); }
public override void Render(IMapContext map) { if (settings.Get <bool>("Ground")) { const int POINTS_COUNT = 64; PointF[] hor = new PointF[POINTS_COUNT]; double step = 2 * map.ViewAngle / (POINTS_COUNT - 1); SolidBrush brushGround = new SolidBrush(map.GetColor(colorGroundNight, colorGroundDay)); // Bottom part of ground shape for (int i = 0; i < POINTS_COUNT; i++) { var h = new CrdsHorizontal(map.Center.Azimuth - map.ViewAngle + step * i, 0); hor[i] = map.Project(h); } if (hor.Any(h => !map.IsOutOfScreen(h))) { GraphicsPath gp = new GraphicsPath(); gp.AddCurve(hor); var pts = map.IsInverted ? new PointF[] { new PointF(map.Width + 1, -1), new PointF(-1, -1), } : new PointF[] { new PointF(map.Width + 1, map.Height + 1), new PointF(-1, map.Height + 1) }; if (hor.Last().X > map.Width / 2) { gp.AddLines(pts); } else { gp.AddLines(pts.Reverse().ToArray()); } map.Graphics.FillPath(brushGround, gp); } else if (map.Center.Altitude <= 0) { map.Graphics.FillRectangle(brushGround, 0, 0, map.Width, map.Height); } // Top part of ground shape if (map.Center.Altitude > 0) { for (int i = 0; i < POINTS_COUNT; i++) { var h = new CrdsHorizontal(map.Center.Azimuth - map.ViewAngle - step * i, 0); hor[i] = map.Project(h); } if (hor.Count(h => !map.IsOutOfScreen(h)) > 2) { GraphicsPath gp = new GraphicsPath(); gp.AddCurve(hor); gp.AddLines(new PointF[] { new PointF(map.Width + 1, -1), new PointF(-1, -1), }); map.Graphics.FillPath(brushGround, gp); } } } if (map.Schema == ColorSchema.White || (!settings.Get <bool>("Ground") && settings.Get <bool>("HorizonLine"))) { const int POINTS_COUNT = 64; PointF[] hor = new PointF[POINTS_COUNT]; double step = 2 * map.ViewAngle / (POINTS_COUNT - 1); for (int i = 0; i < POINTS_COUNT; i++) { var h = new CrdsHorizontal(map.Center.Azimuth - map.ViewAngle + step * i, 0); hor[i] = map.Project(h); } if (hor.Any(h => !map.IsOutOfScreen(h))) { Pen penHorizonLine = new Pen(map.GetColor("ColorHorizon"), 2); map.Graphics.DrawCurve(penHorizonLine, hor); } } if (settings.Get <bool>("LabelCardinalDirections")) { Brush brushCardinalLabels = new SolidBrush(map.GetColor("ColorCardinalDirections")); StringFormat format = new StringFormat() { LineAlignment = StringAlignment.Near, Alignment = StringAlignment.Center }; for (int i = 0; i < cardinalDirections.Length; i++) { var h = new CrdsHorizontal(i * 360 / cardinalDirections.Length, 0); if (Angle.Separation(h, map.Center) < map.ViewAngle) { PointF p = map.Project(h); var fontBase = settings.Get <Font>("CardinalDirectionsFont"); var font = new Font(fontBase.FontFamily, fontBase.Size * (i % 2 == 0 ? 1 : 0.75f), fontBase.Style); using (var gp = new GraphicsPath()) { map.Graphics.DrawString(Text.Get($"CardinalDirections.{cardinalDirections[i]}"), font, brushCardinalLabels, p, format); } } } } }
/// <summary> /// Creates new instance /// </summary> public Comet() { Horizontal = new CrdsHorizontal(); TailHorizontal = new CrdsHorizontal(); }