using System; using System.Linq; using System.Collections.Generic; namespace Test { public static class MathHelper { public static double ToRadians(double degrees) { return degrees * Math.PI / 180.0; } public static double ToDegrees(double radians) { return radians / Math.PI * 180.0; } } public class Planet { public string Name { get; set; } public double Inclination { get; set; } public double LongitudeOfAscent { get; set; } public double Distance { get; set; } public double MaxElevation { get; set; } double solarAngle { get; set; } // angle in radians for 1/2 of sun at this orbit, for +/- calculation public Planet(string name, double inclination, double longitude, double distance) { this.Name = name; this.Inclination = MathHelper.ToRadians(inclination); this.LongitudeOfAscent = MathHelper.ToRadians(longitude); this.Distance = distance; MaxElevation = Math.Tan(this.Inclination) * this.Distance; solarAngle = Math.Atan(0.6955/Distance); // 1/2 angular size of the sun at orbital distance } public static List Planets; static Planet() { Planets = new List(); Planets.Add(new Planet("Mercury", 6.34, 48.331, 57.9)); Planets.Add(new Planet("Venus", 2.19, 76.678, 108.20)); Planets.Add(new Planet("Earth", 1.57, 348.73936, 149.60)); Planets.Add(new Planet("Mars", 1.67, 49.562, 227.9)); Planets.Add(new Planet("Jupiter", 0.32, 100.492, 778.3)); Planets.Add(new Planet("Saturn", 0.93, 113.642811, 1427)); Planets.Add(new Planet("Uranus", 1.02, 73.989, 2871)); Planets.Add(new Planet("Neptune", 0.72, 131.79431, 4497.10)); } /// /// For a given longitude on the invariable plane, calculate and return /// the minimum and maximum latitude where the planet's center could be /// seen with the sun in the background. /// /// /// public Range GetRange(double longitude) { double longitudeRadians = MathHelper.ToRadians(longitude); // ok, first we get the viewing longitude as relative to the angle of the ascending node double viewingLongitude = longitudeRadians - LongitudeOfAscent; // ok, angle above plane is inclination of plane * sin of viewing angle double planetAngle = Inclination * Math.Sin(viewingLongitude); return new Range() { Min = planetAngle - solarAngle, Max = planetAngle + solarAngle }; } } public class Range { public double Min { get; set; } public double Max { get; set; } } public class ShowOrbits { public static void Main() { // for 360 degrees, show what other planets are visible from earth var others = Planet.Planets.Where(x => x.Name != "Earth"); var earth = Planet.Planets.Where(x => x.Name == "Earth").Single(); for (double angle = 0; angle < 360; angle += 1.0) { var er = earth.GetRange(angle); List planets = new List(); foreach (var planet in others) { var range = planet.GetRange(angle); if (range.Min <= er.Max && range.Max >= er.Min) { planets.Add(planet.Name); } } Console.WriteLine("{0:000} degrees: {1:##0.00} to {2:##0.00} can see {3}", angle, MathHelper.ToDegrees(er.Min), MathHelper.ToDegrees(er.Max), string.Join(", ", planets.ToArray())); // at Earth's Longitude of Ascending node, show all planets if (angle == 349 || angle == 107) { foreach (var p in Planet.Planets) { var r = p.GetRange(angle); Console.WriteLine("{0:10}: {1:##0.00} to {2:##0.00}", p.Name, MathHelper.ToDegrees(r.Min), MathHelper.ToDegrees(r.Max)); } } } } } }