The game must allow these operations by the player:
The elements can be positioned around the 2π azimuths only at one of cNrSectors positions, i.e. the user cannot drop an element at an arbitrary angle. cNrSectors is a number divisible by 8, such as 32 or 40. The 2π azimuths are divided into cNrSectors fixed sectors, numbered 0 to cNrSectors-1. An array gSectorElement holds the element names of the elements occupying each of these sectors.
Sections are elements that cover a sector. Each ring is built from cNrSectors curved sections. A crossing element also covers a sector. Injection and dump lines have a part covering a sector and corresponding to a curved section, plus a part that extends from the sector.
Curved sections making up the rings cannot be moved. They can be hidden, e.g. when there is a crossing or an injection or dump in the same sector.
There are one or two trains of bunches of particles injected into the machine. The trains are called the A-train or the A-bunches and the B-train or B-bunches. The trains consist always of exactly the same number of graphics, but some may be invisible if the player has suppressed some bunches. The number is equal to the number of sectors so that with a full train the rings look fully filled.
Since the geometry of the machine is determined by the player the bunches must follow a path that depends on the relative positions of the elements as placed by the player.
The path followed starts at the beginning of an injection line and returns to the end of it after one or two revolutions through the machine. If there are dumps or ejection lines a further path may be attached at the position of the dump or ejection, but we will leave this detail out of the discussion for now.
To simulate the motion of the bunches we will move them from one point to the next along a set of points placed at regular intervals along the path. The list of points can be built once the position of the elements is known, viz. at the moment the player presses the "Run" button.
To build the complete list we first pre-compute the points inside each element and we make all elements approximately the same length. This basic length is the length of a segment. The set of points spaced regularly inside an element is called the path through that element. Each path through has a point at each end of the element but only one of these is used depending on the sense in which the element is traversed by the bunches. This avoids duplicate points where elements join but still permits joining elements in both senses around the rings.
A hypothetical segment
For example, if cPathDivision is 8 then a segment will have 9 points defining the path through it: P1 P2 P3 … P8 P9. If that segment is traversed in the normal sense we use its points P2 … P9 , but we use P8 … P1 if traversed in the other sense.
There are two paths through a crossing: one for each leg of the "X" form. The central point is the collision point and it must be common to both paths. This also implies that the path through an element must be split in an even number of parts (cPathDivision must be even) so that there is always a point in the middle.
To compute the list of points successively taken up by the bunches we simply concatenate the paths through the successive elements, for each path leaving out the first point encountered in the sense of the traversal as mentioned earlier. The list is stored in an array.
There can be only two injection lines, so there are at most two paths to compute and we know where to start.
A bunch returns to the same position after a number of turns: this position is always the end of the injection line through which it came in.
In the case of a collider with crossings, the bunch makes a single turn around the rings to reach this point if there are an even number of crossings and it needs to make two turns if there is an odd number of crossings.
To concatenate, start at the beginning of an injection, then follow the rings in the sense given by the injection line (clockwise or counterclockwise). Stop when the sector is reached where the injection started. This gives an array of points gAPosition for the A-bunches and possibly a path gBPosition for the B-bunches (if there are two injection lines).
For efficiency there are two other arrays gNextAPosition and gNextBPosition which for each position give the index of next position. In general the next position of gAPosition[i] is gAPosition[i+1] and hence in general gNextAPosition[i] = i+1 but there are two exceptions: