Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #4
0
        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")}%");
            }
        }
Exemple #6
0
        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);
        }