#pragma once #include "base.h" #include "point.h" // represents a single object class Moon { friend class Cosmos; public: Moon(); ~Moon(); void DeleteArrays(); void InitArrays(); // Read the spec, one character at a time. // Throw an error if you cannot read a legitimate moon out of it. void ReadConfig(const char* spec); // Add the attraction of this moon to the other, and the other to this void Attract(Moon* other); // Use multistep method to move this moon forward one step. // This assumes current accelerations are already known. // Masses have been scaled such that the time increment is 1.0 . void Step14(); void Step13(); void Step12(); void Step11(); void Step10(); void Step9(); void Step8(); void Step7(); void Step6(); void Step5(); void Step4(); // An inaccurate step function that only needs one past step: 3rd order multistep void Leapfrog(); // Increment step counters and record _ov and _oa void RecordStep(); // Return approximate actual velocity at time ov[head-4] Point EstimateVelocity(); void ZeroAcceleration() { _a.Zero(); } double FindZeroZ(); static void UnitTest(); private: int _points; // number of points needed for simulation int _history; // _oa[_head - _history] and _ov[_head - _history] are valid int _head; // current offset, _history <= _head < 2*_history int _id; // name of this moon Point _p; // current position Point _peye; // current position, as translated by the simulator eye Point _v; // current velocity Point _a; // acceleration // _op and _oa are circular queues of length _history. They point at // the same points twice, so *_op[i] and *_op[i+_history] are the same // physical memory. If you pass &_op[i] into something expecting a // Point* array, it doesn't need to do mod. The head of the queue is // the most recent position. Point** _ov; // old velocities, really _op[i] - _op[i+1] Point** _oa; // old accelerations, _oa[i] == _oa[i+_history] bool _fixed; // if true, and this is a ring simulation, keep x and y coordinate fixed double _m; // mass int _color; // color of moon double _size; // radius of ball u8 _steps; // how many steps forward in time this has been run }; // To pass momentum from one moon to another, attach one of these to one moon and the other to the other. // This assumes instantaneous transfer of momentum. For delayed transfers, actually form a new moon to throw from one to the other. class Momentum { Point _momentum; // mass*velocity of the momentum double _start; // how long ago was this momentum transferred, like 0 for right now or -1 for next step Momentum* _next; // a moon could be applying many momentums, and momentums live on a freelist when not in use };