|
1 | | -using System.Linq; |
| 1 | +using System; |
| 2 | +using System.Collections.Generic; |
| 3 | +using System.Linq; |
2 | 4 | using System.IO; |
3 | | -using UnityEngine; |
4 | 5 |
|
5 | 6 |
|
6 | | -namespace SigmaRandomPlugin |
| 7 | +namespace SigmaCartographerPlugin |
7 | 8 | { |
8 | | - [KSPAddon(KSPAddon.Startup.MainMenu, false)] |
9 | | - class BodyInfo : MonoBehaviour |
| 9 | + internal static class BodyInfo |
10 | 10 | { |
11 | | - static string[] info = new string[9]; |
| 11 | + static double definition = 0.5; |
| 12 | + static string[] text = new string[16]; |
12 | 13 |
|
13 | | - void Start() |
| 14 | + internal static void GetInfo(ConfigNode bodyInfo) |
14 | 15 | { |
15 | | - UrlDir.UrlConfig[] nodes = GameDatabase.Instance?.GetConfigs("SigmaCartographer"); |
| 16 | + List<string> info = null; |
16 | 17 |
|
17 | | - foreach (var node in nodes) |
| 18 | + if (bodyInfo != null) |
18 | 19 | { |
19 | | - foreach (var bodyInfo in node.config.GetNodes("Info")) |
| 20 | + info = info ?? new List<string>(); |
| 21 | + |
| 22 | + if (!double.TryParse(bodyInfo.GetValue("definition"), out definition)) |
20 | 23 | { |
21 | | - foreach (var bodyName in bodyInfo.GetValues("body")) |
22 | | - { |
23 | | - CelestialBody body = FlightGlobals.Bodies.FirstOrDefault(p => p.transform.name == bodyName); |
24 | | - if (body?.pqsController != null) |
25 | | - { |
26 | | - FirstPass(body); |
27 | | - } |
28 | | - } |
| 24 | + definition = 0.5; |
| 25 | + } |
| 26 | + |
| 27 | + string[] body = bodyInfo.GetValues("body"); |
| 28 | + |
| 29 | + for (int i = 0; i < body.Length; i++) |
| 30 | + { |
| 31 | + if (!info.Contains(body[i])) |
| 32 | + info.Add(body[i]); |
| 33 | + } |
| 34 | + } |
| 35 | + |
| 36 | + if (info != null) |
| 37 | + { |
| 38 | + int n = info.Count; |
| 39 | + |
| 40 | + if (n == 0) |
| 41 | + { |
| 42 | + info = FlightGlobals.Bodies.Select(p => p.transform.name).ToList(); |
| 43 | + n = info.Count(); |
| 44 | + } |
| 45 | + |
| 46 | + for (int i = 0; i < n; i++) |
| 47 | + { |
| 48 | + string bodyName = info[i]; |
| 49 | + CelestialBody body = FlightGlobals.Bodies.FirstOrDefault(p => p.transform.name == bodyName); |
| 50 | + |
| 51 | + if (body?.pqsController != null) |
| 52 | + FirstPass(body); |
29 | 53 | } |
30 | 54 | } |
31 | 55 | } |
32 | 56 |
|
33 | | - void FirstPass(CelestialBody body) |
| 57 | + static void FirstPass(CelestialBody body) |
34 | 58 | { |
35 | | - double lowest = double.MaxValue; |
36 | | - double highest = double.MinValue; |
| 59 | + List<LLA> ALL = new List<LLA>(); |
37 | 60 |
|
38 | | - Vector2d LatLonLo = new Vector2d(); |
39 | | - Vector2d LatLonHi = new Vector2d(); |
| 61 | + double terrain = 0; |
| 62 | + double surface = 0; |
| 63 | + double underwater = 0; |
40 | 64 |
|
41 | | - for (double LON = -180; LON < 180; LON += 0.1) |
| 65 | + for (double LON = -180 + definition / 2; LON < 180; LON += definition) |
42 | 66 | { |
43 | | - for (double LAT = -90; LAT <= 90; LAT += 0.1) |
| 67 | + for (double LAT = -90 + definition / 2; LAT < 90; LAT += definition) |
44 | 68 | { |
45 | 69 | double ALT = body.TerrainAltitude(LAT, LON, true); |
46 | 70 |
|
47 | | - if (ALT < lowest) |
| 71 | + ALL.Add(new LLA(LAT, LON, ALT)); |
| 72 | + |
| 73 | + if (ALT == 0) continue; |
| 74 | + |
| 75 | + double area = Math.PI * (Math.Cos((LAT - definition / 2) / 180 * Math.PI) + Math.Cos((LAT + definition / 2) / 180 * Math.PI)) / (4 * 180 / definition * 360 / definition); |
| 76 | + |
| 77 | + terrain += ALT * area; |
| 78 | + |
| 79 | + if (ALT > 0) |
48 | 80 | { |
49 | | - lowest = ALT; |
50 | | - LatLonLo = new Vector2d(LAT, LON); |
| 81 | + surface += ALT * area; |
51 | 82 | } |
52 | | - if (ALT > highest) |
| 83 | + else |
53 | 84 | { |
54 | | - highest = ALT; |
55 | | - LatLonHi = new Vector2d(LAT, LON); |
| 85 | + underwater += area; |
56 | 86 | } |
57 | 87 | } |
58 | 88 | } |
59 | | - Lowest(body, LatLonLo); |
60 | | - Highest(body, LatLonHi); |
| 89 | + |
| 90 | + Lowest(body, definition, ALL.OrderBy(v => v.alt).Take(100)); |
| 91 | + Highest(body, definition, ALL.OrderByDescending(v => v.alt).Take(100)); |
| 92 | + Print(body, terrain, surface, underwater); |
61 | 93 | } |
62 | 94 |
|
63 | | - void Lowest(CelestialBody body, Vector2d LatLon) |
| 95 | + static void Lowest(CelestialBody body, double delta, IEnumerable<LLA> ALL) |
64 | 96 | { |
65 | | - double altitude = double.MaxValue; |
66 | | - double latitude = LatLon.x; |
67 | | - double longitude = LatLon.y; |
68 | | - |
69 | | - for (double LON = LatLon.y - 0.1; LON <= LatLon.y + 0.1; LON += 0.001) |
| 97 | + if (delta > 0.0001) |
70 | 98 | { |
71 | | - for (double LAT = LatLon.x - 0.1; LAT <= LatLon.x + 0.1; LAT += 0.001) |
| 99 | + List<LLA> BEST = new List<LLA>(); |
| 100 | + |
| 101 | + int n = ALL.Count(); |
| 102 | + |
| 103 | + for (int i = 0; i < n; i++) |
72 | 104 | { |
73 | | - double ALT = body.TerrainAltitude(LAT, LON, true); |
74 | | - if (ALT < altitude) |
| 105 | + LLA LatLon = ALL.ElementAt(i); |
| 106 | + |
| 107 | + for (double LON = LatLon.lon - delta / 2; LON <= LatLon.lon + delta / 2; LON += delta / 10) |
75 | 108 | { |
76 | | - latitude = LAT; |
77 | | - longitude = LON; |
78 | | - altitude = ALT; |
| 109 | + for (double LAT = LatLon.lat - delta / 2; LAT <= LatLon.lat + delta / 2; LAT += delta / 10) |
| 110 | + { |
| 111 | + double ALT = body.TerrainAltitude(LAT, LON, true); |
| 112 | + BEST.Add(new LLA(LAT, LON, ALT)); |
| 113 | + } |
79 | 114 | } |
80 | 115 | } |
| 116 | + |
| 117 | + Lowest(body, delta / 10, BEST.OrderBy(v => v.alt).Take(100)); |
81 | 118 | } |
| 119 | + else |
| 120 | + { |
| 121 | + LLA BEST = ALL.OrderBy(v => v.alt).FirstOrDefault(); |
82 | 122 |
|
83 | | - info[0] = "Lowest Point"; |
84 | | - info[1] = "LAT = " + latitude; |
85 | | - info[2] = "LON = " + longitude; |
86 | | - info[3] = "ALT = " + altitude; |
87 | | - info[4] = ""; |
| 123 | + text[0] = "Lowest Point"; |
| 124 | + text[1] = "LAT = " + BEST.lat; |
| 125 | + text[2] = "LON = " + BEST.lon; |
| 126 | + text[3] = "ALT = " + BEST.alt; |
| 127 | + text[4] = ""; |
| 128 | + } |
88 | 129 | } |
89 | 130 |
|
90 | | - void Highest(CelestialBody body, Vector2d LatLon) |
| 131 | + static void Highest(CelestialBody body, double delta, IEnumerable<LLA> ALL) |
91 | 132 | { |
92 | | - double altitude = double.MinValue; |
93 | | - double latitude = LatLon.x; |
94 | | - double longitude = LatLon.y; |
95 | | - |
96 | | - for (double LON = LatLon.y - 0.1; LON <= LatLon.y + 0.1; LON += 0.001) |
| 133 | + if (delta > 0.001) |
97 | 134 | { |
98 | | - for (double LAT = LatLon.x - 0.1; LAT <= LatLon.x + 0.1; LAT += 0.001) |
| 135 | + List<LLA> BEST = new List<LLA>(); |
| 136 | + |
| 137 | + int n = ALL.Count(); |
| 138 | + |
| 139 | + for (int i = 0; i < n; i++) |
99 | 140 | { |
100 | | - double ALT = body.TerrainAltitude(LAT, LON, true); |
101 | | - if (ALT > altitude) |
| 141 | + LLA LatLon = ALL.ElementAt(i); |
| 142 | + |
| 143 | + for (double LON = LatLon.lon - delta / 2; LON <= LatLon.lon + delta / 2; LON += delta / 10) |
102 | 144 | { |
103 | | - latitude = LAT; |
104 | | - longitude = LON; |
105 | | - altitude = ALT; |
| 145 | + for (double LAT = LatLon.lat - delta / 2; LAT <= LatLon.lat + delta / 2; LAT += delta / 10) |
| 146 | + { |
| 147 | + double ALT = body.TerrainAltitude(LAT, LON, true); |
| 148 | + BEST.Add(new LLA(LAT, LON, ALT)); |
| 149 | + } |
106 | 150 | } |
107 | 151 | } |
| 152 | + |
| 153 | + Highest(body, delta / 10, BEST.OrderByDescending(v => v.alt).Take(100)); |
108 | 154 | } |
| 155 | + else |
| 156 | + { |
| 157 | + LLA BEST = ALL.OrderByDescending(v => v.alt).FirstOrDefault(); |
109 | 158 |
|
110 | | - info[5] = "Highest Point"; |
111 | | - info[6] = "LAT = " + latitude; |
112 | | - info[7] = "LON = " + longitude; |
113 | | - info[8] = "ALT = " + altitude; |
| 159 | + text[5] = "Highest Point"; |
| 160 | + text[6] = "LAT = " + BEST.lat; |
| 161 | + text[7] = "LON = " + BEST.lon; |
| 162 | + text[8] = "ALT = " + BEST.alt; |
| 163 | + text[9] = ""; |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + static void Print(CelestialBody body, double terrain, double surface, double underwater) |
| 168 | + { |
| 169 | + text[10] = "Average Elevation"; |
| 170 | + text[11] = "Terrain = " + terrain; |
| 171 | + |
| 172 | + if (body.ocean) |
| 173 | + { |
| 174 | + text[12] = "Surface = " + surface; |
| 175 | + text[13] = ""; |
| 176 | + text[14] = "Water Coverage = " + Math.Round(100 * underwater, 2) + "%"; |
| 177 | + } |
114 | 178 |
|
115 | 179 | string path = "GameData/Sigma/Cartographer/PluginData/" + body.transform.name + "/"; |
116 | 180 |
|
117 | 181 | Directory.CreateDirectory(path); |
118 | | - File.WriteAllLines(path + "Info.txt", info); |
| 182 | + File.WriteAllLines(path + "Info.txt", text); |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + internal class LLA |
| 187 | + { |
| 188 | + internal double lat; |
| 189 | + internal double lon; |
| 190 | + internal double alt; |
| 191 | + |
| 192 | + internal LLA() |
| 193 | + { |
| 194 | + } |
| 195 | + |
| 196 | + internal LLA(double lat, double lon, double alt) |
| 197 | + { |
| 198 | + this.lat = lat; |
| 199 | + this.lon = lon; |
| 200 | + this.alt = alt; |
119 | 201 | } |
120 | 202 | } |
121 | 203 | } |
0 commit comments