Exemple #1
0
        /// <summary>
        /// The True Anomaly in radians
        /// https://en.wikipedia.org/wiki/True_anomaly#From_state_vectors
        /// </summary>
        /// <returns>The True Anomaly in radians</returns>
        /// <param name="eccentVector">Eccentricity vector.</param>
        /// <param name="position">Position ralitive to parent</param>
        /// <param name="velocity">Velocity ralitive to parent</param>
        public static double TrueAnomaly(Vector3 eccentVector, Vector3 position, Vector3 velocity)
        {
            double e = eccentVector.Length(); //eccentricity
            double r = position.Length();

            if (e > Epsilon) //if eccentricity is bigger than a tiny amount, it's a circular orbit.
            {
                double dotEccPos = Vector3.Dot(eccentVector, position);
                double talen     = e * r;
                talen = dotEccPos / talen;
                talen = GMath.Clamp(talen, -1, 1);
                var trueAnomoly = Math.Acos(talen);

                if (Vector3.Dot(position, velocity) < 0)
                {
                    trueAnomoly = Math.PI * 2 - trueAnomoly;
                }

                return(Angle.NormaliseRadiansPositive(trueAnomoly));
            }
            else
            {
                return(Angle.NormaliseRadiansPositive(Math.Atan2(position.Y, position.X))); //circular orbit, assume AoP is 0;
            }
        }
Exemple #2
0
        internal static void MineResources(Entity colonyEntity)
        {
            Dictionary <Guid, int> mineRates = colonyEntity.GetDataBlob <ColonyMinesDB>().MineingRate;
            Dictionary <Guid, MineralDepositInfo> planetMinerals = colonyEntity.GetDataBlob <ColonyInfoDB>().PlanetEntity.GetDataBlob <SystemBodyInfoDB>().Minerals;
            //Dictionary<Guid, int> colonyMineralStockpile = colonyEntity.GetDataBlob<ColonyInfoDB>().MineralStockpile;
            CargoStorageDB stockpile   = colonyEntity.GetDataBlob <CargoStorageDB>();
            float          mineBonuses = 1;//colonyEntity.GetDataBlob<ColonyBonusesDB>().GetBonus(AbilityType.Mine);

            foreach (var kvp in mineRates)
            {
                double accessability = planetMinerals[kvp.Key].Accessibility;
                double actualRate    = kvp.Value * mineBonuses * accessability;
                int    mineralsMined = (int)Math.Min(actualRate, planetMinerals[kvp.Key].Amount);
                long   capacity      = StorageSpaceProcessor.RemainingCapacity(stockpile, stockpile.CargoTypeID(kvp.Key));
                if (capacity > 0)
                {
                    //colonyMineralStockpile.SafeValueAdd<Guid>(kvp.Key, mineralsMined);
                    StorageSpaceProcessor.AddItemToCargo(stockpile, kvp.Key, mineralsMined);
                    MineralDepositInfo mineralDeposit = planetMinerals[kvp.Key];
                    int newAmount = mineralDeposit.Amount -= mineralsMined;

                    accessability = Math.Pow((float)mineralDeposit.Amount / mineralDeposit.HalfOriginalAmount, 3) * mineralDeposit.Accessibility;
                    double newAccess = GMath.Clamp(accessability, 0.1, mineralDeposit.Accessibility);

                    mineralDeposit.Amount        = newAmount;
                    mineralDeposit.Accessibility = newAccess;
                }
            }
        }
Exemple #3
0
        public static double GetEccentricAnomalyFromStateVectors(Vector3 position, double semiMajAxis, double linierEccentricity, double aop)
        {
            var x = (position.X * Math.Cos(-aop)) - (position.Y * Math.Sin(-aop));

            x = linierEccentricity + x;
            double foo = GMath.Clamp(x / semiMajAxis, -1, 1); //because sometimes we were getting a floating point error that resulted in numbers infinatly smaller than -1

            return(Math.Acos(foo));
        }
Exemple #4
0
        public static void UpdateAtmosphere(AtmosphereDB atmoDB, SystemBodyInfoDB bodyDB)
        {
            if (atmoDB.Exists)
            {
                // clear old values.
                atmoDB.Pressure           = 0;
                atmoDB.GreenhousePressure = 0;

                foreach (var gas in atmoDB.Composition)
                {
                    atmoDB.Pressure += gas.Value;

                    // only add a greenhouse gas if it is not frozen or liquid:
                    if (atmoDB.SurfaceTemperature >= gas.Key.BoilingPoint)
                    {
                        // actual greenhouse pressure adjusted by gas GreenhouseEffect.
                        // note that this produces the same affect as in aurora if all GreenhouseEffect bvalue are -1, 0 or 1.
                        atmoDB.GreenhousePressure += (float)gas.Key.GreenhouseEffect * gas.Value;
                    }
                }

                if (bodyDB.BodyType == BodyType.GasDwarf ||
                    bodyDB.BodyType == BodyType.GasGiant ||
                    bodyDB.BodyType == BodyType.IceGiant)
                {
                    // special gas giant stuff, needed because we do not apply greenhouse factor to them:
                    atmoDB.SurfaceTemperature = bodyDB.BaseTemperature * (1 - atmoDB.Albedo);
                    atmoDB.Pressure           = 1; // because thats the definition of the surface of these planets, when
                    // atmosphereic pressure = the pressure of earths atmosphere at its surface (what we call 1 atm).
                }
                else
                {
                    // From Aurora: Greenhouse Factor = 1 + (Atmospheric Pressure /10) + Greenhouse Pressure   (Maximum = 3.0)
                    atmoDB.GreenhouseFactor = (atmoDB.Pressure * 0.035F) + atmoDB.GreenhousePressure;  // note that we do without the extra +1 as it seems to give us better temps.
                    atmoDB.GreenhouseFactor = (float)GMath.Clamp(atmoDB.GreenhouseFactor, -3.0, 3.0);

                    // From Aurora: Surface Temperature in Kelvin = Base Temperature in Kelvin x Greenhouse Factor x Albedo
                    atmoDB.SurfaceTemperature  = Temperature.ToKelvin(bodyDB.BaseTemperature);
                    atmoDB.SurfaceTemperature += atmoDB.SurfaceTemperature * atmoDB.GreenhouseFactor * (float)Math.Pow(1 - atmoDB.Albedo, 0.25);   // We need to raise albedo to the power of 1/4, see: http://en.wikipedia.org/wiki/Stefan%E2%80%93Boltzmann_law
                    atmoDB.SurfaceTemperature  = Temperature.ToCelsius(atmoDB.SurfaceTemperature);
                }
            }
            else
            {
                // simply apply albedo, see here: http://en.wikipedia.org/wiki/Stefan%E2%80%93Boltzmann_law
                atmoDB.Pressure           = 0;
                atmoDB.SurfaceTemperature = Temperature.ToKelvin(bodyDB.BaseTemperature);
                atmoDB.SurfaceTemperature = atmoDB.SurfaceTemperature * (float)Math.Pow(1 - atmoDB.Albedo, 0.25);   // We need to raise albedo to the power of 1/4
            }

            // update the descriptions:
            atmoDB.GenerateDescriptions();
        }
Exemple #5
0
        /*
         * /// <summary>
         * /// The True Anomaly in radians
         * /// </summary>
         * /// <returns>The anomaly.</returns>
         * /// <param name="position">Position.</param>
         * /// <param name="loP">Lo p.</param>
         * public static double TrueAnomaly(Vector4 position, double loP)
         * {
         *  return Math.Atan2(position.Y, position.X) - loP;
         * }
         */
        /// <summary>
        /// The True Anomaly in radians
        /// https://en.wikipedia.org/wiki/True_anomaly#From_state_vectors
        /// </summary>
        /// <returns>The True Anomaly in radians</returns>
        /// <param name="eccentVector">Eccentricity vector.</param>
        /// <param name="position">Position ralitive to parent</param>
        /// <param name="velocity">Velocity ralitive to parent</param>
        public static double TrueAnomaly(Vector3 eccentVector, Vector3 position, Vector3 velocity)
        {
            var dotEccPos = Vector3.Dot(eccentVector, position);
            var talen     = eccentVector.Length() * position.Length();

            talen = dotEccPos / talen;
            talen = GMath.Clamp(talen, -1, 1);
            var trueAnomoly = Math.Acos(talen);

            if (Vector3.Dot(position, velocity) < 0)
            {
                trueAnomoly = Math.PI * 2 - trueAnomoly;
            }

            return(trueAnomoly);
        }
        private void MineResources(Entity colonyEntity)
        {
            Dictionary <Guid, int> mineRates = colonyEntity.GetDataBlob <MiningDB>().MineingRate;
            Dictionary <Guid, MineralDepositInfo> planetMinerals = colonyEntity.GetDataBlob <ColonyInfoDB>().PlanetEntity.GetDataBlob <SystemBodyInfoDB>().Minerals;

            VolumeStorageDB stockpile   = colonyEntity.GetDataBlob <VolumeStorageDB>();
            float           mineBonuses = 1;//colonyEntity.GetDataBlob<ColonyBonusesDB>().GetBonus(AbilityType.Mine);

            foreach (var kvp in mineRates)
            {
                ICargoable mineral         = _minerals[kvp.Key];
                Guid       cargoTypeID     = mineral.CargoTypeID;
                double     itemMassPerUnit = mineral.MassPerUnit;

                double accessability        = planetMinerals[kvp.Key].Accessibility;
                double actualRate           = kvp.Value * mineBonuses * accessability;
                int    unitsMinableThisTick = (int)Math.Min(actualRate, planetMinerals[kvp.Key].Amount);

                if (!stockpile.TypeStores.ContainsKey(mineral.CargoTypeID))
                {
                    var    type  = StaticRefLib.StaticData.CargoTypes[mineral.CargoTypeID];
                    string erstr = "We didn't mine a potential " + unitsMinableThisTick + " of " + mineral.Name + " because we have no way to store " + type.Name + " cargo.";
                    StaticRefLib.EventLog.AddPlayerEntityErrorEvent(colonyEntity, erstr);
                    continue;    //can't store this mineral
                }

                var unitsMinedThisTick = stockpile.AddCargoByUnit(mineral, unitsMinableThisTick);

                if (unitsMinableThisTick > unitsMinedThisTick)
                {
                    var    dif   = unitsMinableThisTick - unitsMinedThisTick;
                    var    type  = StaticRefLib.StaticData.CargoTypes[mineral.CargoTypeID];
                    string erstr = "We didn't mine a potential " + dif + " of " + mineral.Name + " because we don't have enough space to store it.";
                    StaticRefLib.EventLog.AddPlayerEntityErrorEvent(colonyEntity, erstr);
                }

                MineralDepositInfo mineralDeposit = planetMinerals[kvp.Key];
                int newAmount = mineralDeposit.Amount -= unitsMinedThisTick;

                accessability = Math.Pow((float)mineralDeposit.Amount / mineralDeposit.HalfOriginalAmount, 3) * mineralDeposit.Accessibility;
                double newAccess = GMath.Clamp(accessability, 0.1, mineralDeposit.Accessibility);

                mineralDeposit.Amount        = newAmount;
                mineralDeposit.Accessibility = newAccess;
            }
        }
Exemple #7
0
        /// <summary>
        /// This returns the heading mesured from the periapsis (AoP) and is on the plane of the object
        /// Add the LoP to this to get the true heading in a 2d orbit.
        /// </summary>
        /// <returns>The from periaps.</returns>
        /// <param name="pos">Position.</param>
        /// <param name="eccentcity">Eccentcity.</param>
        /// <param name="semiMajorAxis">Semi major axis.</param>
        /// <param name="trueAnomaly">True anomaly.</param>
        public static double HeadingFromPeriaps(Vector3 pos, double eccentcity, double semiMajorAxis, double trueAnomaly)
        {
            double r = pos.Length();
            double a = semiMajorAxis;
            double e = eccentcity;
            double k = r / a;
            double f = trueAnomaly;

            double bar   = ((2 - 2 * e * e) / (k * (2 - k))) - 1;
            double foo   = GMath.Clamp(bar, -1, 1);
            double alpha = Math.Acos(foo);

            if (trueAnomaly > Math.PI || trueAnomaly < 0)
            {
                alpha = -alpha;
            }
            double heading = f + ((Math.PI - alpha) / 2);

            return(heading);
        }
        private void MineResources(Entity colonyEntity)
        {
            Dictionary <Guid, int> mineRates = colonyEntity.GetDataBlob <MiningDB>().MineingRate;
            Dictionary <Guid, MineralDepositInfo> planetMinerals = colonyEntity.GetDataBlob <ColonyInfoDB>().PlanetEntity.GetDataBlob <SystemBodyInfoDB>().Minerals;

            CargoStorageDB stockpile   = colonyEntity.GetDataBlob <CargoStorageDB>();
            float          mineBonuses = 1;//colonyEntity.GetDataBlob<ColonyBonusesDB>().GetBonus(AbilityType.Mine);

            foreach (var kvp in mineRates)
            {
                ICargoable mineral         = _minerals[kvp.Key];
                Guid       cargoTypeID     = mineral.CargoTypeID;
                int        itemMassPerUnit = mineral.Mass;


                double accessability         = planetMinerals[kvp.Key].Accessibility;
                double actualRate            = kvp.Value * mineBonuses * accessability;
                int    amountMinableThisTick = (int)Math.Min(actualRate, planetMinerals[kvp.Key].Amount);

                long freeCapacity = stockpile.StoredCargoTypes[mineral.CargoTypeID].FreeCapacity;

                long weightMinableThisTick = itemMassPerUnit * amountMinableThisTick;
                weightMinableThisTick = Math.Min(weightMinableThisTick, freeCapacity);

                int  actualAmountToMineThisTick = (int)(weightMinableThisTick / itemMassPerUnit);                                        //get the number of items from the mass transferable
                long actualweightMinaedThisTick = actualAmountToMineThisTick * itemMassPerUnit;

                StorageSpaceProcessor.AddCargo(stockpile, mineral, actualAmountToMineThisTick);

                MineralDepositInfo mineralDeposit = planetMinerals[kvp.Key];
                int newAmount = mineralDeposit.Amount -= actualAmountToMineThisTick;

                accessability = Math.Pow((float)mineralDeposit.Amount / mineralDeposit.HalfOriginalAmount, 3) * mineralDeposit.Accessibility;
                double newAccess = GMath.Clamp(accessability, 0.1, mineralDeposit.Accessibility);

                mineralDeposit.Amount        = newAmount;
                mineralDeposit.Accessibility = newAccess;
            }
        }
Exemple #9
0
        /// <summary>
        /// Heading on the orbital plane.
        /// </summary>
        /// <returns>The from periaps.</returns>
        /// <param name="pos">Position.</param>
        /// <param name="eccentricity">Eccentricity.</param>
        /// <param name="semiMajAxis">Semi major axis.</param>
        /// <param name="trueAnomaly">True anomaly.</param>
        /// <param name="aoP">Argument Of Periapsis</param>
        ///
        public static double ObjectLocalHeading(Vector3 pos, double eccentricity, double semiMajAxis, double trueAnomaly, double aoP)
        {
            double r = pos.Length();
            double a = semiMajAxis;
            double e = eccentricity;
            double k = r / a;
            double f = trueAnomaly;

            double bar   = ((2 - 2 * e * e) / (k * (2 - k))) - 1;
            double foo   = GMath.Clamp(bar, -1, 1);
            double alpha = Math.Acos(foo);

            if (trueAnomaly > Math.PI || trueAnomaly < 0)
            {
                alpha = -alpha;
            }
            double heading = ((Math.PI - alpha) / 2) + f;

            heading += aoP;
            Angle.NormaliseRadiansPositive(heading);
            return(heading);
        }
Exemple #10
0
        /// <summary>
        /// In calculation this is referred to as RAAN or LoAN or Ω
        /// </summary>
        /// <param name="nodeVector">The node vector of the Kepler elements</param>
        /// <returns>Radians as a double</returns>
        public static double CalculateLongitudeOfAscendingNode(Vector3 nodeVector)
        {
            double longitudeOfAscendingNodeLength = nodeVector.X / nodeVector.Length();

            if (double.IsNaN(longitudeOfAscendingNodeLength))
            {
                longitudeOfAscendingNodeLength = 0;
            }
            else
            {
                longitudeOfAscendingNodeLength = GMath.Clamp(longitudeOfAscendingNodeLength, -1, 1);
            }

            double longitudeOfAscendingNode = 0;

            if (longitudeOfAscendingNodeLength != 0)
            {
                longitudeOfAscendingNode = Math.Acos(longitudeOfAscendingNodeLength);
            }

            return(longitudeOfAscendingNode);
        }
Exemple #11
0
        /// <summary>
        /// Kepler elements from velocity and position.
        /// </summary>
        /// <returns>a struct of Kepler elements.</returns>
        /// <param name="standardGravParam">Standard grav parameter.</param>
        /// <param name="position">Position ralitive to parent</param>
        /// <param name="velocity">Velocity ralitive to parent</param>
        public static KeplerElements KeplerFromPositionAndVelocity(double standardGravParam, Vector3 position, Vector3 velocity, DateTime epoch)
        {
            KeplerElements ke = new KeplerElements();
            Vector3        angularVelocity = Vector3.Cross(position, velocity);
            Vector3        nodeVector      = Vector3.Cross(new Vector3(0, 0, 1), angularVelocity);

            Vector3 eccentVector = EccentricityVector(standardGravParam, position, velocity);

            //Vector4 eccentVector2 = EccentricityVector2(standardGravParam, position, velocity);

            double eccentricity = eccentVector.Length();

            double specificOrbitalEnergy = Math.Pow(velocity.Length(), 2) * 0.5 - standardGravParam / position.Length();


            double semiMajorAxis;
            double p;                                                                //p is where the ellipse or hypobola crosses a line from the focal point 90 degrees from the sma

            if (Math.Abs(eccentricity) > 1)                                          //hypobola
            {
                semiMajorAxis = -(-standardGravParam / (2 * specificOrbitalEnergy)); //in this case the sma is negitive
                p             = semiMajorAxis * (1 - eccentricity * eccentricity);
            }
            else if (Math.Abs(eccentricity) < 1) //ellipse
            {
                semiMajorAxis = -standardGravParam / (2 * specificOrbitalEnergy);
                p             = semiMajorAxis * (1 - eccentricity * eccentricity);
            }
            else //parabola
            {
                p             = angularVelocity.Length() * angularVelocity.Length() / standardGravParam;
                semiMajorAxis = double.MaxValue;
            }

            /*
             * if (Math.Abs(eccentricity - 1.0) > 1e-15)
             * {
             *  semiMajorAxis = -standardGravParam / (2 * specificOrbitalEnergy);
             *  p = semiMajorAxis * (1 - eccentricity * eccentricity);
             * }
             * else //parabola
             * {
             *  p = angularVelocity.Length() * angularVelocity.Length() / standardGravParam;
             *  semiMajorAxis = double.MaxValue;
             * }
             */

            double semiMinorAxis      = EllipseMath.SemiMinorAxis(semiMajorAxis, eccentricity);
            double linierEccentricity = eccentricity * semiMajorAxis;

            double inclination = Math.Acos(angularVelocity.Z / angularVelocity.Length()); //should be 0 in 2d. or pi if counter clockwise orbit.

            if (double.IsNaN(inclination))
            {
                inclination = 0;
            }

            double loANlen   = nodeVector.X / nodeVector.Length();
            double longdOfAN = 0;

            if (double.IsNaN(loANlen))
            {
                loANlen = 0;
            }
            else
            {
                loANlen = GMath.Clamp(loANlen, -1, 1);
            }
            if (loANlen != 0)
            {
                longdOfAN = Math.Acos(loANlen); //RAAN or LoAN or Ω
            }
            double eccentricAnomoly = GetEccentricAnomalyFromStateVectors2(standardGravParam, semiMajorAxis, position, velocity);

            double trueAnomaly  = TrueAnomalyFromEccentricAnomaly(eccentricity, eccentricAnomoly);
            double argOfPeriaps = ArgumentOfPeriapsis2(position, inclination, longdOfAN, trueAnomaly);

            var meanMotion = Math.Sqrt(standardGravParam / Math.Pow(semiMajorAxis, 3));

            var meanAnomaly = eccentricAnomoly - eccentricity * Math.Sin(eccentricAnomoly);

            ke.SemiMajorAxis = semiMajorAxis;
            ke.SemiMinorAxis = semiMinorAxis;
            ke.Eccentricity  = eccentricity;

            ke.Apoapsis           = EllipseMath.Apoapsis(eccentricity, semiMajorAxis);
            ke.Periapsis          = EllipseMath.Periapsis(eccentricity, semiMajorAxis);
            ke.LinierEccentricity = EllipseMath.LinierEccentricity(ke.Apoapsis, semiMajorAxis);
            ke.LoAN               = longdOfAN;
            ke.AoP                = argOfPeriaps;
            ke.Inclination        = inclination;
            ke.MeanMotion         = meanMotion;
            ke.MeanAnomalyAtEpoch = meanAnomaly;
            ke.TrueAnomalyAtEpoch = trueAnomaly;
            ke.Epoch              = epoch; //TimeFromPeriapsis(semiMajorAxis, standardGravParam, meanAnomaly);
            //Epoch(semiMajorAxis, semiMinorAxis, eccentricAnomoly, OrbitalPeriod(standardGravParam, semiMajorAxis));

            return(ke);
        }