Have a beam of particles turn corners

Short question: How do I steer a beam of particles around the inside of a circular tube?

Long question:
I've started working on a game which simulates a particle accelerator, where a player will create two beams of particles and move them closer together until the particles start to collide. So right now I have two classes (aside from the game class itself), Particle and ParticleBeam. A ParticleBeam is just a homogeneous (all the same) std::vector of Particles. When you call the ParticleBeam::Update method it iterates over the vector and calls the Particle::Update method for each particle, so every particle is in charge of where it is, how fast it is going, etc. What I need is a way of steering the beam around inside the accelerator, which is a circle (actually, it's two concentric circles).

Particle class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
class Particle {
public:
	std::string	Name;		/**< The particle's name. */
	sf::Color	Color;		/**< The particle's colour. */
	sf::Vector2f	Position;	/**< The position vector. */
	sf::Vector2f	Velocity;	/**< The velocity (m s^-1). */
	sf::Vector2f	Acceleration;	/**< The acceleration (m s^-2). */
	const unsigned	RestMass;	/**< The rest mass (kg). */
	const double	Radius;		/**< The radius (m). */
	unsigned	Mass;		/**< The relativistic mass (kg). */

	/**
	 * \brief	Constructor.
	 * \param name	The particle's name.
	 * \param color	The particle's colour.
	 * \param pos	The initial position.
	 * \param mass	The particle's (rest) mass.
	 * \param radius The particle's radius.
	 * \param veloc	(optional) The initial velocity.
	 * \param accel	(optional) The initial acceleration.
	 */
	Particle(std::string name, sf::Color color, sf::Vector2f pos,
						unsigned mass, double radius,
					sf::Vector2f veloc = sf::Vector2f(0, 0),
				sf::Vector2f accel = sf::Vector2f(0, 0));

	/**
	 * \brief	Calculates the magnitude of a vector.
	 * \param vector The vector.
	 * \return	The magnitude of the vector.
	 */
	double GetVectorMagnitude(sf::Vector2f vector);

	/**
	 * \brief	Calculates the kinetic energy.
	 * \return	The kinetic energy.
	 */
	double GetKineticEnergy();

	/**
	 * \brief	Checks whether the particle is inside of a circle.
	 * \param circle The circle.
	 * \return	If the particle is inside the circle, true is returned.
	 *		Otherwise, false is returned.
	 */
	bool InsideCircle(sf::Shape circle);

	/**
	 * \brief	Checks whether the particle is on the circumference of a
	 *		circle.
	 * \param circle The circle.
	 * \return	If the particle is on the circle, true is returned.
	 *		Otherwise, false is returned.
 	*/
	bool OnCircle(sf::Shape circle);

	/**
	 * \brief	Checks whether the particle is outside of a circle.
	 * \return	If the particle is outside of the circle, true is
	 *		returned. Otherwise, false is returned.
	 */
	bool OutsideCircle(sf::Shape circle);

	/**
	 * \brief	Update the particle.
	 * \param time	The time in seconds since the last call to Update or
	 *		since construction, whichever is more recent.
	 * \param inner	The inner circle.
	 * \param outer	The outer circle. The particle must be in between the
	 *		inner and outer circles.
	 * \return	Whether the particle is in a valid position: if the
	 *		particle goes outside of the inner or outer circle,
	 *		false is returned. Otherwise, true is returned.
	 */
	bool Update(double time, sf::Shape inner, sf::Shape outer);
};


ParticleBeam class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class ParticleBeam {
private:
	std::vector <Particle>	Particles;	/**< The particles. */
public:
	sf::Vector2f		MeanVelocity;	/**< The mean velocity. */

	/**
	 * \brief	Constructor.
	 * \param particle The particle type.
	 * \param count	The number of particles in the beam.
	 */
	ParticleBeam(Particle particle, size_t count = 1);

	/**
	 * \brief	Update the particles.
	 * \param time	The time in seconds since the last call to Update or
	 *		since construction, whichever is more recent.
	 * \param inner	The inner circle.
	 * \param outer	The outer circle. The particles must be in between the
	 *		inner and outer circles.
	 * \return	If any particles still exist, true is returned. If all
	 *		particles have been lost false is returned.
	 */
	bool Update(double time, sf::Shape inner, sf::Shape outer);
};


If you need to see the implementation, just ask.
I'm not gonna look at the code, but since I'm a physicist, I can suggest that you use simple reflections after defining the geometry of the accelerator. Use the tangent of the chamber at the point of reflection, and have the angle of collision equal to the angle of reflection.
Unless I'm mistaken, are you suggesting that I have the particles constantly reflected from an imaginary surface within the chamber? Or that the particles should come into contact with the "walls" of the accelerator?

I was thinking of simulating an electromagnetic field to guide the particles, like they do in the LHC (and probably other accelerators).

I should probably mention that, for the time being, it's only a 2D simulation. I will add a third dimension once I get what I have now working.
Off topic.
Nicely documented methods! Try something like @param and @return.
@liquidfuzz,
'\' does the same as '@' in Doxygen comments (in other words, it tells Doxygen that the following word is a command).
Topic archived. No new replies allowed.