private static void drawVesselLabel(Rect maprect, SCANmap map, int num, Vessel vessel) { double lon = (vessel.longitude + 360 + 180) % 360; double lat = (vessel.latitude + 180 + 90) % 180; if(map != null) { lat = (map.projectLatitude(vessel.longitude, vessel.latitude) + 90) % 180; lon = (map.projectLongitude(vessel.longitude, vessel.latitude) + 180) % 360; lat = map.scaleLatitude(lat); lon = map.scaleLongitude(lon); if(lat < 0 || lon < 0 || lat > 180 || lon > 360) return; } lon = lon * maprect.width / 360f; lat = maprect.height - lat * maprect.height / 180f; string txt = num.ToString(); if(num == 0) txt = vessel.vesselName; else if(num < 0) txt = ""; Rect r = new Rect(maprect.x + (float)lon, maprect.y + (float)lat, 250f, 25f); Color col = Color.white; if(SCANcontroller.controller.colours == 1 && vessel != FlightGlobals.ActiveVessel) col = cb_skyBlue; if(vessel == FlightGlobals.ActiveVessel && (int)(Time.realtimeSinceStartup % 2) == 0) { col = cb_yellow; } int sz = 16; if(vessel.vesselType == VesselType.Flag) sz = 24; drawOrbitIcon((int)r.x, (int)r.y, orbitIconForVesselType(vessel.vesselType), col, sz, true); if(maprect.width < 360) return; r.x += 12; drawLabel(r, col, txt, true, true); }
private static void drawAnomalyLabel(Rect maprect, SCANmap map, SCANdata.SCANanomaly anomaly) { if(!anomaly.known) return; double lon = (anomaly.longitude + 360 + 180) % 360; double lat = (anomaly.latitude + 180 + 90) % 180; if(map != null) { lat = (map.projectLatitude(anomaly.longitude, anomaly.latitude) + 90) % 180; lon = (map.projectLongitude(anomaly.longitude, anomaly.latitude) + 180) % 360; lat = map.scaleLatitude(lat); lon = map.scaleLongitude(lon); if(lat < 0 || lon < 0 || lat > 180 || lon > 360) return; } lon = lon * maprect.width / 360f; lat = maprect.height - lat * maprect.height / 180f; string txt = SCANcontroller.controller.anomalyMarker + " " + anomaly.name; if(!anomaly.detail) txt = SCANcontroller.controller.anomalyMarker + " Anomaly"; Rect r = new Rect(maprect.x + (float)lon, maprect.y + (float)lat, 250f, 25f); drawLabel(r, cb_yellow, txt, true, true); }
private static void drawOrbit(Rect maprect, SCANmap map, Vessel vessel) { if(vessel.LandedOrSplashed) return; bool lite = maprect.width < 400; Orbit o = vessel.orbit; startUT = Planetarium.GetUniversalTime(); double UT = startUT; int steps = 100; // increase for neater lines, decrease for better speed indication bool ath = false; if(vessel.mainBody.atmosphere) { if(vessel.mainBody.maxAtmosphereAltitude >= vessel.altitude) { ath = true; } } Rect r = new Rect(0, 0, 50f, 50f); Color col; // project the last and the current orbital period onto the map for(int i=-steps; i<steps; ++i) { if(i < 0) UT = startUT - (steps + i) * (o.period / steps); else UT = startUT + i * o.period * 1f / steps; if(double.IsNaN(UT)) continue; if(UT < o.StartUT && o.StartUT != startUT) continue; if(UT > o.EndUT) continue; if(double.IsNaN(o.getObtAtUT(UT))) continue; Vector3d pos = o.getPositionAtUT(UT); double rotation = 0; if(vessel.mainBody.rotates) { rotation = (360 * ((UT - startUT) / vessel.mainBody.rotationPeriod)) % 360; } double alt = (vessel.mainBody.GetAltitude(pos)); if(alt < 0) { if(i < 0) { i = 0; continue; } break; } double lo = (vessel.mainBody.GetLongitude(pos) - rotation); double la = (vessel.mainBody.GetLatitude(pos)); double lon = (map.projectLongitude(lo, la) + 180) % 360; double lat = (map.projectLatitude(lo, la) + 90) % 180; lat = map.scaleLatitude(lat); lon = map.scaleLongitude(lon); if(lat < 0 || lon < 0 || lat > 180 || lon > 360) continue; lon = lon * maprect.width / 360f; lat = maprect.height - lat * maprect.height / 180f; r.x = maprect.x + (float)lon; r.y = maprect.y + (float)lat; col = cb_skyBlue; if(i < 0) { col = cb_orange; } else { if(vessel.mainBody.atmosphere) { if(vessel.mainBody.maxAtmosphereAltitude >= alt) { if(!ath) { ath = true; // do something when it flips? } col = cb_reddishPurple; } } } drawOrbitIcon((int)r.x, (int)r.y, OrbitIcon.Planet, col, 8, false); } // show apoapsis and periapsis if(o.ApA > 0 && mapPosAtT(maprect, map, ref r, vessel, o, o.timeToAp)) { drawOrbitIcon((int)r.x, (int)r.y, OrbitIcon.Ap, cb_skyBlue, 32, true); r.x += 24; r.y -= 12; if(!lite) drawLabel(r, cb_skyBlue, o.ApA.ToString("N1"), true, true); } if(o.PeA > 0 && mapPosAtT(maprect, map, ref r, vessel, o, o.timeToPe)) { drawOrbitIcon((int)r.x, (int)r.y, OrbitIcon.Pe, cb_skyBlue, 32, true); r.x += 24; r.y -= 12; if(!lite) drawLabel(r, cb_skyBlue, o.PeA.ToString("N1"), true, true); } if(lite) return; // show first maneuver node if(vessel.patchedConicSolver.maneuverNodes.Count > 0) { ManeuverNode n = vessel.patchedConicSolver.maneuverNodes[0]; if(n.patch == vessel.orbit && n.nextPatch != null && n.nextPatch.activePatch && n.UT > startUT - o.period && mapPosAtT(maprect, map, ref r, vessel, o, n.UT - startUT)) { col = cb_reddishPurple; if(SCANcontroller.controller.colours != 1) col = XKCDColors.PurplyPink; drawOrbitIcon((int)r.x, (int)r.y, OrbitIcon.ManeuverNode, col, 32, true); Orbit nuo = n.nextPatch; for(int i=0; i<steps; ++i) { double T = n.UT - startUT + i * nuo.period / steps; if(T + startUT > nuo.EndUT) break; if(mapPosAtT(maprect, map, ref r, vessel, nuo, T)) { drawOrbitIcon((int)r.x, (int)r.y, OrbitIcon.Planet, col, 8, false); } } if(nuo.patchEndTransition == Orbit.PatchTransitionType.ESCAPE) { drawOrbitIcon((int)r.x, (int)r.y, OrbitIcon.Exit, col, 32, true); } else if(nuo.patchEndTransition == Orbit.PatchTransitionType.ENCOUNTER) { drawOrbitIcon((int)r.x, (int)r.y, OrbitIcon.Encounter, col, 32, true); } if(nuo.timeToAp > 0 && n.UT + nuo.timeToAp < nuo.EndUT && mapPosAtT(maprect, map, ref r, vessel, nuo, n.UT - startUT + nuo.timeToAp)) { drawOrbitIcon((int)r.x, (int)r.y, OrbitIcon.Ap, col, 32, true); } if(nuo.timeToPe > 0 && n.UT + nuo.timeToPe < nuo.EndUT && mapPosAtT(maprect, map, ref r, vessel, nuo, n.UT - startUT + nuo.timeToPe)) { drawOrbitIcon((int)r.x, (int)r.y, OrbitIcon.Pe, col, 32, true); } } } if(o.PeA < 0) return; if(overlay_static == null) return; if(map.projection == SCANmap.MapProjection.Polar) return; if(eq_frame <= 0) { // predict equatorial crossings for the next 100 loops double TAAN = 360f - o.argumentOfPeriapsis; // true anomaly at ascending node double TADN = (TAAN + 180) % 360; // true anomaly at descending node double MAAN = meanForTrue(TAAN, o.eccentricity); double MADN = meanForTrue(TADN, o.eccentricity); double tAN = (((MAAN - o.meanAnomaly * Mathf.Rad2Deg + 360) % 360) / 360f * o.period + startUT); double tDN = (((MADN - o.meanAnomaly * Mathf.Rad2Deg + 360) % 360) / 360f * o.period + startUT); int eqh = 16; if(eq_an_map == null || eq_dn_map == null || eq_an_map.Length != overlay_static.width) { eq_an_map = new int[overlay_static.width]; eq_dn_map = new int[overlay_static.width]; } if(eq_map == null || eq_map.width != eq_an_map.Length) { eq_map = new Texture2D(eq_an_map.Length, eqh, TextureFormat.ARGB32, false); } for(int i=0; i<eq_an_map.Length; ++i) { eq_an_map[i] = 0; eq_dn_map[i] = 0; } for(int i=0; i<100; ++i) { double UTAN = tAN + o.period * i; double UTDN = tDN + o.period * i; if(double.IsNaN(UTAN) || double.IsNaN(UTDN)) continue; Vector3d pAN = o.getPositionAtUT(UTAN); Vector3d pDN = o.getPositionAtUT(UTDN); double rotAN = 0, rotDN = 0; if(vessel.mainBody.rotates) { rotAN = ((360 * ((UTAN - startUT) / vessel.mainBody.rotationPeriod)) % 360); rotDN = ((360 * ((UTDN - startUT) / vessel.mainBody.rotationPeriod)) % 360); } double loAN = vessel.mainBody.GetLongitude(pAN) - rotAN; double loDN = vessel.mainBody.GetLongitude(pDN) - rotDN; int lonAN = (int)(((map.projectLongitude(loAN, 0) + 180) % 360) * eq_an_map.Length / 360f); int lonDN = (int)(((map.projectLongitude(loDN, 0) + 180) % 360) * eq_dn_map.Length / 360f); if(lonAN >= 0 && lonAN < eq_an_map.Length) eq_an_map[lonAN] += 1; if(lonDN >= 0 && lonDN < eq_dn_map.Length) eq_dn_map[lonDN] += 1; } Color[] pix = eq_map.GetPixels(0, 0, eq_an_map.Length, eqh); Color cAN = cb_skyBlue, cDN = cb_orange; for(int y = 0; y < eqh; ++y) { Color lc = Color.clear; for(int x = 0; x < eq_an_map.Length; ++x) { Color c = Color.clear; float scale = 0; if(y < eqh / 2) { c = cDN; scale = eq_dn_map[x]; } else { c = cAN; scale = eq_an_map[x]; } if(scale >= 1) { if(y == 0 || y == eqh - 1) { c = Color.black; } else { if(lc == Color.clear) pix[y * eq_an_map.Length + x - 1] = Color.black; scale = Mathf.Clamp(scale - 1, 0, 10) / 10f; c = Color.Lerp(c, Color.white, scale); } } else { c = Color.clear; if(lc != Color.clear && lc != Color.black) c = Color.black; } pix[y * eq_an_map.Length + x] = c; lc = c; } } eq_map.SetPixels(0, 0, eq_an_map.Length, eqh, pix); eq_map.Apply(); eq_frame = 4; } else { eq_frame -= 1; } if(eq_map != null) { r.x = maprect.x; r.y = maprect.y + maprect.height / 2 + - eq_map.height / 2; r.width = eq_map.width; r.height = eq_map.height; GUI.DrawTexture(r, eq_map); } }
private static bool mapPosAtT(Rect maprect, SCANmap map, ref Rect r, Vessel vessel, Orbit o, double dT) { double UT = startUT + dT; if(double.IsNaN(UT)) return false; try { if(double.IsNaN(o.getObtAtUT(UT))) return false; Vector3d pos = o.getPositionAtUT(UT); double rotation = 0; if(vessel.mainBody.rotates) { rotation = (360 * (dT / vessel.mainBody.rotationPeriod)) % 360; } double lo = (vessel.mainBody.GetLongitude(pos) - rotation); double la = (vessel.mainBody.GetLatitude(pos)); double lon = (map.projectLongitude(lo, la) + 180) % 360; double lat = (map.projectLatitude(lo, la) + 90) % 180; lat = map.scaleLatitude(lat); lon = map.scaleLongitude(lon); if(lat < 0 || lon < 0 || lat > 180 || lon > 360) return false; lon = lon * maprect.width / 360f; lat = maprect.height - lat * maprect.height / 180f; r.x = maprect.x + (float)lon; r.y = maprect.y + (float)lat; return true; } catch(Exception) { return false; } }