Optimisation of Surface::intersect(...)
Closes #666 (closed)
Triggered by the following remark in the code:
// Evaluate (if necessary in terms of boundaries)
// @todo: speed up isOnSurface - we know that it is on surface
This MR adds a benchmark for Surface::intersect(...) and introduces some optimisations.
-
PlaneSurfaceduring theintersectEstimate(...)asking forinsideBounds(...)did a fullglobalToLocaltransformation. This is not necessary, as part of the information is already available in this regard.
This is a test of 100 million intersections with PlaneSurface in master:

When shifting the inverse into the method it becomes this:

And optimising the usage of Eigen a bit, we arrive at:

As a cross-check, the final implementation of this MR is faster than a by hand calculation, which is certainly also uglier:
double lx = tMatrix(0,0)*intersection.position.x()+tMatrix(0,1)*intersection.position.y()+tMatrix(0,2)*intersection.position.z();
double ly = tMatrix(1,0)*intersection.position.x()+tMatrix(1,1)*intersection.position.y()+tMatrix(1,2)*intersection.position.z();
if (not insideBounds(Vector2D(lx,ly), bcheck)) {
intersection.status = Intersection::Status::missed;
}
-
DiscSurface- following the implementation of thePlaneSurface, we start from:
And then re-using the information available inside the intersectionEstimate(...) we arrive at:
The gain is not as impressive, as we spend a significant amount of time on atan2 for the cartesian to global transformation.
-
CylinderSurface:
Here, the last MR introduced some overhead via the second solution being stored in a std::vector - I reverted that to be a simple object, and allowed for maximum of two intersections with a surface for the moment.
Start time lies at >20s for 100 million tests:

While after optimisation, the current time is ~4s:

One trick was to introduce a bool fullAzimuth() method to the CylinderBounds, which indicates full azimuthal coverage and hence saves us from checking the radial compatibility (when knowing that we are compatible).
-
StrawSurfaceorLineSurface:
And with the same modifications:

Additionally, the boundaryCheck for PerigeeSurface : public LineSurface is always omitted, as a closest approach as a perigee does not have bounds.


