internal override SubRequirementState VesselMeetsCondition(Vessel vessel, EvaluationContext context) { SolarElevationState state = new SolarElevationState(); var vesselPosition = context.VesselPosition(vessel); var mainBodyPosition = context.BodyPosition(vessel.mainBody); var sunPosition = context.BodyPosition(Lib.GetParentSun(vessel.mainBody)); var a = vesselPosition - mainBodyPosition; var b = sunPosition - mainBodyPosition; state.solarElevation = Vector3d.Angle(a, b); state.requirementMet = true; if (min != double.MinValue && state.solarElevation < min) { state.requirementMet = false; } if (max != double.MaxValue && state.solarElevation > max) { state.requirementMet = false; } return(state); }
internal static double GetElevation(Vessel vessel, double lat, double lon, CelestialBody body, EvaluationContext context, int secondsAgo = 0) { Vector3d waypointPosition = context.SurfacePosition(lat, lon, body, secondsAgo); Vector3d bodyPosition = context.BodyPosition(body, secondsAgo); Vector3d vesselPosition = context.VesselPosition(vessel, secondsAgo); var a = Vector3d.Angle(vesselPosition - bodyPosition, waypointPosition - bodyPosition); var b = Vector3d.Angle(waypointPosition - vesselPosition, bodyPosition - vesselPosition); // Utils.LogDebug($"wp {waypointPosition} body {bodyPosition} vessel {vesselPosition} a {a} b {b}"); // a + b + elevation = 90 degrees return(90.0 - a - b); }
internal override bool VesselsMeetCondition(List <Vessel> vessels, EvaluationContext context, out string statusLabel) { if (minSurface == 0 || vessels.Count == 0) { statusLabel = string.Empty; return(vessels.Count > 0); } Vector3d bodyPosition = context.BodyPosition(context.targetBody); double visible = 100.0 * BodySurfaceObservation.VisibleSurface(vessels, context, bodyPosition, minElevation, Surfaces()); string observedPercStr = Lib.HumanReadablePerc(visible / 100.0) + " / " + Lib.HumanReadablePerc(minSurface / 100.0); observedPercStr = Lib.Color(observedPercStr, visible > minSurface ? Lib.Kolor.Green : Lib.Kolor.Red); statusLabel = Localizer.Format("#KerCon_XofSurfaceObserved", observedPercStr); return(visible > minSurface); }
internal override bool VesselsMeetCondition(List <Vessel> vessels, EvaluationContext context, out string statusLabel) { if (minSurface == 0 || vessels.Count == 0) { statusLabel = string.Empty; return(vessels.Count > 0); } double visible; double R = context.targetBody.Radius; if (vessels.Count == 1) { Vessel vessel = vessels[0]; double a = context.Altitude(vessel, context.targetBody); visible = 100.0 * a / (2 * (a + R)); } else { ResetVisibleSurfaces(); Vector3d bodyPosition = context.BodyPosition(context.targetBody); foreach (Vessel v in vessels) { Vector3d vesselPosition = context.VesselPosition(v); Vector3d viewDirection = (vesselPosition - bodyPosition); double a = R; double b = R + context.Altitude(v, context.targetBody); double c = Math.Sqrt(a * a + b * b); double α = Math.Asin(b / c) * 180.0 / Math.PI; MarkVisibleSurfaces(viewDirection.normalized, α); } visible = 100.0 * visibleSurfaces / (double)surfaces.Count; } string observedPercStr = Lib.HumanReadablePerc(visible / 100.0) + " / " + Lib.HumanReadablePerc(minSurface / 100.0); observedPercStr = Lib.Color(observedPercStr, visible > minSurface ? Lib.Kolor.Green : Lib.Kolor.Red); statusLabel = Localizer.Format("<<1>> of surface observed", observedPercStr); return(visible > minSurface); }
private void UpdateSunObservationStatus() { // determine sun surface observation status for all suns in the system vesselsPerSun.Clear(); foreach (var entries in EquipmentStates.states) { foreach (var e in entries.Value) { if (e.id == Configuration.SunObservationEquipment && e.value == EquipmentState.nominal) { Vessel v = FlightGlobals.FindVessel(entries.Key); if (v != null) { var sun = Sim.GetParentStar(v.mainBody); if (!vesselsPerSun.ContainsKey(sun)) { vesselsPerSun[sun] = new List <Vessel>(); } vesselsPerSun[sun].Add(v); } } } } foreach (var e in vesselsPerSun) { var sun = e.Key; var vessels = e.Value; if (solarSurfaces == null) { solarSurfaces = BodySurfaceObservation.CreateVisibleSurfaces(); } var context = new EvaluationContext(GetUniverseEvaluator(), null, sun); context.SetTime(Planetarium.GetUniversalTime()); Vector3d sunPosition = context.BodyPosition(sun); var observedSurface = (float)BodySurfaceObservation.VisibleSurface(vessels, context, sunPosition, Configuration.MinSunObservationAngle, solarSurfaces); API.SetStormObservationQuality(sun, observedSurface); Utils.LogDebug($"Solar surface observation for {sun.displayName}: {(observedSurface * 100.0).ToString("F2")}%"); } }
internal override SubRequirementState VesselMeetsCondition(Vessel vessel, EvaluationContext context) { ObserveBodyState state = new ObserveBodyState(); var body = context.targetBody; // generate ray parameters var vesselPosition = context.VesselPosition(vessel); var bodyDir = context.BodyPosition(body) - vesselPosition; state.distance = bodyDir.magnitude; bodyDir /= state.distance; state.distance -= body.Radius; double distance = maxDistance; if (distance == 0 && maxDistanceAU != 0) { distance = Sim.AU * maxDistanceAU; } if (distance != 0 && state.distance > distance) { state.requirementMet = false; return(state); } if (minAngularVelocity > 0 || maxAngularVelocity > 0) { var elevation = AboveWaypoint.GetElevation(vessel, 0, 0, context.targetBody, context); var elevation10s = AboveWaypoint.GetElevation(vessel, 0, 0, context.targetBody, context, 10); state.angularVelocity = Math.Abs((elevation10s - elevation) * 6.0); // radial velocity is in degrees/minute state.angularRequirementMet = true; if (minAngularVelocity > 0) { state.angularRequirementMet &= state.angularVelocity >= minAngularVelocity; } if (maxAngularVelocity > 0) { state.angularRequirementMet &= state.angularVelocity <= maxAngularVelocity; } state.requirementMet &= state.angularRequirementMet; } VesselData vd; if (!vessel.TryGetVesselData(out vd)) { state.requirementMet = false; return(state); } // check if the ray intersects with an occluder foreach (CelestialBody occludingBody in vd.EnvVisibleBodies) { if (occludingBody == body) { continue; } if (!Sim.RayAvoidBody(vesselPosition, bodyDir, state.distance, occludingBody)) { state.occluder = occludingBody; state.requirementMet = false; return(state); } } state.requirementMet = true; return(state); }