예제 #1
0
    public Vector3_ Check2D(Vector3_ tp, Creature target)
    {
        var n = new Vector2_(creature.x, creature.cy);
        var t = new Vector2_(target.x, target.cy);

        var c = creature.colliderSize + target.colliderSize;

        if (t.y > n.y + creature.colliderHeight || Mathd.Abs(n.x - t.x) < c * 0.025)
        {
            return(tp);
        }

        var nx = n.x;
        var tx = tp.x;

        if (tx > nx && t.x < n.x || tx < nx && t.x > n.x)
        {
            return(tp);
        }

        var max = tx > nx ? t.x - c : t.x + c;

        nx   = tx > nx && tx > max || tx < nx && tx < max ? max : tx;
        tp.x = nx;

        return(tp);
    }
예제 #2
0
        public bool ContainsLatLon(Vector2d coord)
        {
            ////first check tile
            var coordinateTileId = Conversions.LatitudeLongitudeToTileId(
                coord.x, coord.y, Tile.CurrentZoom);

            if (Points.Count > 0)
            {
                var from = Conversions.LatLonToMeters(coord.x, coord.y);

                var to   = new Vector2d((Points[0][0].x / Tile.TileScale) + Tile.Rect.Center.x, (Points[0][0].z / Tile.TileScale) + Tile.Rect.Center.y);
                var dist = Vector2d.Distance(from, to);
                if (Mathd.Abs(dist) < 50)
                {
                    return(true);
                }
            }


            //Debug.Log("Distance -> " + dist);
            {
                if ((!coordinateTileId.Canonical.Equals(Tile.CanonicalTileId)))
                {
                    return(false);
                }

                //then check polygon
                var point  = Conversions.LatitudeLongitudeToVectorTilePosition(coord, Tile.CurrentZoom);
                var output = PolygonUtils.PointInPolygon(new Point2d <float>(point.x, point.y), _geom);

                return(output);
            }
        }
예제 #3
0
 public RectD(Vector2d min, Vector2d size)
 {
     Min    = min;
     Max    = min + size;
     Center = new Vector2d(Min.x + size.x / 2, Min.y + size.y / 2);
     Size   = new Vector2d(Mathd.Abs(size.x), Mathd.Abs(size.y));
 }
예제 #4
0
    public static double Gamma(double value, double absmax, double gamma)
    {
        bool flag = false;

        if (value < 0.0)
        {
            flag = true;
        }
        double num1 = Mathd.Abs(value);

        if (num1 > absmax)
        {
            if (flag)
            {
                return(-num1);
            }
            else
            {
                return(num1);
            }
        }
        else
        {
            double num2 = Mathd.Pow(num1 / absmax, gamma) * absmax;
            if (flag)
            {
                return(-num2);
            }
            else
            {
                return(num2);
            }
        }
    }
예제 #5
0
        public OrbitPoint[] GenerateOrbit(BodyInfo body)
        {
            List <OrbitPoint> orbitPoints   = new List <OrbitPoint>();
            OrbitalElements   orbit         = body.orbit;
            double            semiMinorAxis = orbit.SemiMinorAxis();
            //double moveOffset = (orbit.apoapsis + orbit.periapsis) / 2 - orbit.periapsis;
            float timer = Mathf.PI * 2;

            for (float t = 0; t < timer; t++)
            {
                double          posX          = orbit.semiMajorAxis * Mathd.Cos(timer) /* - moveOffset*/;
                double          posZ          = semiMinorAxis * Mathd.Sin(timer);
                double          posY          = 0; // ?
                double          nPosX         = posX * Mathd.Cos(orbit.inclination) - posY * Mathd.Sin(orbit.inclination);
                double          nPosY         = posY * Mathd.Cos(orbit.inclination) + posX * Mathd.Sin(orbit.inclination);
                double          nPosX2        = nPosX * Mathd.Cos(orbit.inclination) - posZ * Mathd.Sin(orbit.inclination);
                double          nPosZ         = posZ * Mathd.Cos(orbit.inclination) + nPosX * Mathd.Sin(orbit.inclination);
                PrecisePosition pointPosition = new PrecisePosition(nPosX, nPosY, nPosZ);
                double          pointVelocity = Mathd.Sqrt(
                    Mathd.Abs((g * body.mass) * ((2 / body.radius) - (1 / orbit.semiMajorAxis)))
                    );
                orbitPoints.Add(new OrbitPoint(pointPosition, pointVelocity));
            }
            return(orbitPoints.ToArray());
        }
예제 #6
0
    public bool Intersect(Box2D other)
    {
        if (m_radius == 0 || other.size_ == Vector2_.zero)
        {
            return(false);
        }

        var dx = Mathd.Abs(m_x - other.x);
        var dy = Mathd.Abs(m_y - other.y);

        if (dx > other.width * 0.5 + m_radius || dy > other.height * 0.5 + m_radius)
        {
            return(false);
        }

        if (dx <= other.width * 0.5 || dy <= other.height * 0.5)
        {
            return(true);
        }

        var hdx = (dx - other.width * 0.5);
        var hdy = (dy - other.height * 0.5);
        var dsq = hdx * hdx + hdy * hdy;

        return(dsq <= m_radius * m_radius);
    }
예제 #7
0
		/// <summary>
		/// Orbit plane will be unchanged.
		/// </summary>
		public void MakeOrbitCircle(bool clockwise) {
			if (attractor) {
#if UNITY_EDITOR
				if (!Application.isPlaying) {
					FindReferences();
					attractor.FindReferences();
					Undo.RecordObject(this, "Round orbit");
				}
#endif
				var dotProduct = CelestialBodyUtils.DotProduct(orbitData.orbitNormal, simControlRef.eclipticNormal); //sign of this value determines orbit orientation
				if (Mathd.Abs(orbitData.orbitNormal.sqrMagnitude - 1d) > 0.5d) {
					orbitData.orbitNormal = simControlRef.eclipticNormal;
				}
				var v = CelestialBodyUtils.CalcCircleOrbitVelocity(
					attractor._position,
					_position,
					attractor.mass,
					mass,
					orbitData.orbitNormal * ( clockwise && dotProduct >= 0 || !clockwise && dotProduct < 0 ? 1 : -1 ),
					simControlRef.gravitationalConstant
				);
				if (relativeVelocity != v) {
					relativeVelocity = v;
					orbitData.isDirty = true;
				}
			}
		}
예제 #8
0
 private void Update()
 {
     if (Mathd.Abs(SimControl.TimeScale) > 1e-6)
     {
         Calc();
     }
     ShowPredictOrbit();
 }
예제 #9
0
 double Abs(double x, double y, double z)
 {
     if (modules == null || modules.Count < 1)
     {
         return(0.0);
     }
     return(Mathd.Abs(planet.noiseModules[modules[0]].Get(x, y, z)));
 }
예제 #10
0
    }  // findc2c3

    /// <summary>
    /// Determine the time of flight in physics time units (GE internal time) that it takes for the body
    /// in orbit to go from position r0 to position r1 in an orbit with parameter p.
    ///
    /// The angle between two 3D vectors cannot be greater than 180 degrees unless the orientation of the
    /// plane they define is also specified. The normal parameter is used for this. If an angle less than
    /// 180 is desired then the cross product of r0 and v0 can be used as the normal.
    /// Calling TOF via the OrbitUniversal wrapper will handle all that automatically.
    ///
    /// </summary>
    /// <param name="r0">from point (with respect to center)</param>
    /// <param name="r1">to point (with respect to center)</param>
    /// <param name="p">orbit semi-parameter</param>
    /// <param name="mu">centerbody mass</param>
    /// <param name="normal">normal to orital plane</param>
    /// <returns>time to travel from r0 to r1 in GE time</returns>
    public static double TimeOfFlight(Vector3d r0, Vector3d r1, double p, double mu, Vector3d normal)
    {
        // Vallado, Algorithm 11, p126
        double tof     = 0;
        double r0r1    = r0.magnitude * r1.magnitude;
        double cos_dnu = Vector3d.Dot(r0, r1) / r0r1;
        double sin_dnu = Vector3d.Cross(r0, r1).magnitude / r0r1;

        // use the normal to determine if angle is > 180
        if (Vector3d.Dot(Vector3d.Cross(r0, r1), normal) < 0.0)
        {
            sin_dnu *= -1.0;
        }
        // GE - precision issue at 180 degrees. Simply return 1/2 the orbit period.
        if (Mathd.Abs(1.0 + cos_dnu) < 1E-5)
        {
            double a180 = 0.5f * (r0.magnitude + r1.magnitude);
            return(Mathd.Sqrt(a180 * a180 * a180 / mu) * Mathd.PI);
        }
        // sin_nu: Need to use direction of flight to pick sign per Algorithm 53
        double k = r0r1 * (1.0 - cos_dnu);
        double l = r0.magnitude + r1.magnitude;
        double m = r0r1 * (1 + cos_dnu);
        double a = (m * k * p) / ((2.0 * m - l * l) * p * p + 2.0 * k * l * p - k * k);
        double f = 1.0 - (r1.magnitude / p) * (1.0 - cos_dnu);
        double g = r0r1 * sin_dnu / (Mathd.Sqrt(mu * p));

        double alpha = 1 / a;

        if (alpha > 1E-7)
        {
            // ellipse
            double delta_nu = Mathd.Atan2(sin_dnu, cos_dnu);
            double fdot     = Mathd.Sqrt(mu / p) * Mathd.Tan(0.5 * delta_nu) *
                              ((1 - cos_dnu) / p - (1 / r0.magnitude) - (1.0 / r1.magnitude));
            double cos_deltaE = 1 - r0.magnitude / a * (1.0 - f);
            double sin_deltaE = -r0r1 * fdot / (Mathd.Sqrt(mu * a));
            double deltaE     = Mathd.Atan2(sin_deltaE, cos_deltaE);
            tof = g + Mathd.Sqrt(a * a * a / mu) * (deltaE - sin_deltaE);
        }
        else if (alpha < -1E-7)
        {
            // hyperbola
            double cosh_deltaH = 1.0 + (f - 1.0) * r0.magnitude / a;
            double deltaH      = GEMath.Acosh(cosh_deltaH);
            tof = g + Mathd.Sqrt(-a * a * a / mu) * (GEMath.Sinh(deltaH) - deltaH);
        }
        else
        {
            // parabola
            double c = Mathd.Sqrt(r0.magnitude * r0.magnitude + r1.magnitude * r1.magnitude - 2.0 * r0r1 * cos_dnu);
            double s = 0.5 * (r0.magnitude + r1.magnitude + c);
            tof = 2 / 3 * Mathd.Sqrt(s * s * s / (2.0 * mu)) * (1 - Mathd.Pow(((s - c) / s), 1.5));
        }
        return(tof);
    }
예제 #11
0
 public static double MoveTowards(double current, double target, double maxDelta)
 {
     if (Mathd.Abs(target - current) <= maxDelta)
     {
         return(target);
     }
     else
     {
         return(current + Mathd.Sign(target - current) * maxDelta);
     }
 }
예제 #12
0
        public static Vector3 GetRayPlaneIntersectionPoint(Vector3 pointOnPlane, Vector3 normal, Vector3 rayOrigin, Vector3 rayDirection)
        {
            var dotProd = CelestialBodyUtils.DotProduct(rayDirection, normal);

            if (Mathd.Abs(dotProd) < 1e-5)
            {
                return(new Vector3());
            }
            var p = rayOrigin + rayDirection * CelestialBodyUtils.DotProduct((pointOnPlane - rayOrigin), normal) / dotProd;

            p = p - normal * CelestialBodyUtils.DotProduct(p - pointOnPlane, normal);             //projection. for better precision
            return(p);
        }
예제 #13
0
    /// <summary>
    /// Cotangent function.
    ///
    /// Adapted from Vallado's astmath CPP functions.
    ///
    /// </summary>
    public static double Cot(double x)
    {
        double temp = Mathd.Tan(x);

        if (Mathd.Abs(temp) < 1E-8)
        {
            return(double.NaN);
        }
        else
        {
            return(1.0 / temp);
        }
    }
예제 #14
0
    }  // lambhodograph

    private static double KBattin
    (
        double v
    )
    {
        double[] d = new double[21]
        {
            1.0 / 3.0, 4.0 / 27.0,
            8.0 / 27.0, 2.0 / 9.0,
            22.0 / 81.0, 208.0 / 891.0,
            340.0 / 1287.0, 418.0 / 1755.0,
            598.0 / 2295.0, 700.0 / 2907.0,
            928.0 / 3591.0, 1054.0 / 4347.0,
            1330.0 / 5175.0, 1480.0 / 6075.0,
            1804.0 / 7047.0, 1978.0 / 8091.0,
            2350.0 / 9207.0, 2548.0 / 10395.0,
            2968.0 / 11655.0, 3190.0 / 12987.0,
            3658.0 / 14391.0
        };
        double del, delold, term, termold, sum1;
        int    i;

        /* ---- process forwards ---- */
        sum1    = d[0];
        delold  = 1.0;
        termold = d[0];
        i       = 1;
        while ((i <= 20) && (Mathd.Abs(termold) > 0.00000001))
        {
            del  = 1.0 / (1.0 - d[i] * v * delold);
            term = termold * (del - 1.0);
            sum1 = sum1 + term;
            i++;
            delold  = del;
            termold = term;
        }
        //return sum1;

        int    ktr   = 20;
        double sum2  = 0.0;
        double term2 = 1.0 + d[ktr] * v;

        for (i = 1; i <= ktr - 1; i++)
        {
            sum2  = d[ktr - i] * v / term2;
            term2 = 1.0 + sum2;
        }

        return(d[0] / term2);
    }  // double kbattin
예제 #15
0
 public override void OnPointerUp(PointerEventData eventData)
 {
     base.OnPointerUp(eventData);
     if (SnapInMiddle)
     {
         if (Mathd.Abs(m_Value) < SnapToZeroTreshold)
         {
             value = 0f;
             RefreshFillAreas();
         }
     }
     if (SimulationControl.Instance != null)
     {
         SimulationControl.Instance.TimeScale = value;
     }
 }
예제 #16
0
 public override void OnPointerUp(PointerEventData eventData)
 {
     base.OnPointerUp(eventData);
     if (snapInMiddle)
     {
         if (Mathd.Abs(m_Value) < 0.1f)
         {
             value = 0f;
             RefreshFillAreas();
         }
     }
     if (simControl != null)
     {
         simControl.timeScale = value;
     }
 }
예제 #17
0
    public void GenerateObjects()
    {
        List <string> curCollisions = player.GetComponent <Collision>().getCurrentCollisions();
        Vector2d      playerLoc     = locman.GetComponent <PositionWithLocationProvider>().getCurrentLoc();

        foreach (var name in curCollisions)
        {
            Vector2d objLoc = obman.GetComponent <ObjectManager>().getObjectCoords(name);
            Debug.Log("objloc: " + objLoc);
            Debug.Log("playerloc: " + playerLoc);
            double LatDistance  = Mathd.Abs(Mathd.Abs(objLoc.x) - Mathd.Abs(playerLoc.x)) * 111000;
            double LongDistance = Mathd.Abs(Mathd.Abs(objLoc.y) - Mathd.Abs(playerLoc.y)) * (Mathd.Cos(objLoc.x) * 111000);
            Debug.Log("LR: " + LongDistance + " UD: " + LatDistance);
            double newPosX, newPosY;
            if (objLoc.x < playerLoc.x)
            {
                Debug.Log("Spawning South");
                Debug.Log("Obj Loc x: " + objLoc.x + " Player Loc x: " + playerLoc.x);
                newPosY = ARCam.transform.position.z - (LatDistance);
            }
            else
            {
                Debug.Log("Spawning North");
                Debug.Log("Obj Loc x: " + objLoc.x + " Player Loc x: " + playerLoc.x);
                newPosY = ARCam.transform.position.z + (LatDistance);
            }
            if (objLoc.y < playerLoc.y)
            {
                Debug.Log("Spawning West");
                Debug.Log("Obj Loc x: " + objLoc.y + " Player Loc x: " + playerLoc.y);
                newPosX = ARCam.transform.position.x - (LongDistance);
            }
            else
            {
                Debug.Log("Spawning East");
                Debug.Log("Obj Loc x: " + objLoc.y + " Player Loc x: " + playerLoc.y);
                newPosX = ARCam.transform.position.x + (LongDistance);
            }
            GameObject plsWork = Instantiate(prefab, new Vector3((float)newPosX, ARCam.transform.position.y, (float)newPosY), Quaternion.identity);
            plsWork.name             = name;
            plsWork.transform.parent = this.transform;
        }
        var newRotation = Quaternion.Euler(0, -Input.compass.trueHeading, 0);

        this.transform.rotation = newRotation;
    }
예제 #18
0
    }  // coe2rvMirror

    public static double GetPhaseFromOE(OrbitUtils.OrbitElements oe)
    {
        if (oe.ecc < small)
        {
            // ----------------  circular equatorial  ------------------

            if ((oe.incl < small) | (Mathd.Abs(oe.incl - Mathd.PI) < small))
            {
                return(oe.truelon);
            }
            else
            {
                // --------------  circular inclined  ------------------
                return(oe.arglat);
            }
        }
        return(oe.nu);
    }
예제 #19
0
    // Update is called once per frame
    void Update()
    {
        if (updateLocationTry == false)
        {
            StartCoroutine(UpdateLocation());
        }

        //text onscreen
        logLabel.GetComponent <Text>().text = log;
        gpstext = "Lat: " + latitude.ToString() + "\n" + "Lon: " + longtitude.ToString() + "\n" + "Acc: " + horizontalAcc.ToString() + "\n" + "Alt: " + altitude.ToString() + "\n" + "Time: " + timeStamp.ToString() + "\n" + "DistBtw: " + distanceTraveledBetw.ToString() + "\n" + "Angle: " + angleInBetween.ToString() + "\n" + "DistTarget: " + distanceToTarget.ToString() + "\n" + "Throttle: " + throttle.ToString();
        gpsLabel.GetComponent <Text> ().text = gpstext;
        //rotating cursor for navigation
        cursor.GetComponent <RectTransform>().localRotation = Quaternion.Euler(0.0F, 0.0F, -1.0F * (float)angleInBetween + 180.0F);
        //showing big angle
        angleText.GetComponent <Text> ().text = Mathd.RoundToInt(Mathd.Abs(angleInBetween)).ToString();
        //throttlebar
        throttleBar.GetComponent <Image>().fillAmount = throttle;
    }
예제 #20
0
    public static string DisplayDistanceMeasure(double measure, int decimals = 2)
    {
        double m = Mathd.Abs(measure);
        int    u = 0;

        if (m < 1e3d)
        {
            u = 0;
        }
        else if (m < 1e6d)
        {
            measure *= 1e-3d;
            u        = 1;
        }
        else if (m < 1e9d)
        {
            measure *= 1e-6d;
            u        = 2;
        }
        else if (m < LightSpeed)
        {
            measure *= 1e-9d;
            u        = 3;
        }
        else if (m < LightDay)
        {
            measure *= InvLightSpeed;
            u        = 4;
        }
        else if (m < LightYear)
        {
            measure *= InvLightDay;
            u        = 5;
        }
        else
        {
            measure *= InvLightYear;
            u        = 6;
        }

        return(measure.ToString("f" + decimals) + distUnits[u]);
    }
예제 #21
0
    private void CompareOrbits(OrbitUniversal orbit1, OrbitUniversal orbit2, double precision)
    {
        if (Mathd.Abs(orbit1.p - orbit2.p) > precision)
        {
            Debug.LogFormat("** FAIL ** p compare failed {0} vs {1}", orbit1.p, orbit2.p);
            Debug.LogFormat("** orbit1={0}\n**  orbit2={1}", orbit1.DumpInfo(), orbit2.DumpInfo());
            Assert.Fail();
        }
        if (Mathd.Abs(orbit1.eccentricity - orbit2.eccentricity) > precision)
        {
            Debug.LogFormat("** FAIL ** ecc compare failed {0} vs {1}", orbit1.eccentricity, orbit2.eccentricity);
            Debug.LogFormat("** orbit1={0}\n**  orbit2={1}", orbit1.DumpInfo(), orbit2.DumpInfo());
            Assert.Fail();
        }
        if (Mathd.Abs(orbit1.inclination - orbit2.inclination) > precision)
        {
            Debug.LogFormat("** FAIL ** incl compare failed {0} vs {1}", orbit1.inclination, orbit2.inclination);
            Debug.LogFormat("** orbit1={0}\n**  orbit2={1}", orbit1.DumpInfo(), orbit2.DumpInfo());
            Assert.Fail();
        }
        double diff = orbit1.omega_lc - orbit2.omega_lc;

        if ((Mathd.Abs(diff) > precision) &&
            (Mathd.Abs(diff - 360.0) > precision) &&
            (Mathd.Abs(diff + 360.0) > precision))
        {
            Debug.LogFormat("** FAIL ** Omega LC compare failed {0} vs {1}", orbit1.omega_lc, orbit2.omega_lc);
            Debug.LogFormat("** orbit1={0}\n**  orbit2={1}", orbit1.DumpInfo(), orbit2.DumpInfo());
            Assert.Fail();
        }
        diff = orbit1.omega_uc - orbit2.omega_uc;
        if ((Mathd.Abs(diff) > precision) &&
            (Mathd.Abs(diff - 360.0) > precision) &&
            (Mathd.Abs(diff + 360.0) > precision))
        {
            Debug.LogFormat("** FAIL ** omega UC compare failed {0} vs {1}", orbit1.omega_uc, orbit2.omega_uc);
            Debug.LogFormat("** orbit1={0}\n**  orbit2={1}", orbit1.DumpInfo(), orbit2.DumpInfo());
            Assert.Fail();
        }
    }
예제 #22
0
        double Billow(double x, double y, double z)
        {
            double value = 0.0, signal;

            x *= frequency;
            y *= frequency;
            z *= frequency;

            for (uint i = 0; i < octaves; ++i)
            {
                signal = sources[i].Get(x, y, z);
                signal = 2.0 * Mathd.Abs(signal) - 1.0;
                value += signal * exparray[i];

                x *= lacunarity;
                y *= lacunarity;
                z *= lacunarity;
            }

            value += 0.5;
            return(value * correction[octaves - 1, 0] + correction[octaves - 1, 1]);
        }
예제 #23
0
    public static string DisplaySpeedMeasure(double measure, int decimals = 2)
    {
        double m = Mathd.Abs(measure);
        int    u = 0;

        if (m < 1e3d)
        {
            u = 0; // m
        }
        else if (m < 1e6d)
        {
            measure *= 1e-3d;
            u        = 1; // km
        }
        else
        {
            measure *= InvLightSpeed;
            u        = 2; // c
        }

        return(measure.ToString("f" + decimals) + spdUnits[u]);
    }
예제 #24
0
        double Ridged(double x, double y, double z)
        {
            double result = 0.0, signal;

            x *= frequency;
            y *= frequency;
            z *= frequency;

            for (uint i = 0; i < octaves; ++i)
            {
                signal  = sources[i].Get(x, y, z);
                signal  = offst - Mathd.Abs(signal);
                signal *= signal;
                result += signal * exparray[i];

                x *= lacunarity;
                y *= lacunarity;
                z *= lacunarity;
            }

            return(result * correction[octaves - 1, 0] + correction[octaves - 1, 1]);
        }
예제 #25
0
        /// <summary>
        /// Sets the eccentricity and updates all corresponding orbit state values.
        /// </summary>
        /// <param name="e">The new eccentricity value.</param>
        /// <remarks>
        /// Mean anomaly will try to preserve.
        /// </remarks>
        public void SetEccentricity(double e)
        {
            if (!IsValidOrbit)
            {
                return;
            }
            e = Mathd.Abs(e);
            var _periapsis = PeriapsisDistance; // Periapsis remains constant

            Eccentricity = e;
            var compresion = Eccentricity < 1 ? (1 - Eccentricity * Eccentricity) : (Eccentricity * Eccentricity - 1);

            SemiMajorAxis  = Math.Abs(_periapsis / (1 - Eccentricity));
            FocalParameter = SemiMajorAxis * compresion;
            SemiMinorAxis  = SemiMajorAxis * Mathd.Sqrt(compresion);
            CenterPoint    = SemiMajorAxis * Math.Abs(Eccentricity) * SemiMajorAxisBasis;
            if (Eccentricity < 1)
            {
                EccentricAnomaly = CelestialBodyUtils.KeplerSolver(MeanAnomaly, Eccentricity);
                var cosE = Math.Cos(EccentricAnomaly);
                TrueAnomaly = Math.Acos((cosE - Eccentricity) / (1 - Eccentricity * cosE));
                if (MeanAnomaly > Mathd.PI)
                {
                    TrueAnomaly = Mathd.PI_2 - TrueAnomaly;
                }
            }
            else
            {
                EccentricAnomaly = CelestialBodyUtils.KeplerSolverHyperbolicCase(MeanAnomaly, Eccentricity);
                TrueAnomaly      = Math.Atan2(Math.Sqrt(Eccentricity * Eccentricity - 1) * Math.Sinh(EccentricAnomaly), Eccentricity - Math.Cosh(EccentricAnomaly));
            }
            SetVelocityByCurrentAnomaly();
            SetPositionByCurrentAnomaly();

            CalculateNewOrbitData();
        }
예제 #26
0
        public void SetEccentricity(double e)
        {
            if (!isValidOrbit)
            {
                return;
            }
            e = Mathd.Abs(e);
            var _periapsis = periapsisDistance;             // Periapsis remains constant

            eccentricity = e;
            var compresion = eccentricity < 1 ? (1 - eccentricity * eccentricity) : (eccentricity * eccentricity - 1);

            semiMajorAxis  = System.Math.Abs(_periapsis / (1 - eccentricity));
            focalParameter = semiMajorAxis * compresion;
            semiMinorAxis  = semiMajorAxis * Mathd.Sqrt(compresion);
            centerPoint    = semiMajorAxis * System.Math.Abs(eccentricity) * semiMajorAxisBasis;
            if (eccentricity < 1)
            {
                eccentricAnomaly = CelestialBodyUtils.KeplerSolver(meanAnomaly, eccentricity);
                var cosE = System.Math.Cos(eccentricAnomaly);
                trueAnomaly = System.Math.Acos((cosE - eccentricity) / (1 - eccentricity * cosE));
                if (meanAnomaly > Mathd.PI)
                {
                    trueAnomaly = Mathd.PI_2 - trueAnomaly;
                }
            }
            else
            {
                eccentricAnomaly = CelestialBodyUtils.KeplerSolverHyperbolicCase(meanAnomaly, eccentricity);
                trueAnomaly      = System.Math.Atan2(System.Math.Sqrt(eccentricity * eccentricity - 1) * System.Math.Sinh(eccentricAnomaly), eccentricity - System.Math.Cosh(eccentricAnomaly));
            }
            SetVelocityByCurrentAnomaly();
            SetPositionByCurrentAnomaly();

            CalculateNewOrbitData();
        }
    public CircularInclinationAndAN(OrbitData fromOrbit, OrbitData toOrbit) : base(fromOrbit, toOrbit)
    {
        name = "Circular Change Inclination and Ascending Node";

        // check the orbits are circular and have the same radius
        if (fromOrbit.ecc > GEConst.small)
        {
            Debug.LogWarning("fromOrbit is not circular. ecc=" + fromOrbit.ecc);
            return;
        }
        if (toOrbit.ecc > GEConst.small)
        {
            Debug.LogWarning("toOrbit is not circular. ecc=" + toOrbit.ecc);
            return;
        }
        if (Mathf.Abs(fromOrbit.a - toOrbit.a) > GEConst.small)
        {
            Debug.LogWarning("Orbits do not have the same radius delta=" + Mathf.Abs(fromOrbit.a - toOrbit.a));
            return;
        }

        double dOmega    = (toOrbit.omega_uc - fromOrbit.omega_uc) * Mathd.Deg2Rad;
        double i_initial = fromOrbit.inclination * Mathd.Deg2Rad;
        double i_final   = toOrbit.inclination * Mathd.Deg2Rad;

        // u_initial = omega_lc + nu (i.e. phase of circular orbit)
        // eqn (6-25)
        double cos_theta = Mathd.Cos(i_initial) * Mathd.Cos(i_final) +
                           Mathd.Sin(i_initial) * Mathd.Sin(i_final) * Mathd.Cos(dOmega);
        // Quadrant check
        double theta = Mathd.Acos(Mathd.Clamp(cos_theta, -1.0, 1.0));

        if (dOmega < 0)
        {
            theta = -theta;
        }

        // u_initial: phase of intersection in the initial orbit
        double numer = Mathd.Sin(i_final) * Mathd.Cos(dOmega) - cos_theta * Mathd.Sin(i_initial);
        double denom = Mathd.Sin(theta) * Mathd.Cos(i_initial);

        if (Mathd.Abs(denom) < 1E-6)
        {
            Debug.LogError("u_initial: about to divide by zero (small theta)");
            // return;
        }
        double u_initial = Mathd.Acos(Mathd.Clamp(numer / denom, -1.0, 1.0));

        // u_final: phase of intersection in the final orbit
        numer = Mathd.Cos(i_initial) * Mathd.Sin(i_final) - Mathd.Sin(i_initial) * Mathd.Cos(i_final) * Mathd.Cos(dOmega);
        if (Mathd.Abs(Mathd.Sin(theta)) < 1E-6)
        {
            Debug.LogError("u_final: about to divide by zero (small theta)");
            return;
        }
        double u_final = Mathd.Acos(Mathd.Clamp(numer / Mathd.Sin(theta), -1.0, 1.0));

        double u_initialDeg = u_initial * Mathd.Rad2Deg;
        double u_finalDeg   = u_final * Mathd.Rad2Deg;

        // Orbits cross at two places, pick the location closest to the current position of the fromOrbit
        double time_to_crossing = fromOrbit.period * (u_initialDeg - fromOrbit.phase) / 360f;

        if (time_to_crossing < 0)
        {
            u_initialDeg     += 180f;
            u_finalDeg       += 180f;
            time_to_crossing += 0.5f * fromOrbit.period;
        }

        // Determine velocity change required
        Vector3 dV = toOrbit.GetPhysicsVelocityForEllipse((float)u_finalDeg) -
                     fromOrbit.GetPhysicsVelocityForEllipse((float)u_initialDeg);

        // Create a maneuver object
        Maneuver m = new Maneuver();

        m.physPosition = new Vector3d(fromOrbit.GetPhysicsPositionforEllipse((float)(u_initialDeg)));
        m.mtype        = Maneuver.Mtype.vector;
        m.dV           = dV.magnitude;
        m.velChange    = dV;
        m.worldTime    = GravityEngine.instance.GetPhysicalTime() + (float)time_to_crossing;
        m.nbody        = fromOrbit.nbody;
        maneuvers.Add(m);

        //Debug.LogFormat("u_initial = {0} u_final={1} (deg) dOmega={2} (deg) timeToCrossing={3} fromPhase={4} cos_theta={5} theta={6}",
        //    u_initialDeg,
        //    u_finalDeg,
        //    dOmega * Mathd.Rad2Deg,
        //    time_to_crossing,
        //    fromOrbit.phase,
        //    cos_theta,
        //    theta);
    }
예제 #28
0
    public static bool Cross(Box2D box, Box2D other, Vector2_ tp, ref Vector2_ hit)
    {
        if (box.Intersect(other))
        {
            return(true);
        }

        var o = box.center_;

        tp -= o;
        other.Set(other.center_ - o, other.size_ + box.size_);
        box.SetCenter(Vector2_.zero);

        double minx = Mathd.Min(0, tp.x), maxx = Mathd.Max(0, tp.x), miny = Mathd.Min(0, tp.y), maxy = Mathd.Max(0, tp.y);

        var l1 = Mathd.Abs(other.leftEdge) < Mathd.Abs(other.rightEdge) ? other.leftEdge : other.rightEdge;
        var l2 = Mathd.Abs(other.topEdge) < Mathd.Abs(other.bottomEdge) ? other.topEdge : other.bottomEdge;

        bool b1 = false, b2 = false;

        if (other.leftEdge < 0 && other.rightEdge > 0)
        {
            goto _l2;
        }

_l1:
        b1 = true;
        if (l1 > minx && l1 < maxx)
        {
            var yy = tp.y / tp.x * l1;
            if (yy > other.bottomEdge && yy < other.topEdge)
            {
                hit.Set(l1, yy);
                hit += o;

                return(true);
            }
        }

        if (b2)
        {
            return(false);
        }

_l2:
        b2 = true;
        if (l2 > miny && l2 < maxy)
        {
            var xx = l2 * tp.x / tp.y;
            if (xx > other.leftEdge && xx < other.rightEdge)
            {
                hit.Set(xx, l2);
                hit += o;

                return(true);
            }
        }

        if (!b1)
        {
            goto _l1;
        }

        return(false);
    }
예제 #29
0
    private void OnInputChanged(InputKey[] changedKeys, int count)
    {
        if (!current)
        {
            return;
        }

        // Inputs bitmask:The first 20 bits contains 4 input id. every 5 bit stored one input id, 20-29 contains hold input, last 2 bits: left and right movement state
        var ns = m_state;

        //var n = $"({ns.BitMask(24)},{ns >> 20 & 0x0F}|{ns.BitMask(29)},{ns >> 25 & 0x0F}),";
        //for (var pp = 0; pp < MAX_KEY_CACHE_COUNT; ++pp)
        //{
        //    var k = (m_state >> KEY_BITS * pp) & 0x1F;
        //    n += "[" + k + "], ";
        //}
        //Logger.LogDetail("nidx: {0}, keys: {1}", m_inputIndex, n);

        for (var i = 0; i < count; ++i)
        {
            var key = changedKeys[i];

            if (key.value == KEY_LEFT || key.value == KEY_RIGHT)  // Movement key
            {
                ns = ns.BitMask(key.value, key.fired);
                continue;
            }

            if (m_disabledKeys.BitMask(key.ID))
            {
                continue;                                 // Key disabled
            }
            if (key.ID < 1 || key.ID > 0x1F)
            {
                continue;                              // Valid input id: [1 - 31]
            }
            if (Mathd.Abs(key.value) < 1 || Mathd.Abs(key.value) > 0x1D)
            {
                continue;                                                            // Valid key value: [1 - 29]
            }
            if (key.isInstant && (m_inputIndex >= MAX_KEY_CACHE_COUNT || !key.fired))
            {
                continue;
            }

            if (key.keyFired && !OnValidateKeyboard(key))
            {
                continue;
            }

            var val = key.ID;
            if (!key.isInstant)
            {
                val = val.BitMask(4, true);
                var hold = ns >> INSTANT_KEY_BITS & 0x3FF;
                int h1 = hold & 0x1F, h2 = hold >> 5 & 0x1F;
                if (!key.fired)
                {
                    if (val != h1 && val != h2)
                    {
                        continue;
                    }
                    h1 = val == h1 ? h2 : h1;
                    h2 = 0;
                }
                else
                {
                    h2 = h1;
                    h1 = val;
                }
                hold = h1 == h2 ? h1 : h1 | h2 << 5;
                ns   = ns & ~0x3FF00000 | hold << INSTANT_KEY_BITS;
            }
            else
            {
                ns |= val << m_inputIndex * KEY_BITS;
                ++m_inputIndex;
            }
        }

        //n = $"({ns.BitMask(24)},{ns >> 20 & 0x0F}|{ns.BitMask(29)},{ns >> 25 & 0x0F}),";
        //for (var pp = 0; pp < MAX_KEY_CACHE_COUNT; ++pp)
        //{
        //    var k = (m_state >> KEY_BITS * pp) & 0x0F;
        //    n += "[" + k + "], ";
        //}
        //Logger.LogDetail("nidx: {0}, keys: {1}", m_inputIndex, n);

        UpdateState(ns);
    }
예제 #30
0
    /* -----------------------------------------------------------------------------
    *
    *                           function newtonnu
    *
    *  this function solves keplers equation when the true anomaly is known.
    *    the mean and eccentric, parabolic, or hyperbolic anomaly is also found.
    *    the parabolic limit at 168ø is arbitrary. the hyperbolic anomaly is also
    *    limited. the hyperbolic sine is used because it's not double valued.
    *
    *  author        : david vallado                  719-573-2600   27 may 2002
    *
    *  revisions
    *    vallado     - fix small                                     24 sep 2002
    *
    *  inputs          description                    range / units
    *    ecc         - eccentricity                   0.0  to
    *    nu          - true anomaly                   -2pi to 2pi rad
    *
    *  outputs       :
    *    e0          - eccentric anomaly              0.0  to 2pi rad       153.02 deg
    *    m           - mean anomaly                   0.0  to 2pi rad       151.7425 deg
    *
    *  locals        :
    *    e1          - eccentric anomaly, next value  rad
    *    sine        - sine of e
    *    cose        - cosine of e
    *    ktr         - index
    *
    *  coupling      :
    *    arcsinh     - arc hyperbolic sine
    *    sinh        - hyperbolic sine
    *
    *  references    :
    *    vallado       2013, 77, alg 5
    * --------------------------------------------------------------------------- */

    private static void NewtonNu(OrbitElements oe)
    {
        double small, sine, cose, cosnu, temp;

        double ecc = oe.ecc;
        double nu = oe.nu;
        double e0, m;

        // ---------------------  implementation   ---------------------
        e0    = 999999.9;
        m     = 999999.9;
        small = 0.00000001;

        // --------------------------- circular ------------------------
        if (Mathd.Abs(ecc) < small)
        {
            m  = nu;
            e0 = nu;
        }
        else
        // ---------------------- elliptical -----------------------
        if (ecc < 1.0 - small)
        {
            cosnu = Mathd.Cos(nu);
            temp  = 1.0 / (1.0 + ecc * cosnu);
            sine  = (Mathd.Sqrt(1.0 - ecc * ecc) * Mathd.Sin(nu)) * temp;
            cose  = (ecc + cosnu) * temp;
            e0    = Mathd.Atan2(sine, cose);
            m     = e0 - ecc * Mathd.Sin(e0);
        }
        else
        // -------------------- hyperbolic  --------------------
        if (ecc > 1.0 + small)
        {
            if ((ecc > 1.0) && (Mathd.Abs(nu) + 0.00001 < Mathd.PI - Mathd.Acos(Mathd.Clamp(1.0 / ecc, -1.0, 1.0))))
            {
                sine = (Mathd.Sqrt(ecc * ecc - 1.0) * Mathd.Sin(nu)) / (1.0 + ecc * Mathd.Cos(nu));
                e0   = GEMath.Asinh(sine);
                m    = ecc * GEMath.Sinh(e0) - e0;
            }
        }
        else
        // ----------------- parabolic ---------------------
        if (Mathd.Acos(Mathd.Clamp(nu, -1.0, 1.0)) < 168.0 * Mathd.PI / 180.0)
        {
            e0 = Mathd.Tan(nu * 0.5);
            m  = e0 + (e0 * e0 * e0) / 3.0;
        }

        if (ecc < 1.0)
        {
            m = System.Math.Truncate(m / (2.0 * Mathd.PI));
            if (m < 0.0)
            {
                m = m + 2.0 * Mathd.PI;
            }
            e0 = System.Math.Truncate(e0 / (2.0 * Mathd.PI));
        }
        oe.m       = m;
        oe.eccanom = e0;
    }  // newtonnu