/// <summary>Constructs a link between two satellites, if one is possible.</summary> /// <returns>The new link, or null if the two satellites cannot connect.</returns> /// <param name="rangeFunc">A function that computes the maximum range between two /// satellites, given their individual ranges.</param> public static NetworkLink <ISatellite> GetLink(ISatellite satA, ISatellite satB, Func <double, double, double> rangeFunc) { // Which antennas on either craft are capable of communication? IEnumerable <IAntenna> omnisA = GetOmnis(satA); IEnumerable <IAntenna> omnisB = GetOmnis(satB); IEnumerable <IAntenna> dishesA = GetDishesThatSee(satA, satB); IEnumerable <IAntenna> dishesB = GetDishesThatSee(satB, satA); // Pick the best range for each case double maxOmniA = omnisA.Any() ? omnisA.Max(ant => ant.Omni) : 0.0; double maxOmniB = omnisB.Any() ? omnisB.Max(ant => ant.Omni) : 0.0; double maxDishA = dishesA.Any() ? dishesA.Max(ant => ant.Dish) : 0.0; double maxDishB = dishesB.Any() ? dishesB.Max(ant => ant.Dish) : 0.0; double bonusA = GetMultipleAntennaBonus(omnisA, maxOmniA); double bonusB = GetMultipleAntennaBonus(omnisB, maxOmniB); double distance = satA.DistanceTo(satB); // Which antennas have the range to reach at least one antenna on the other satellite?? omnisA = omnisA.Where(ant => CheckRange(rangeFunc, ant.Omni + bonusA, omniClamp, maxOmniB + bonusB, omniClamp) >= distance || CheckRange(rangeFunc, ant.Omni + bonusA, omniClamp, maxDishB, dishClamp) >= distance); dishesA = dishesA.Where(ant => CheckRange(rangeFunc, ant.Dish, dishClamp, maxOmniB + bonusB, omniClamp) >= distance || CheckRange(rangeFunc, ant.Dish, dishClamp, maxDishB, dishClamp) >= distance); omnisB = omnisB.Where(ant => CheckRange(rangeFunc, ant.Omni + bonusB, omniClamp, maxOmniA + bonusA, omniClamp) >= distance || CheckRange(rangeFunc, ant.Omni + bonusB, omniClamp, maxDishA, dishClamp) >= distance); dishesB = dishesB.Where(ant => CheckRange(rangeFunc, ant.Dish, dishClamp, maxOmniA + bonusA, omniClamp) >= distance || CheckRange(rangeFunc, ant.Dish, dishClamp, maxDishA, dishClamp) >= distance); // Just because an antenna is in `omnisA.Concat(dishesA)` doesn't mean it can connect to *any* // antenna in `omnisB.Concat(dishesB)`, and vice versa. Pick the max to be safe. IAntenna selectedAntennaA = omnisA.Concat(dishesA) .OrderByDescending(ant => Math.Max(ant.Omni, ant.Dish)).FirstOrDefault(); IAntenna selectedAntennaB = omnisB.Concat(dishesB) .OrderByDescending(ant => Math.Max(ant.Omni, ant.Dish)).FirstOrDefault(); if (selectedAntennaA != null && selectedAntennaB != null) { List <IAntenna> interfaces = omnisA.Concat(dishesA).ToList(); LinkType type = (dishesA.Contains(selectedAntennaA) || dishesB.Contains(selectedAntennaB) ? LinkType.Dish : LinkType.Omni); return(new NetworkLink <ISatellite>(satB, interfaces, type)); } return(null); }
/// <summary>Constructs a link between two satellites, if one is possible.</summary> /// <returns>The new link, or null if the two satellites cannot connect.</returns> /// <param name="rangeFunc">A function that computes the maximum range between two /// satellites, given their individual ranges.</param> public static NetworkLink<ISatellite> GetLink(ISatellite satA, ISatellite satB, Func<double, double, double> rangeFunc) { // Which antennas on either craft are capable of communication? IEnumerable<IAntenna> omnisA = GetOmnis(satA); IEnumerable<IAntenna> omnisB = GetOmnis(satB); IEnumerable<IAntenna> dishesA = GetDishesThatSee(satA, satB); IEnumerable<IAntenna> dishesB = GetDishesThatSee(satB, satA); // Pick the best range for each case double maxOmniA = omnisA.Any() ? omnisA.Max(ant => ant.Omni) : 0.0; double maxOmniB = omnisB.Any() ? omnisB.Max(ant => ant.Omni) : 0.0; double maxDishA = dishesA.Any() ? dishesA.Max(ant => ant.Dish) : 0.0; double maxDishB = dishesB.Any() ? dishesB.Max(ant => ant.Dish) : 0.0; double bonusA = GetMultipleAntennaBonus(omnisA, maxOmniA); double bonusB = GetMultipleAntennaBonus(omnisB, maxOmniB); double distance = satA.DistanceTo(satB); // Which antennas have the range to reach at least one antenna on the other satellite?? omnisA = omnisA.Where(ant => CheckRange(rangeFunc, ant.Omni + bonusA, omniClamp, maxOmniB + bonusB, omniClamp) >= distance || CheckRange(rangeFunc, ant.Omni + bonusA, omniClamp, maxDishB , dishClamp) >= distance); dishesA = dishesA.Where(ant => CheckRange(rangeFunc, ant.Dish , dishClamp, maxOmniB + bonusB, omniClamp) >= distance || CheckRange(rangeFunc, ant.Dish , dishClamp, maxDishB , dishClamp) >= distance); omnisB = omnisB.Where(ant => CheckRange(rangeFunc, ant.Omni + bonusB, omniClamp, maxOmniA + bonusA, omniClamp) >= distance || CheckRange(rangeFunc, ant.Omni + bonusB, omniClamp, maxDishA , dishClamp) >= distance); dishesB = dishesB.Where(ant => CheckRange(rangeFunc, ant.Dish , dishClamp, maxOmniA + bonusA, omniClamp) >= distance || CheckRange(rangeFunc, ant.Dish , dishClamp, maxDishA , dishClamp) >= distance); // Just because an antenna is in `omnisA.Concat(dishesA)` doesn't mean it can connect to *any* // antenna in `omnisB.Concat(dishesB)`, and vice versa. Pick the max to be safe. IAntenna selectedAntennaA = omnisA.Concat(dishesA) .OrderByDescending(ant => Math.Max(ant.Omni, ant.Dish)).FirstOrDefault(); IAntenna selectedAntennaB = omnisB.Concat(dishesB) .OrderByDescending(ant => Math.Max(ant.Omni, ant.Dish)).FirstOrDefault(); if (selectedAntennaA != null && selectedAntennaB != null) { List<IAntenna> interfaces = omnisA.Concat(dishesA).ToList(); LinkType type = (dishesA.Contains(selectedAntennaA) || dishesB.Contains(selectedAntennaB) ? LinkType.Dish : LinkType.Omni); return new NetworkLink<ISatellite>(satB, interfaces, type); } return null; }
public static NetworkLink <ISatellite> GetLink(ISatellite sat_a, ISatellite sat_b) { var omni_a = sat_a.Antennas.Where(a => a.Omni > 0); var omni_b = sat_b.Antennas.Where(b => b.Omni > 0); var dish_a = sat_a.Antennas.Where(a => a.Dish > 0 && (a.IsTargetingDirectly(sat_b) || a.IsTargetingActiveVessel(sat_b) || a.IsTargetingPlanet(sat_b, sat_a))); var dish_b = sat_b.Antennas.Where(b => b.Dish > 0 && (b.IsTargetingDirectly(sat_a) || b.IsTargetingActiveVessel(sat_a) || b.IsTargetingPlanet(sat_a, sat_b))); double max_omni_a = omni_a.Any() ? omni_a.Max(a => a.Omni) : 0.0; double max_omni_b = omni_b.Any() ? omni_b.Max(b => b.Omni) : 0.0; double max_dish_a = dish_a.Any() ? dish_a.Max(a => a.Dish) : 0.0; double max_dish_b = dish_b.Any() ? dish_b.Max(b => b.Dish) : 0.0; double bonus_a = 0.0; double bonus_b = 0.0; if (RTSettings.Instance.MultipleAntennaMultiplier > 0.0) { double sum_omni_a = omni_a.Sum(a => a.Omni); double sum_omni_b = omni_b.Sum(b => b.Omni); bonus_a = (sum_omni_a - max_omni_a) * RTSettings.Instance.MultipleAntennaMultiplier; bonus_b = (sum_omni_b - max_omni_b) * RTSettings.Instance.MultipleAntennaMultiplier; } double max_a = Math.Max(max_omni_a + bonus_a, max_dish_a); double max_b = Math.Max(max_omni_b + bonus_b, max_dish_b); double distance = sat_a.DistanceTo(sat_b); omni_a = omni_a.Where(a => MaxDistance(a.Omni + bonus_a, max_b, OmniRangeClamp) >= distance); dish_a = dish_a.Where(a => MaxDistance(a.Dish, max_omni_b + bonus_b, OmniRangeClamp) >= distance || MaxDistance(a.Dish, max_dish_b, DishRangeClamp) >= distance); omni_b = omni_b.Where(b => MaxDistance(b.Omni + bonus_b, max_a, OmniRangeClamp) >= distance); dish_b = dish_b.Where(b => MaxDistance(b.Dish, max_omni_a + bonus_a, OmniRangeClamp) >= distance || MaxDistance(b.Dish, max_dish_a, DishRangeClamp) >= distance); var conn_a = omni_a.Concat(dish_a).FirstOrDefault(); var conn_b = omni_b.Concat(dish_b).FirstOrDefault(); if (conn_a != null && conn_b != null) { var interfaces = omni_a.Concat(dish_a).ToList(); var type = LinkType.Omni; if (dish_a.Contains(conn_a) || dish_b.Contains(conn_b)) { type = LinkType.Dish; } return(new NetworkLink <ISatellite>(sat_b, interfaces, type)); } return(null); }
public static NetworkLink<ISatellite> GetLink(ISatellite sat_a, ISatellite sat_b) { var omni_a = sat_a.Antennas.Where(a => a.Omni > 0); var omni_b = sat_b.Antennas.Where(b => b.Omni > 0); var dish_a = sat_a.Antennas.Where(a => a.Dish > 0 && (a.IsTargetingDirectly(sat_b) || a.IsTargetingActiveVessel(sat_b) || a.IsTargetingPlanet(sat_b, sat_a))); var dish_b = sat_b.Antennas.Where(b => b.Dish > 0 && (b.IsTargetingDirectly(sat_a) || b.IsTargetingActiveVessel(sat_a) || b.IsTargetingPlanet(sat_a, sat_b))); double max_omni_a = omni_a.Any() ? omni_a.Max(a => a.Omni) : 0.0; double max_omni_b = omni_b.Any() ? omni_b.Max(b => b.Omni) : 0.0; double max_dish_a = dish_a.Any() ? dish_a.Max(a => a.Dish) : 0.0; double max_dish_b = dish_b.Any() ? dish_b.Max(b => b.Dish) : 0.0; double bonus_a = 0.0; double bonus_b = 0.0; if (RTSettings.Instance.MultipleAntennaMultiplier > 0.0) { double sum_omni_a = omni_a.Sum(a => a.Omni); double sum_omni_b = omni_b.Sum(b => b.Omni); bonus_a = (sum_omni_a - max_omni_a) * RTSettings.Instance.MultipleAntennaMultiplier; bonus_b = (sum_omni_b - max_omni_b) * RTSettings.Instance.MultipleAntennaMultiplier; } double max_a = Math.Max(max_omni_a + bonus_a, max_dish_a); double max_b = Math.Max(max_omni_b + bonus_b, max_dish_b); double distance = sat_a.DistanceTo(sat_b); omni_a = omni_a.Where(a => MaxDistance(a.Omni + bonus_a, max_b, OmniRangeClamp) >= distance); dish_a = dish_a.Where(a => MaxDistance(a.Dish, max_omni_b + bonus_b, OmniRangeClamp) >= distance || MaxDistance(a.Dish, max_dish_b, DishRangeClamp) >= distance); omni_b = omni_b.Where(b => MaxDistance(b.Omni + bonus_b, max_a, OmniRangeClamp) >= distance); dish_b = dish_b.Where(b => MaxDistance(b.Dish, max_omni_a + bonus_a, OmniRangeClamp) >= distance || MaxDistance(b.Dish, max_dish_a, DishRangeClamp) >= distance); var conn_a = omni_a.Concat(dish_a).FirstOrDefault(); var conn_b = omni_b.Concat(dish_b).FirstOrDefault(); if (conn_a != null && conn_b != null) { var interfaces = omni_a.Concat(dish_a).ToList(); var type = LinkType.Omni; if (dish_a.Contains(conn_a) || dish_b.Contains(conn_b)) type = LinkType.Dish; return new NetworkLink<ISatellite>(sat_b, interfaces, type); } return null; }
public static Point2D Triangulation(ISatellite s1, double r1, ISatellite s2, double r2, ISatellite s3, double r3) { if (r1 == 0 || r2 == 0 || r3 == 0) { Console.WriteLine("*** Error: Las distancias son incorrectas"); return(null); } double x1, x2 = 0, y1 = 0, y2; try { // (X) // /b\ // r1 / | \ r2 // / h \ // a /_ r12 _\ g // (s1) (s2) double r12 = s1.DistanceTo(s2); double h = 2 * Heron(r1, r12, r2) / r12; double alphaRadians = Math.Sin(h / r1); double ah = (r1 * Math.Cos(alphaRadians)); Point2D p1 = (Point2D)s1.GetCoords(); Point2D p2 = (Point2D)s2.GetCoords(); Point2D p3 = p1 + ((ah / r12) * (p2 - p1)); x1 = p3.X + (h * (p2.Y - p1.Y) / r12); x2 = p3.X - (h * (p2.Y - p1.Y) / r12); y1 = p3.Y + (h * (p2.X - p1.X) / r12); y2 = p3.Y + (h * (p2.X - p1.X) / r12); // TODO: Select combination with minimun error automatically Console.ForegroundColor = ConsoleColor.Cyan; Console.BackgroundColor = ConsoleColor.DarkGray; Console.WriteLine("\tShowing the error in the different solutions of:"); Console.WriteLine($"\tX={p1} ± ({ah:0.###}/{r12:0.###})({p2}-{p1})"); Console.WriteLine($"\ts1. Difference distance informed to kenobi vs distance approximated (x1,y1): {Math.Abs(DistanceFromTo(p1, new Point2D(x1, y1)) - r1)}"); Console.WriteLine($"\ts1. Difference distance informed to kenobi vs distance approximated (x1,y2): {Math.Abs(DistanceFromTo(p1, new Point2D(x1, y2)) - r1)}"); Console.WriteLine($"\ts1. Difference distance informed to kenobi vs distance approximated (x2,y1): {Math.Abs(DistanceFromTo(p1, new Point2D(x2, y1)) - r1)}"); Console.WriteLine($"\ts1. Difference distance informed to kenobi vs distance approximated (x2,y2): {Math.Abs(DistanceFromTo(p1, new Point2D(x2, y2)) - r1)}"); Console.WriteLine($"\ts2. Difference distance informed to skywalker vs distance approximated (x1,y1): {Math.Abs(DistanceFromTo(p2, new Point2D(x1, y1)) - r2)}"); Console.WriteLine($"\ts2. Difference distance informed to skywalker vs distance approximated (x1,y2): {Math.Abs(DistanceFromTo(p2, new Point2D(x1, y2)) - r2)}"); Console.WriteLine($"\ts2. Difference distance informed to skywalker vs distance approximated (x2,y1): {Math.Abs(DistanceFromTo(p2, new Point2D(x2, y1)) - r2)}"); Console.WriteLine($"\ts2. Difference distance informed to skywalker vs distance approximated (x2,y2): {Math.Abs(DistanceFromTo(p2, new Point2D(x2, y2)) - r2)}"); Console.WriteLine($"\ts3. Difference distance informed to sato vs distance approximated (x1,y1): {Math.Abs(DistanceFromTo((Point2D)s3.GetCoords(), new Point2D(x1, y1)) - r3)}"); Console.WriteLine($"\ts3. Difference distance informed to sato vs distance approximated (x1,y2): {Math.Abs(DistanceFromTo((Point2D)s3.GetCoords(), new Point2D(x1, y2)) - r3)}"); Console.WriteLine($"\ts3. Difference distance informed to sato vs distance approximated (x2,y1): {Math.Abs(DistanceFromTo((Point2D)s3.GetCoords(), new Point2D(x2, y1)) - r3)}"); Console.WriteLine($"\ts3. Difference distance informed to sato vs distance approximated (x2,y2): {Math.Abs(DistanceFromTo((Point2D)s3.GetCoords(), new Point2D(x2, y2)) - r3)}"); Console.WriteLine("\tThe minimum error is in the 3th and 4th combination, and the right combination is the 3th."); Console.ResetColor(); } catch (ArithmeticException e) { Console.WriteLine(e.Message); } return(new Point2D() { X = x2, Y = y1 }); }