Comment 1: Your Coordinate Scheme abstraction is at the right level.
As long as the classes are templated off "CoordSystem" I explored the
possibility of making CoordSystem mean what it would mean to a (mathematical)
physicist. That is, the coordinate system tells you:
1) How you are parameterizing space (cartesian, spherical polar, etc.) --
let's call that the CoordinateScheme
2) What is the orientation of the axes of your system relative to some global
system?
3) What is the displacement of the Origin? (This is relevant only for
PositionVector -- Point3D etc. -- and not for DisplacementVector).
Taking the ground rules to be that whatever we do can't add per-vector memory
and can't have runtime speed costs, can we do this cleanly?
The answer (ask me if you want a detailed write-up) is "almost." If there
were a (compile-time) fixed number of Coordinate Systems in use, then I have
a good scheme. But that would just tease writiers of general purpose
simulation and reconstruction tools, that want to take their geometry from
run-time data.
Bottom line:
* Your level of coordinate system extraction (just the scheme) is as far as
* we should go.
Comment 1a: Should we go even simpler, with just Cartesian coordinates?
What is one "seminal use case" that says that internal representation in
spherical or cylindrical-eta coordinates is important. (Remember, one can
always extract eta() or phi() or r() from a given vector if it is only needed
once.)
If we can't think of such a use case, we should consider bactracking to only
Cartesian coordinates.
Comment 2:
It appears that (given that we do template off what I'm calling the coordinate
scheme) the use of Basic3DObject is an unnecessary extra level of inheritance.
(Yes, I know it costs zero in speed/space after optimization, but it costs in
complexity.)
We can get everything we need by the following design:
// CoordinateSchemes contain various methods which currently are in the
// Basic3DObject template:
template
class CartesianCoordinates;
template class ShericalPolarCoordinates;
template class CylindricalRapidityCoordinates;
typedef DisplacementVector3D DispacementVector
// The vector template looks like:
template
class DisplacementVector3D {
typedef typename CoordinateScheme::scalar_type Scalar
public:
DisplacementVector3D() : m() {}
DisplacementVector3D() : m(Scalar v1, Scalar v2, Scalar v3) : m(v1, v2, v3)
{}
// various methods follow ...
private:
CoordinateScheme::Coordinates m;
}
Each method a class is permitted to use has a trivial forwarding to use
its CoordinateScheme.
Code using different CoordinateSchemes would look something like:
DispacementVector v1; // same as DispacementVector3D
DispacementVector3D v2;
DispacementVector3D v3 = 4.5 * v2;
// very easy; only v2.m.r would be scaled up
DispacementVector3D v4 = v1 + v2;
// this is much harder; v2 has to be converted to cartesian
DispacementVector3D v5 = v2 + v1;
// we need to implement the optimal way to do such things;
// converting v1 to spherical and then adding seems silly
DisplacementVector3D<CartesianCoordinates >vf1;
We should probably enforce that every CoordinateScheme satisfies the
requirements of some model, either by imposing constraints (a la Stroustrup)
or by abstract interface inheritance. That way, only that model needs to
be in the public user documentation.