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); }
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); }
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); //} }
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++; }
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); }
public void DrawCurve(PCurve curve) { DrawCurve(curve, ActiveCanvas); }
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); }