This lab is about class, object, constructor and destructor
A class is a user-defined type representing a set of objects with the same structure and
behavior. Objects are
variables of class type. Each object of a class has its own copies and values of its data
members. All objects of a class
share a common set of member functions. In addition, C++ allows access control to each data
member and member function:
There are at least 4 types of member functions:
operator::.
In this lab, you are going to create a very simple animated physics simulation of planetary bodies. The interaction of planets are simulated using a very rough approximation of Newtonian physics, and are drawn onto the console frame by frame.
Note that the character inputs to the program are case sensitive.
6 for perfect fullscreen display if necessary (see below).default: 16).
The displacement vector $\vec{s}=(s_x,s_y)$ of an object is the location of the planet relative to the center of the grid. $s_x,s_y$ are the horizontal and vertical distances respectively, with up, right being the positive direction.
The velocity vector, \(\vec{v} = (v_x, v_y)\), is the change in displacement relative to time, and similarly the acceleration, \(\vec{a} = (a_x, a_y)\), is the change in velocity respect to time. We have $$\frac{d\vec{s}}{dt}=\vec{v}\phantom{ee}\frac{d\vec{v}}{dt}=\vec{a}$$ $$\frac{ds_x}{dt}=v_x\phantom{ee}\frac{ds_y}{dt}=v_y$$ $$\frac{dv_x}{dt}=a_x\phantom{ee}\frac{dv_y}{dt}=a_y$$
By Newton's Law of Universal Gravitation, the magnitude of the gravitational force, \(|\vec{F}|\) , between two bodies are both given by $$|\vec{F}| = G \frac{m_1m_2}{r^2}$$ where $m_1,m_2$ are the masses of the two objects, $r$ is the distance between the two objects, and $G$ is the gravitational constant. For our purposes, we can assume the units are normalized such that $G=1$, and the magnitude of the force would then be $$|\vec{F}|=\frac{m_1m_2}{r^2}$$ The gravitational force by Planet 2 on Planet 1, \(\vec{F}_{2\;on\;1}\), is obviously in the direction of the position of Planet 2 relative to Planet 1. We can derive \begin{align*} \vec{F}_{2\text{ on }1}&=\frac{m_1m_2}{r_{21}^2} \cdot \frac{\vec{s}_2 - \vec{s}_1}{|\vec{s}_2-\vec{s}_1|} \\ &=\frac{m_1m_2}{r_{21}^3} (\vec{s}_2-\vec{s}_1) \\ &=\frac{m_1m_2}{r_{21}^3} \cdot (s_{x2}-s_{x1},s_{y2}-s_{y1}) \end{align*}
By Newton's Second Law, the acceleration on a body is related to the net force, \(\vec{F}_{net}\) , on the body $$\vec{F}_{net}=m\vec{a}$$ The net force is just the sum of all the forces on the body. The net force on the planets would then be the sum of forces by all the other planets \begin{align*} m_i\vec{a}_i = \vec{F}_{\text{net on }i} &= \sum_{\substack{0 \leq j < n \\ j \neq i}} \frac{m_jm_i}{r_{ji}^3}(\vec{s}_j - \vec{s}_i) \\ \therefore \vec{a}_i &= \sum_{\substack{0 \leq j < n \\ j \neq i}} \frac{m_j}{r_{ji}^3}(\vec{s}_j - \vec{s}_i) \\ &= \sum_{\substack{0 \leq j < n \\ j \neq i}} \frac{m_j}{\Big(\sqrt{(s_{xj}-s_{xi})^2+(s_{yj}-s_{yi})^2}\Big)^3}(\vec{s}_j - \vec{s}_i) \end{align*} The acceleration is related to the displacements in this fashion, but the acceleration is also the second derivative of the displacement. This is a second order differential equation, which is hard to solve in general.
The displacement of all the planets are to be approximated at regular time intervals of $\Delta t$ seconds. Intuitively, if $\Delta t \rightarrow 0$, we expect that the instantaneous velocity to be very very close in that time interval, and similarly for acceleration. In other words, the velocities and accelerations would be approximately uniform, which gives the approximations $$\vec{s}(t+\Delta t)=\vec{s}(t) + \Delta t \cdot \vec{v}(t)\phantom{eee}\vec{v}(t+\Delta t)=\vec{v}(t) + \Delta t \cdot \vec{a}(t)$$ where $\vec{a}(t)$ can be computed as before.
Whenever two planets come too close to each other (in our purposes $|\vec{s}_i-\vec{s}_j|<0.1$), a collision occurs. For simplicity, the collision is to be handled in this fashion:
In this lab, the codes for rendering and configuration of planets are already provided. You only need to implement the Planet class in Planet.cpp and the function do_single_iteration for an iteration of the simulation in Simulation.cpp.
const int FPS - How many frames per second in the animation. const int STEPS - How many iterations of simulation per frame. const int MAX_PLANETS - The length of the array of planets.Planet planets[MAX_PLANETS] - The array of planets.Planet classbool activated - Whether the planet is enabled. It is unnecessary to perform calculations on disabled planets. bool flag_deactivate - If this is flagged true, disable the planet later. activated = false may cause logical errors, as the attribute activated is itself used in the collision checking.double x,y,vx,vy,ax,ay - The displacement, velocity and acceleration of the planet. int mass - The mass of the planet. int uid - The index of the planet in the array. Planet classvoid determine_collision() - Determines the collision and updates flag_deactivate according to the collision rules. void update_acceleration() - Computes the acceleration by the formula above. void update_velocity() - Computes the velocity using the approximation method with acceleration. void update_displacement() - Computes the displacement using the approximation method with velocity. void do_single_iteration() - Runs a single iteration of the simulation. Note: In order to avoid discrepancies of the output from your program with the demo, you should use the following conventions (unless explicitly stated otherwise):
Recall that STEPS * FPS are the number of iterations per second. Therefore $\Delta t = \frac{1}{STEPS \times FPS}$. So the approximation of displacement would be
$$\vec{s}_{\text{new}}=\vec{s}(t+\Delta t) = \vec{s}(t) + \Delta t \cdot \vec{v}(t) = \vec{s} + \frac{\vec{v}}{STEPS \times FPS}$$
*** For those of you who
are not familiar with Physics, please use the
following formula to implement the member
functions. ***
$$s_{x\text{new}}=s_x + \frac{v_x}{STEPS \times FPS}$$
$$s_{y\text{new}}=s_y + \frac{v_y}{STEPS \times FPS}$$
The approximation of the velocity is similar. Use the operator += whenever possible.
void Planet::update_velocity();
void Planet::update_displacement();
Recall that the acceleration vector of Planet $i$ is given by the formula
$$\vec{a}_i = \sum_{\substack{0 \leq j < n \\ j \neq i}} \frac{m_j \cdot (\vec{s}_j - \vec{s}_i)}{r_{ji}^3}$$
*** For those of you who
are not familiar with Physics, please use the
following formula to implement the member
function. ***
$$a_{xi} = \sum_{\substack{0 \leq j < n \\ j \neq i}} \frac{m_j \cdot (s_{xj} - s_{xi})}{r_{ji}^3}$$
$$a_{yi} = \sum_{\substack{0 \leq j < n \\ j \neq i}} \frac{m_j \cdot (s_{yj} - s_{yi})}{r_{ji}^3}$$
where $r_{ij}=|\vec{s}_j - \vec{s}_i|$ is the distance between planets $i,j$. Use std::hypot in the header cmath to compute the distance, and use $r_{ji} \cdot r_{ji} \cdot r_{ji}$ to compute the cube of the length.
You should also check Planet::activated, inactive planets should not contribute any gravitational force towards the current planet.
void Planet::update_acceleration(); // Updates the acceleration of the planet
Recall that we handle the collision in this fashion:
std::hypot).Planet::activated to false to avoid logical errors. Flag Planet::flag_deactivate to true instead so the planet gets deactivated later.
void Planet::determine_collision();
This function is in Simulation.cpp.
void do_single_iteration();
You should complete the body of this function, which does the following in order.
commit_activationsDisplay.h. There are FPS frames in one second, and this function is called STEPS times every frame.
Y 0 0 0 0 4 Y 0 6 10 0 1 n A
Y 0 0 0 0 4 Y 0 6 10 0 1 Y 0 -6 -9 -1 1 n A
Simulation.cpp and Planet.cpp and zip them as lab5.zip for submission to ZINC.