I am trying to build a monte-carlo simulation from the ground up using only ROOT to handle geometries and navigation (i.e: I am not using GEANT in any way). My simulation is of very low energy particles which move under gravity, so the simulation must do navigation along parabolic trajectories.
One way to do this would be to approximate the path as a series of small straight-line steps, such as using TGeoNavigator::FindNextBoundaryAndStep(). However I want to implement a system more akin to “FindNextBoundaryAndStep[b]AlongParabola/b”, that solves for the actual intersection between the boundary and the parabolic trajectory.
To do this, I want to copy the process that ROOT uses in FindNextBoundaryAndStep, where I ask the current volume for its shape and then call TGeoShape::DistFromInside/Outside. To do this, I envisaged needing to add new methods to all of the shapes such as TimeFromInsideAlongParabola(), (or at least implement TGeoBBox, and any others that I wish to use in my program, such as the tube and the torus). I would also need to change the navigator to recognise the presence of a gravitational field object and then call these parabolic-intersection finding methods instead of the usual straight-line intersection methods.
One way to do all this would be for me to alter my local copy of the ROOT source code on my computer to add the new methods I wish to add. However I would strongly prefer not to tarnish ROOT with my handiwork, and would rather find a way to add this new functionality to new classes that I would make to inherit from those in ROOT.
So those are my aims and what I am trying to achieve. I am writing this post to ask for any advice with doing this sort of thing.
I have found it very difficult to implement any new functionality through inheritance because I imagine some of the classes in TGeom obviously weren’t designed expecting anything to inherit from them in this way. For example, supposing I wanted to make a new class: TMyGeoNavigator that inherits from TGeoNavigator, that re-implements ‘FindNextBoundaryAndStep()’ in a slightly different way. This is impossible since it isn’t virtual. So then I create a new method - ‘FindNextBoundaryAndStepAlongParabola()’ - which I will have to access by casting down any TGeoNavigator-type pointer to this type before calling. However the difficultly I now run into is that I cannot change the value of any of the private members of TGeoNavigator, for example the pointer fNextNode or the flag fIsOnBoundary - since they do not have any mutator methods.
To get around this then, I have to create new pointers and new flags to replicate those in TGeoNavigator, which then requires my program to always distinguish between when to use this flag and when to use the base-class flag… As you can see this is now getting extremely messy and difficult to actually implement in any sort of safe/debuggable way.
I could use composition to change the interface of the class, however I would then need to re-create the entire TGeoNavigator class-interface more or less intact in TMyGeoNavigator, and would then have to ensure that all other classes, such at TGeoManager, are also altered in some way so as to only make calls to TMyGeoNavigator.
I think I will not get into how I have added new methods to the TGeoShape’s for now, for the sake of post-length, but hopefully this illustrates how hackish/ugly what I am doing is. I have had some success in getting it to work, but it is far from pleasant and is becoming harder and harder to debug.
To be extremely cheeky, I suppose what I would like to ask is this: would it be at all possible/not-harmful to add the word virtual to the front of the methods in a few classes in TGeom in a future distribution of ROOT, and also add some simple mutator methods for those private data members that don’t have one (or make them protected).
Any other suggestions welcome. If your suggestion is ‘use Geant’, can you tell me why this would work there, and whether they have shapes and tracking methods that I can inherit from and adapt as indicated above.