Beispiel #1
0
        public void UpdateCurve(PVector3 velocity, int cElementCount = PSettings.CurveElementCount)
        {
            var ElInfo = GetEllipseInfo(Body.LocalPosition, velocity, Body.Mass, Body.GravityBody.Mass);

            Curve = MakeCurve(ElInfo.a, ElInfo.b, Body.LocalPosition, velocity, Body.GravityBody.Position, Body.GravityBody.Mass, cElementCount);
            //Debug.Log("e: "+ Curve.e + " p: "+Curve.p + " iA: "+Curve.PositionAngle);
        }
Beispiel #2
0
        double GetAlphaDt(double dt)
        {
            PCurve curve = Trajectory.Curve;
            double a     = curve.a;                                              // большая полуось
            double n     = Math.Sqrt(PWorld.G * GravityBody.Mass / (a * a * a)); //среднее движение
            double M     = n * dt;                                               // средняя аномалия

            var func  = curve.KeplerFunc;
            var Dfunc = curve.KeplerDFunc;


            double M0 = curve.e < 1 ?  M : -M;

            int t;
            //double tEx = NumericalMethods.NewtonForKepler(curve.KeplerFunc, curve.KeplerDFunc, M0, M, out t);
            double tEx = NumericalMethods.StaticPointKepler(curve.e, M0, out t);

            double alpha = curve.AlphaFromEAnomaly(tEx);

            if (t > 100)
            {
                Console.Write("angle:" + alpha + " M:" + M + " E:" + tEx + " func:" + func(tEx, M) + " t:" + t);
            }
            //UnityEngine.Debug.Log("e: " + curve.e+ " sqrt((e+1)/(e-1)):" + Math.Sqrt((curve.e + 1) / (curve.e - 1)) + " tanh(H/2)" + Math.Tanh(Ex/2));
            //UnityEngine.Debug.Log("dt " + dt + " Ex " + Ex + " alpha "+alpha + " M: " + M + " func "+ func(Ex,M));

            return(alpha);
        }
Beispiel #3
0
        public override void Draw(List <PVector> data)
        {
            var crv = new PCurve(data, CurveType.Normal);

            _renderer.DrawCurve(crv);

            //if (data.Count > 1 && lastAddedIndex > -1)
            //{
            //    PVector p1, p2, p3;
            //    if (data.Count > lastAddedIndex + 2)
            //    {


            //        if (lastAddedIndex == 0)
            //        {
            //            p1 = data[0];
            //        }
            //        else
            //        {
            //            var vec = PVector.Sub(data[lastAddedIndex + 1], data[lastAddedIndex]);
            //            vec.Mult(0.5);
            //            vec.Add(data[lastAddedIndex]);
            //            p1 = vec;
            //        }
            //        p2 = data[lastAddedIndex + 1];
            //        if (data.Count == lastAddedIndex + 3) { p3 = data[lastAddedIndex + 2]; }
            //        else
            //        {
            //            PVector vec = PVector.Sub(data[lastAddedIndex + 2], data[lastAddedIndex + 1]);
            //            vec.Mult(0.5); vec.Add(data[lastAddedIndex + 1]);
            //            p3 = vec;
            //        }
            //    }
            //    else
            //    {
            //        p1 = data[lastAddedIndex];

            //        p3 = data[lastAddedIndex+1];
            //        var vec = PVector.Sub(p3, p1);
            //        vec.Mult(0.5);
            //        vec.Add(p1);
            //        p2 = vec;
            //    }
            //    var list = new List<PVector>() { p1, p2, p3 };
            //    var curve = new PCurve(list, CurveType.Loose);

            //}
        }
Beispiel #4
0
        public void DrawCurve(PCurve curve, SKCanvas canv) {
            int drawnPoints = 0;
            var step = _BrushInfoService.XSpacing;
            var div = curve.DivideLength(step);
           
            float len = 0;
            for(int i = 0;i< div.Count - 1; i++)
            {

                DrawPoint(div[i], div[i + 1], canv, drawnPoints, CurvePositionKoeficient(len, curve.Length));
                drawnPoints++;
                len += PVector.DistanceBetween(div[i], div[i + 1]).ToFloat();
            }
            PVector vec = PVector.Sub(div.Last(), div.Count>1?div[div.Count - 2]:PVector.Add(div.Last(), new PVector(0,1)));
            vec.Add(div.Last());
            DrawPoint(div.Last(), vec, canv, drawnPoints, CurvePositionKoeficient(curve.Length, curve.Length));
            drawnPoints++;
        }
Beispiel #5
0
        private void SKCanvasView_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            var canv = e.Surface.Canvas;
            var info = e.Info;

            canv.DrawPaint(BgPaint);

            //canv.DrawCircle(info.Width / 2, info.Height / 2, Math.Min(info.Height, info.Width) * 0.8F, Service.GetBrush(new PVector(info.Width / 2, info.Height / 2)));
            var p = new List <PVector>
            {
                new PVector(info.Width * 0.2, info.Height * 0.2),
                new PVector(info.Width * 0.33, info.Height * 1),
                new PVector(info.Width / 3 * 2, info.Height * 0.2),
                new PVector(info.Width * 0.8, info.Height * 0.8)
            };
            var cdata = new PCurve(p, Geometry.GeometryShapes.CurveType.Normal);

            _renderer.DrawCurve(cdata, canv);
        }
Beispiel #6
0
 public void DrawCurve(PCurve curve) {
     DrawCurve(curve, ActiveCanvas);
 }
Beispiel #7
0
        public PCurve MakeCurve(double e, double p, PVector3 pos, PVector3 velocity, PVector3 GBodyPosition, double GBodyMass, int StepCount, bool TransitionCurve = false)
        {
            #region Начальный угол, построение кривой, апоцентр\перицентр

            var crv = new PCurve
            {
                e     = e,
                p     = p,
                Curve = new List <Pair <PVector3, double> >(),
                Lv    = PVector3.Cross(pos, velocity)
            };



            var    IAngleCosValue = (p - pos.magnitude) / (e * pos.magnitude);
            double InitAngle      = Math.Acos(IAngleCosValue);
            if (double.IsNaN(InitAngle))
            {
                InitAngle = IAngleCosValue < 0 ? Math.PI : 0;
            }
            if (PVector3.Dot(pos, velocity) < 0) // проверяем направление движения (см. радиальную компоненту скорости)
            {
                InitAngle = 2 * Math.PI - InitAngle;
            }

            var Vz = pos.normalized.RotateAround(crv.Lv, -InitAngle); // выравниваем на перицентр
            crv.Periapsis = new Pair <PVector3, double>(Vz * crv.RFuncAlpha(0), 0);
            crv.Apoapsis  = new Pair <PVector3, double>(crv.RFuncAlphaV3(Math.PI), Math.PI);



            for (double x = -Math.PI; x <= Math.PI; x += (2 * Math.PI) / StepCount)
            {
                var alpha = e < 1 ? crv.AlphaFromEAnomaly(x) : x;
                //var alpha = crv.AlphaFromEAnomaly(x);

                if (e < 1)
                {
                    crv.Curve.Add(new Pair <PVector3, double>(crv.RFuncAlphaV3(alpha) + GBodyPosition, alpha));
                }
                else
                if (Math.Abs(x) < Math.Acos(-1 / crv.e))
                {
                    crv.Curve.Add(new Pair <PVector3, double>(crv.RFuncAlphaV3(alpha) + GBodyPosition, alpha));
                }
            }


            crv.PositionAngle = InitAngle;
            #endregion
            #region Начальное время
            double t;
            if (crv.e < 1)
            {
                double E = 2 * Math.Atan(Math.Sqrt((1 - e) / (1 + e)) * Math.Tan(InitAngle / 2));
                // эксцентрическая аномалия (идем по обратному пути к уравнению кеплера)
                double a = crv.a; // большая полуось
                t = Math.Sqrt(a * a * a / (PWorld.G * GBodyMass)) * (E - e * Math.Sin(E));
            }
            else
            {
                double H = 2 * HyperbolicFuncs.Atanh(Math.Sqrt((e - 1) / (e + 1)) * Math.Tan(InitAngle / 2));
                double k = Math.Sqrt(Math.Pow(crv.a, 3) / (PWorld.G * GBodyMass)); // 1/n
                t = k * (e * Math.Sinh(H) - H);
            }


            crv.PositionTime = t; // для уравнения кеплера начальное время - до перицентра

            #endregion
            #region Наклонение орбиты, AN\DN

            double inclination = PVector3.Angle(crv.Lv, PVector3.up) * 180.0 / Math.PI;
            crv.inclination = inclination <= 90 ? inclination : 180 - inclination;
            if (Math.Abs(crv.inclination) > 0)
            {
                var    DescendingNodeV = PVector3.Cross(crv.Lv, PVector3.up).normalized;
                double DNAngle         = PVector3.Angle(DescendingNodeV, crv.Periapsis.a);
                double DNLength        = crv.RFuncAlpha(DNAngle);
                double ANAngle         = DNAngle - Math.PI;
                double ANLength        = crv.RFuncAlpha(ANAngle);


                crv.DN = new Pair <PVector3, double>(DescendingNodeV * DNLength, DNAngle);
                crv.AN = new Pair <PVector3, double>(-DescendingNodeV * ANLength, -DNAngle);
            }


            #endregion
            #region Точка перехода
            var TPoint   = new Pair <PVector3, double>();
            var isTPoint = false;


            foreach (var gb in World.Gravitybodies)
            {
                foreach (var point in crv.Curve)
                {
                    double distSqr1 = (point.a - GBodyPosition).magnitude;
                    double distSqr2 = (point.a - gb.Position).magnitude;
                    if (!(distSqr1 * distSqr1 * gb.Mass - distSqr2 * distSqr2 * GBodyMass > 0))
                    {
                        // грубый метод поиска точки перехода
                        continue;
                    }
                    isTPoint    = true;
                    crv.PHGBody = gb;

                    var C = GBodyPosition - gb.Position;
                    Func <double, double> Falpha =
                        alpha =>
                        Math.Pow(crv.RFuncAlpha(alpha), 2) * crv.PHGBody.Mass -
                        (C + crv.RFuncAlphaV3(alpha)).sqrMagnitude * GBodyMass;

                    int    i = crv.Curve.IndexOf(point);
                    int    it;
                    double a     = /*crv.Curve[i+1 > crv.Curve.Count ? 1 : i+1].b*/ Math.PI;
                    double b     = /*crv.Curve[i - 3 < 0 ? crv.Curve.Count - 3 : i-3].b*/ 0;
                    double angle = NumericalMethods.Dichotomy(Falpha, a, b, out it);
                    // уточнение координат точки
                    TPoint = new Pair <PVector3, double>(crv.RFuncAlphaV3(angle) + GBodyPosition, angle);
                    if (it > 100)
                    {
                        Debug.Write("angle: " + angle * 180 / Math.PI + " iterations:" + it + " a:" +
                                    a * 180 / Math.PI + " b:" + b * 180 / Math.PI);
                    }
                    break;
                }
                if (isTPoint)
                {
                    break;
                }
            }



            if (isTPoint)
            {
                crv.isTPoint        = true;
                crv.TransitionPoint = TPoint;
            }
            else
            {
                crv.isTPoint = false;
            }
            #endregion
            #region Фантомная траектория перехода

            if (Curve == null)
            {
                return(crv);
            }

            if (!isTPoint || TransitionCurve)
            {
                return(crv);
            }


            PCurve   PHCurve;
            PVector3 PHVelocity = GetVelocityMagnitude(TPoint.a, TPoint.b);
            PVector3 PHPosition = TPoint.a - crv.PHGBody.Position;
            var      PHCInfo    = GetEllipseInfo(PHPosition, PHVelocity, Body.Mass, crv.PHGBody.Mass);
            PHCurve             = MakeCurve(PHCInfo.a, PHCInfo.b, PHPosition, PHVelocity, crv.PHGBody.Position, crv.PHGBody.Mass, PSettings.CurveElementCount, true);
            crv.TransitionCurve = PHCurve;

            #endregion


            return(crv);
        }