From f5a34f31238f541d27b0f1238948818389e3455b Mon Sep 17 00:00:00 2001 From: Andreas Salzburger Date: Thu, 3 Oct 2024 18:17:50 +0200 Subject: [PATCH 1/5] feat!: (fix + chore) streamline nSegments usage (#3419) The generation of display vertices for segments was buggy and very unstable, I have put this onto more solid grounds, which helps displaying (not only) `AnnulusBounds` correctly. ITk Petal Before: ![Screenshot 2024-07-18 at 17 01 59](https://github.com/user-attachments/assets/930b93f2-8df7-4e80-a44b-3ec7a20a84ac) ITk Petal After: ![Screenshot 2024-07-19 at 12 07 32](https://github.com/user-attachments/assets/bc4edd4b-cc22-4b30-bad8-6032d42854da) When checking the code, I see that there was a pretty big inconsistency in how the nSegments have been handled, so I re-worked that: * `nSegments` (full 2 * PI segments) -> changed and renamed to `quaterSegments` This guarantees that the number of segments for a full circle is a multiplier of 4 and hence the phi extrema points at `(-pi,-0.5*pi,0,0.5*pi,pi)` are consistently added. This will lead to a correct `x` and `y` estimation for the `Extent` of the `Polyhedron`. This also guarantees that e.g. overlapping/attaching surfaces with the same number of segments will have vertices at the same positions, which will be better for the displaying. * inconsitent use of `unsigned int` (SurfaceBounds) and `std::size_t` -> changed to `unsigned int everywhere * Introduces tests for the vertex generation (which were missing) Co-authored-by: Paul Gessinger <1058585+paulgessinger@users.noreply.github.com> --- .../Acts/Detector/LayerStructureBuilder.hpp | 5 +- Core/include/Acts/Geometry/Polyhedron.hpp | 1 + Core/include/Acts/Surfaces/AnnulusBounds.hpp | 15 ++- Core/include/Acts/Surfaces/ConeSurface.hpp | 15 ++- .../Acts/Surfaces/ConvexPolygonBounds.hpp | 4 +- .../Acts/Surfaces/ConvexPolygonBounds.ipp | 2 +- Core/include/Acts/Surfaces/CylinderBounds.hpp | 16 ++- .../include/Acts/Surfaces/CylinderSurface.hpp | 16 ++- Core/include/Acts/Surfaces/DiamondBounds.hpp | 10 +- Core/include/Acts/Surfaces/DiscBounds.hpp | 11 +- Core/include/Acts/Surfaces/DiscSurface.hpp | 9 +- .../Acts/Surfaces/DiscTrapezoidBounds.hpp | 8 +- Core/include/Acts/Surfaces/EllipseBounds.hpp | 11 +- Core/include/Acts/Surfaces/PerigeeSurface.hpp | 4 +- Core/include/Acts/Surfaces/PlanarBounds.hpp | 11 +- Core/include/Acts/Surfaces/PlaneSurface.hpp | 12 +- .../include/Acts/Surfaces/RectangleBounds.hpp | 7 +- Core/include/Acts/Surfaces/StrawSurface.hpp | 8 +- Core/include/Acts/Surfaces/Surface.hpp | 15 ++- Core/include/Acts/Surfaces/SurfaceConcept.hpp | 2 +- .../include/Acts/Surfaces/TrapezoidBounds.hpp | 6 +- .../Acts/Surfaces/detail/FacesHelper.hpp | 8 +- .../Acts/Surfaces/detail/VerticesHelper.hpp | 71 +++++----- .../include/Acts/Visualization/ViewConfig.hpp | 4 +- .../detail/ObjVisualization3D.ipp | 4 +- Core/src/Detector/LayerStructureBuilder.cpp | 3 +- Core/src/Surfaces/AnnulusBounds.cpp | 49 ++++--- Core/src/Surfaces/CMakeLists.txt | 2 +- Core/src/Surfaces/ConeSurface.cpp | 62 ++++----- Core/src/Surfaces/CylinderBounds.cpp | 41 +++--- Core/src/Surfaces/CylinderSurface.cpp | 16 +-- Core/src/Surfaces/DiamondBounds.cpp | 2 +- Core/src/Surfaces/DiscSurface.cpp | 24 ++-- Core/src/Surfaces/DiscTrapezoidBounds.cpp | 2 +- Core/src/Surfaces/EllipseBounds.cpp | 4 +- Core/src/Surfaces/PerigeeSurface.cpp | 2 +- Core/src/Surfaces/PlaneSurface.cpp | 24 ++-- Core/src/Surfaces/StrawSurface.cpp | 19 ++- Core/src/Surfaces/Surface.cpp | 3 +- Core/src/Surfaces/TrapezoidBounds.cpp | 2 +- .../Surfaces/{ => detail}/VerticesHelper.cpp | 93 ++++++++------ Core/src/Visualization/EventDataView3D.cpp | 19 +-- Core/src/Visualization/GeometryView3D.cpp | 5 +- .../Geant4/src/SensitiveSurfaceMapper.cpp | 2 +- .../ActsExamples/Io/Svg/SvgDefaults.hpp | 6 +- Examples/Python/src/Geometry.cpp | 2 +- Examples/Python/src/Obj.cpp | 2 +- Examples/Python/src/Output.cpp | 2 +- Examples/Python/src/Svg.cpp | 2 +- .../include/Acts/Plugins/ActSVG/SvgUtils.hpp | 4 +- Plugins/ActSVG/src/SurfaceSvgConverter.cpp | 7 +- .../DD4hep/DD4hepDetectorSurfaceFactory.hpp | 4 +- .../Plugins/DD4hep/DD4hepLayerStructure.hpp | 4 +- .../src/DD4hepDetectorSurfaceFactory.cpp | 4 +- Plugins/DD4hep/src/DD4hepLayerStructure.cpp | 2 +- .../GeoModel/GeoModelBlueprintCreater.hpp | 4 +- .../GeoModel/src/GeoModelBlueprintCreater.cpp | 2 +- .../Tests/CommonHelpers/LineSurfaceStub.hpp | 4 +- .../Core/Surfaces/AnnulusBoundsTests.cpp | 27 +++- .../Surfaces/ConvexPolygonBoundsTests.cpp | 4 + .../Core/Surfaces/PolyhedronSurfacesTests.cpp | 46 ++++--- Tests/UnitTests/Core/Surfaces/SurfaceStub.hpp | 2 +- .../Core/Surfaces/VerticesHelperTests.cpp | 121 ++++++++++++++++++ .../UnitTests/Core/TrackFitting/Gx2fTests.cpp | 2 +- .../Visualization/EventDataView3DTests.cpp | 8 +- .../Core/Visualization/SurfaceView3DBase.hpp | 24 ++-- .../TrackingGeometryView3DBase.hpp | 28 ++-- .../Fatras/Digitization/SegmentizerTests.cpp | 4 +- .../IndexedSurfacesSvgConverterTests.cpp | 2 +- .../Plugins/ActSVG/LayerSvgConverterTests.cpp | 23 ++-- .../ActSVG/PortalSvgConverterTests.cpp | 4 +- .../ActSVG/SurfaceSvgConverterTests.cpp | 4 +- .../TrackingGeometrySvgConverterTests.cpp | 2 +- .../Plugins/TGeo/TGeoTubeConversionTests.cpp | 1 - 74 files changed, 577 insertions(+), 423 deletions(-) rename Core/src/Surfaces/{ => detail}/VerticesHelper.cpp (55%) diff --git a/Core/include/Acts/Detector/LayerStructureBuilder.hpp b/Core/include/Acts/Detector/LayerStructureBuilder.hpp index 9dd0e0a8e8e..02fd726824e 100644 --- a/Core/include/Acts/Detector/LayerStructureBuilder.hpp +++ b/Core/include/Acts/Detector/LayerStructureBuilder.hpp @@ -91,8 +91,9 @@ class LayerStructureBuilder : public IInternalStructureBuilder { /// Minimum number of surfaces to build an internal structure /// - otherwise the tryAll options is used unsigned int nMinimalSurfaces = 4u; - /// Polyhedron approximations - unsigned int nSegments = 1u; + /// Polyhedron approximations: number of segments to be used + /// to approximate a quarter of a circle + unsigned int quarterSegments = 1u; /// Extra information, mainly for screen output std::string auxiliary = ""; }; diff --git a/Core/include/Acts/Geometry/Polyhedron.hpp b/Core/include/Acts/Geometry/Polyhedron.hpp index 2a6eb47d765..00ccaaab4c5 100644 --- a/Core/include/Acts/Geometry/Polyhedron.hpp +++ b/Core/include/Acts/Geometry/Polyhedron.hpp @@ -39,6 +39,7 @@ struct Polyhedron { /// @param facesIn List of lists of indices for faces. /// @param triangularMeshIn List of lists of indices for a triangular mesh /// @param isExact A dedicated flag if this is exact or not + /// /// @note This creates copies of the input vectors Polyhedron(const std::vector& verticesIn, const std::vector& facesIn, diff --git a/Core/include/Acts/Surfaces/AnnulusBounds.hpp b/Core/include/Acts/Surfaces/AnnulusBounds.hpp index 17e64f2a505..f1283ec63b8 100644 --- a/Core/include/Acts/Surfaces/AnnulusBounds.hpp +++ b/Core/include/Acts/Surfaces/AnnulusBounds.hpp @@ -133,19 +133,20 @@ class AnnulusBounds : public DiscBounds { std::vector corners() const; /// This method returns the xy coordinates of the four corners of the - /// bounds in module coordinates (in x/y) + /// bounds in module coordinates (in x/y), and if quarterSegments is bigger or + /// equal to 0, the curved part of the segment is included and approximated + /// by the corresponding number of segments. + /// /// Starting from the upper right (max R, pos locX) and proceeding clock-wise /// i.e. (max R; pos locX), (min R; pos locX), (min R; neg loc X), (max R: neg /// locX) /// - /// @param lseg the number of segments used to approximate - /// and eventually curved line - /// - /// @note that that if @c lseg > 0, the extrema points are given, - /// which may slightly alter the number of segments returned + /// @param quarterSegments the number of segments used to approximate + /// a quarter of a circle /// /// @return vector for vertices in 2D - std::vector vertices(unsigned int lseg) const override; + std::vector vertices( + unsigned int quarterSegments = 2u) const override; /// This method returns inner radius double rMin() const final; diff --git a/Core/include/Acts/Surfaces/ConeSurface.hpp b/Core/include/Acts/Surfaces/ConeSurface.hpp index c15d84d1c23..a2b2572bba8 100644 --- a/Core/include/Acts/Surfaces/ConeSurface.hpp +++ b/Core/include/Acts/Surfaces/ConeSurface.hpp @@ -200,15 +200,16 @@ class ConeSurface : public RegularSurface { /// Return a Polyhedron for the surfaces /// /// @param gctx The current geometry context object, e.g. alignment - /// @param lseg Number of segments along curved lines, it represents - /// the full 2*M_PI coverange, if lseg is set to 1 only the extrema - /// are given - /// @note that a surface transform can invalidate the extrema - /// in the transformed space + /// @param quarterSegments Number of segments used to approximate a quarter + /// + /// @note The phi extrema points at (-pi, -1/2 pi, 0, 1/2 pi) that fall within + /// the surface will be inserted to guarantee an appropriate extent + /// measurement in x and y /// /// @return A list of vertices and a face/facett description of it - Polyhedron polyhedronRepresentation(const GeometryContext& gctx, - std::size_t lseg) const override; + Polyhedron polyhedronRepresentation( + const GeometryContext& gctx, + unsigned int quarterSegments = 2u) const override; /// Return properly formatted class name for screen output std::string name() const override; diff --git a/Core/include/Acts/Surfaces/ConvexPolygonBounds.hpp b/Core/include/Acts/Surfaces/ConvexPolygonBounds.hpp index 2f116ddcee5..e802056e7fd 100644 --- a/Core/include/Acts/Surfaces/ConvexPolygonBounds.hpp +++ b/Core/include/Acts/Surfaces/ConvexPolygonBounds.hpp @@ -114,13 +114,13 @@ class ConvexPolygonBounds : public ConvexPolygonBoundsBase { /// Return the vertices /// - /// @param lseg the number of segments used to approximate + /// @param ignoredSegments the number of segments used to approximate /// and eventually curved line /// /// @note the number of segments is ignored in this representation /// /// @return vector for vertices in 2D - std::vector vertices(unsigned int lseg = 1) const final; + std::vector vertices(unsigned int ignoredSegments = 0u) const final; /// Return a rectangle bounds object that encloses this polygon. /// @return The rectangular bounds diff --git a/Core/include/Acts/Surfaces/ConvexPolygonBounds.ipp b/Core/include/Acts/Surfaces/ConvexPolygonBounds.ipp index 505d9f95d82..9f1a61955ae 100644 --- a/Core/include/Acts/Surfaces/ConvexPolygonBounds.ipp +++ b/Core/include/Acts/Surfaces/ConvexPolygonBounds.ipp @@ -111,7 +111,7 @@ bool Acts::ConvexPolygonBounds::inside( template std::vector Acts::ConvexPolygonBounds::vertices( - unsigned int /*lseg*/) const { + unsigned int /*ignoredSegments*/) const { return {m_vertices.begin(), m_vertices.end()}; } diff --git a/Core/include/Acts/Surfaces/CylinderBounds.hpp b/Core/include/Acts/Surfaces/CylinderBounds.hpp index 7453029c213..51508055e06 100644 --- a/Core/include/Acts/Surfaces/CylinderBounds.hpp +++ b/Core/include/Acts/Surfaces/CylinderBounds.hpp @@ -112,12 +112,18 @@ class CylinderBounds : public SurfaceBounds { /// Returns true for full phi coverage bool coversFullAzimuth() const; - /// Create the bows/circles on either side of the cylinder + /// Create the bow/circle vertices on either side of the cylinder /// - /// @param trans is the global transform - /// @param lseg are the numbero if phi segments - std::vector createCircles(const Transform3 trans, - std::size_t lseg) const; + /// @param transform is the global transform + /// @param quarterSegments is the number of segments to approximate a quarter + /// of a circle. In order to symmetrize fully closed and sectoral cylinders, + /// also in the first case the two end points are given (albeit they overlap) + /// in -pi / pi + /// + /// @return a singlevector containing the vertices from one side and then + /// from the other side consecutively + std::vector circleVertices(const Transform3 transform, + unsigned int quarterSegments) const; /// Output Method for std::ostream std::ostream& toStream(std::ostream& sl) const final; diff --git a/Core/include/Acts/Surfaces/CylinderSurface.hpp b/Core/include/Acts/Surfaces/CylinderSurface.hpp index 82bc1c68bc2..09b953afce1 100644 --- a/Core/include/Acts/Surfaces/CylinderSurface.hpp +++ b/Core/include/Acts/Surfaces/CylinderSurface.hpp @@ -214,14 +214,20 @@ class CylinderSurface : public RegularSurface { /// Return a Polyhedron for a cylinder /// + /// This method represents the cylinder as a polyhedron with a given number + /// of segments to represent a quarter of a full circle. The polyedron will + /// consist of the vertices of the cylinder on both sides, and faces between + /// them, both as rectangular faces and as triangular faces. + /// /// @param gctx The current geometry context object, e.g. alignment - /// @param lseg Number of segments along curved lines, it represents - /// the full 2*M_PI coverange, if lseg is set to 1 only the extrema - /// are given + /// @param quarterSegments The number of segments to approximate a quarter of the + /// full circle; it's chosen to be 1, only the extrema points (-pi, -0.5pi, + /// 0., 0.5pi) are inserted to capture the correct extent in the x-y plane /// /// @return A list of vertices and a face/facett description of it - Polyhedron polyhedronRepresentation(const GeometryContext& gctx, - std::size_t lseg) const override; + Polyhedron polyhedronRepresentation( + const GeometryContext& gctx, + unsigned int quarterSegments = 2u) const override; /// Calculate the derivative of path length at the geometry constraint or /// point-of-closest-approach w.r.t. alignment parameters of the surface (i.e. diff --git a/Core/include/Acts/Surfaces/DiamondBounds.hpp b/Core/include/Acts/Surfaces/DiamondBounds.hpp index ddaf727a3e9..a23b8831125 100644 --- a/Core/include/Acts/Surfaces/DiamondBounds.hpp +++ b/Core/include/Acts/Surfaces/DiamondBounds.hpp @@ -90,15 +90,13 @@ class DiamondBounds : public PlanarBounds { bool inside(const Vector2& lposition, const BoundaryTolerance& boundaryTolerance) const final; - /// Return the vertices + /// Return the vertices that describe this shape /// - /// @param lseg the number of segments used to approximate - /// and eventually curved line - /// - /// @note the number of segments is ignored for this representation + /// @param ignoredSegments is an ignored parameter only used for + /// curved bound segments /// /// @return vector for vertices in 2D - std::vector vertices(unsigned int lseg = 1) const final; + std::vector vertices(unsigned int ignoredSegments = 0u) const final; // Bounding box representation const RectangleBounds& boundingBox() const final; diff --git a/Core/include/Acts/Surfaces/DiscBounds.hpp b/Core/include/Acts/Surfaces/DiscBounds.hpp index 22bcce3f960..626f8e2405c 100644 --- a/Core/include/Acts/Surfaces/DiscBounds.hpp +++ b/Core/include/Acts/Surfaces/DiscBounds.hpp @@ -29,14 +29,13 @@ class DiscBounds : public SurfaceBounds { /// Return the vertices /// - /// @param lseg the number of segments used to approximate - /// and eventually curved line, the number refers to full 2*PI - /// - /// @note that the extremas are given, which may slightly alter the - /// number of segments returned + /// @param quarterSegments The number of segments used to describe a quarter + /// of a circle, if it is 1, then only the extrema points in phi are inserted + /// next to the segment corners /// /// @return vector for vertices in 2D - virtual std::vector vertices(unsigned int lseg) const = 0; + virtual std::vector vertices( + unsigned int quarterSegments = 2u) const = 0; /// Returns a reference radius for binning virtual double binningValueR() const = 0; diff --git a/Core/include/Acts/Surfaces/DiscSurface.hpp b/Core/include/Acts/Surfaces/DiscSurface.hpp index 112ec0b30d2..e2c10df4023 100644 --- a/Core/include/Acts/Surfaces/DiscSurface.hpp +++ b/Core/include/Acts/Surfaces/DiscSurface.hpp @@ -312,13 +312,12 @@ class DiscSurface : public RegularSurface { /// Return a Polyhedron for the surfaces /// /// @param gctx The current geometry context object, e.g. alignment - /// @param lseg Number of segments along curved lines, it represents - /// the full 2*M_PI coverange, if lseg is set to 1 only the extrema - /// are given + /// @param quarterSegments Number of segments used to describe the + /// quarter of a full circle /// /// @return A list of vertices and a face/facett description of it - Polyhedron polyhedronRepresentation(const GeometryContext& gctx, - std::size_t lseg) const override; + Polyhedron polyhedronRepresentation( + const GeometryContext& gctx, unsigned int quarterSegments) const override; /// Calculate the derivative of bound track parameters local position w.r.t. /// position in local 3D Cartesian coordinates diff --git a/Core/include/Acts/Surfaces/DiscTrapezoidBounds.hpp b/Core/include/Acts/Surfaces/DiscTrapezoidBounds.hpp index 1e4d9d7706a..a3e4e5ea28f 100644 --- a/Core/include/Acts/Surfaces/DiscTrapezoidBounds.hpp +++ b/Core/include/Acts/Surfaces/DiscTrapezoidBounds.hpp @@ -123,13 +123,11 @@ class DiscTrapezoidBounds : public DiscBounds { /// This method returns the xy coordinates of the four corners of the /// bounds in module coorindates (in xy) /// - /// @param lseg the number of segments used to approximate - /// and eventually curved line - /// - /// @note that the number of segments are ignored for this surface + /// @param ignoredSegments is an ignored parameter only used for + /// curved bound segments /// /// @return vector for vertices in 2D - std::vector vertices(unsigned int lseg) const final; + std::vector vertices(unsigned int ignoredSegments = 0u) const final; private: std::array m_values; diff --git a/Core/include/Acts/Surfaces/EllipseBounds.hpp b/Core/include/Acts/Surfaces/EllipseBounds.hpp index dc6983b86bb..aec08d10381 100644 --- a/Core/include/Acts/Surfaces/EllipseBounds.hpp +++ b/Core/include/Acts/Surfaces/EllipseBounds.hpp @@ -92,14 +92,13 @@ class EllipseBounds : public PlanarBounds { /// Return the vertices /// - /// @param lseg the number of segments used to approximate - /// and eventually curved line, here it refers to the full 2PI Ellipse - /// - /// @note the number of segments to may be altered by also providing - /// the extremas in all direction + /// @param quarterSegments is the number of segments to approximate a quarter + /// of a circle. In order to symmetrize fully closed and sectoral cylinders, + /// also in the first case the two end points are given (albeit they overlap) + /// in -pi / pi /// /// @return vector for vertices in 2D - std::vector vertices(unsigned int lseg) const final; + std::vector vertices(unsigned int quarterSegments) const final; // Bounding box representation const RectangleBounds& boundingBox() const final; diff --git a/Core/include/Acts/Surfaces/PerigeeSurface.hpp b/Core/include/Acts/Surfaces/PerigeeSurface.hpp index 37b1044f0ce..1d913ecc43e 100644 --- a/Core/include/Acts/Surfaces/PerigeeSurface.hpp +++ b/Core/include/Acts/Surfaces/PerigeeSurface.hpp @@ -76,11 +76,11 @@ class PerigeeSurface : public LineSurface { /// Return a Polyhedron for the surfaces /// /// @param gctx The current geometry context object, e.g. alignment - /// @param lseg is ignored for a perigee @note ignored + /// @param ingoreSegments is an ignored parameter /// /// @return A list of vertices and a face/facett description of it Polyhedron polyhedronRepresentation(const GeometryContext& gctx, - std::size_t lseg) const final; + unsigned int ingoreSegments) const final; protected: /// Output Method for std::ostream diff --git a/Core/include/Acts/Surfaces/PlanarBounds.hpp b/Core/include/Acts/Surfaces/PlanarBounds.hpp index 8c4363dbbc3..28bc0e42b60 100644 --- a/Core/include/Acts/Surfaces/PlanarBounds.hpp +++ b/Core/include/Acts/Surfaces/PlanarBounds.hpp @@ -26,14 +26,15 @@ class PlanarBounds : public SurfaceBounds { public: /// Return the vertices /// - /// @param lseg the number of segments used to approximate - /// and eventually curved line + /// @param quarterSegments is the number of segments used to describe curved + /// segments in a quarter of the phi range. If it is 1, then only the extrema + /// points in phi are inserted next to the segment corners. /// - /// @note that the extremas are given, which may slightly alter the - /// number of segments returned + /// @note for planar bounds without curved segments @c quarterSegments is ignored /// /// @return vector for vertices in 2D - virtual std::vector vertices(unsigned int lseg = 1) const = 0; + virtual std::vector vertices( + unsigned int quarterSegments = 2u) const = 0; /// Bounding box parameters /// diff --git a/Core/include/Acts/Surfaces/PlaneSurface.hpp b/Core/include/Acts/Surfaces/PlaneSurface.hpp index 866cb4d4585..2bc65398f8d 100644 --- a/Core/include/Acts/Surfaces/PlaneSurface.hpp +++ b/Core/include/Acts/Surfaces/PlaneSurface.hpp @@ -198,13 +198,15 @@ class PlaneSurface : public RegularSurface { /// Return a Polyhedron for the surfaces /// /// @param gctx The current geometry context object, e.g. alignment - /// @param lseg Number of segments along curved lines, it represents - /// the full 2*M_PI coverange, if lseg is set to 1 only the extrema - /// are given + /// @param quarterSegments is the number of segments used to describe curved + /// segments in a quarter of the phi range. If it is 1, then only the extrema + /// points in phi are inserted next to the segment corners. + /// + /// @note for planar surfaces without curved segments @c quarterSegments is ignored /// /// @return A list of vertices and a face/facett description of it - Polyhedron polyhedronRepresentation(const GeometryContext& gctx, - std::size_t lseg) const override; + Polyhedron polyhedronRepresentation( + const GeometryContext& gctx, unsigned int quarterSegments) const override; /// Return properly formatted class name for screen output std::string name() const override; diff --git a/Core/include/Acts/Surfaces/RectangleBounds.hpp b/Core/include/Acts/Surfaces/RectangleBounds.hpp index 7ad67f3aafb..aba1743fa74 100644 --- a/Core/include/Acts/Surfaces/RectangleBounds.hpp +++ b/Core/include/Acts/Surfaces/RectangleBounds.hpp @@ -86,13 +86,12 @@ class RectangleBounds : public PlanarBounds { /// Return the vertices /// - /// @param lseg the number of segments used to approximate - /// and eventually curved line - /// + /// @param quarterSegments is the number of segments used to describe curved + /// segments in a quarter of the phi range. /// @note the number of segments is ignored in this representation /// /// @return vector for vertices in 2D - std::vector vertices(unsigned int lseg = 1) const final; + std::vector vertices(unsigned int quarterSegments = 0u) const final; // Bounding box representation const RectangleBounds& boundingBox() const final; diff --git a/Core/include/Acts/Surfaces/StrawSurface.hpp b/Core/include/Acts/Surfaces/StrawSurface.hpp index 88fd8423525..706bb7d9823 100644 --- a/Core/include/Acts/Surfaces/StrawSurface.hpp +++ b/Core/include/Acts/Surfaces/StrawSurface.hpp @@ -92,13 +92,13 @@ class StrawSurface : public LineSurface { /// Return a Polyhedron for the surfaces /// /// @param gctx The current geometry context object, e.g. alignment - /// @param lseg Number of segments along curved lines, it represents - /// the full 2*M_PI coverange, if lseg is set to 1 only the extrema - /// are given @note if lseg is set to 1 then only the straw is created + /// @param quarterSegments is the number of segments used to describe curved + /// segments in a quarter of the phi range. If it is 1, then only the extrema + /// points in phi are inserted next to the segment corners. /// /// @return A list of vertices and a face/facett description of it Polyhedron polyhedronRepresentation(const GeometryContext& gctx, - std::size_t lseg) const final; + unsigned int quarterSegments) const final; }; inline Surface::SurfaceType StrawSurface::type() const { diff --git a/Core/include/Acts/Surfaces/Surface.hpp b/Core/include/Acts/Surfaces/Surface.hpp index c93e7d3c9aa..3a823671823 100644 --- a/Core/include/Acts/Surfaces/Surface.hpp +++ b/Core/include/Acts/Surfaces/Surface.hpp @@ -418,20 +418,21 @@ class Surface : public virtual GeometryObject, /// Return properly formatted class name virtual std::string name() const = 0; - /// Return a Polyhedron for this object + /// Return a Polyhedron for surface objects /// /// @param gctx The current geometry context object, e.g. alignment - /// @param lseg Number of segments along curved lines, if the lseg - /// is set to one, only the corners and the extrema are given, - /// otherwise it represents the number of segments for a full 2*M_PI - /// circle and is scaled to the relevant sector + /// @param quarterSegments The number of segemtns to approximate a 0.5*pi sector, + /// which represents a quarter of the full circle + /// + /// @note In order to symmetrize the code between sectoral and closed cylinders + /// in case of closed cylinders, both (-pi, pi) are given as separate vertices /// /// @note An internal surface transform can invalidate the extrema /// in the transformed space /// /// @return A list of vertices and a face/facett description of it - virtual Polyhedron polyhedronRepresentation(const GeometryContext& gctx, - std::size_t lseg) const = 0; + virtual Polyhedron polyhedronRepresentation( + const GeometryContext& gctx, unsigned int quarterSegments = 2u) const = 0; /// The derivative of bound track parameters w.r.t. alignment /// parameters of its reference surface (i.e. local frame origin in diff --git a/Core/include/Acts/Surfaces/SurfaceConcept.hpp b/Core/include/Acts/Surfaces/SurfaceConcept.hpp index e09b420ee9f..2abcda1d5d7 100644 --- a/Core/include/Acts/Surfaces/SurfaceConcept.hpp +++ b/Core/include/Acts/Surfaces/SurfaceConcept.hpp @@ -87,7 +87,7 @@ concept SurfaceConcept = requires(S s, const S cs, S s2, const S cs2, { cs.name() } -> std::same_as; { - cs.polyhedronRepresentation(gctx, std::declval()) + cs.polyhedronRepresentation(gctx, std::declval()) } -> std::same_as; { diff --git a/Core/include/Acts/Surfaces/TrapezoidBounds.hpp b/Core/include/Acts/Surfaces/TrapezoidBounds.hpp index 3f116dc4110..8ccd3a5c928 100644 --- a/Core/include/Acts/Surfaces/TrapezoidBounds.hpp +++ b/Core/include/Acts/Surfaces/TrapezoidBounds.hpp @@ -108,13 +108,13 @@ class TrapezoidBounds : public PlanarBounds { /// Return the vertices /// - /// @param lseg the number of segments used to approximate - /// and eventually curved line + /// @param ignoredSegments is and ignored parameter used to describe + /// the number of segments to approximate curved sectors. /// /// @note the number of segments is ignored in this representation /// /// @return vector for vertices in 2D - std::vector vertices(unsigned int lseg = 1) const final; + std::vector vertices(unsigned int ignoredSegments = 0u) const final; // Bounding box representation const RectangleBounds& boundingBox() const final; diff --git a/Core/include/Acts/Surfaces/detail/FacesHelper.hpp b/Core/include/Acts/Surfaces/detail/FacesHelper.hpp index 260f7ce3b01..ca2922c325e 100644 --- a/Core/include/Acts/Surfaces/detail/FacesHelper.hpp +++ b/Core/include/Acts/Surfaces/detail/FacesHelper.hpp @@ -21,7 +21,7 @@ namespace Acts::detail { struct FacesHelper { using FaceVector = std::vector; - /// @brief This method words for all convex type surface setups + /// @brief This method works for all convex type surface setups /// It includes: /// /// Rectangle / Triangle / Polygon @@ -60,14 +60,12 @@ struct FacesHelper { /// vector is splittable in half into the two bows. /// /// @param vertices The vector of vertices - /// @param fullTwoPi The indicator if the concentric face is closed static std::pair cylindricalFaceMesh( - const std::vector& vertices, bool fullTwoPi = true) { + const std::vector& vertices) { FaceVector faces; FaceVector triangularMesh; std::size_t nqfaces = static_cast(0.5 * vertices.size()); - std::size_t reduce = (!fullTwoPi) ? 1 : 0; - for (std::size_t iface = 0; iface < nqfaces - reduce; ++iface) { + for (std::size_t iface = 0; iface < nqfaces - 1; ++iface) { std::size_t p2 = (iface + 1 == nqfaces) ? 0 : iface + 1; std::vector face = {iface, p2, p2 + nqfaces, nqfaces + iface}; diff --git a/Core/include/Acts/Surfaces/detail/VerticesHelper.hpp b/Core/include/Acts/Surfaces/detail/VerticesHelper.hpp index 71938626eaf..3e63c7189e6 100644 --- a/Core/include/Acts/Surfaces/detail/VerticesHelper.hpp +++ b/Core/include/Acts/Surfaces/detail/VerticesHelper.hpp @@ -22,51 +22,53 @@ namespace Acts::detail::VerticesHelper { /// A method that inserts the cartesian extrema points and segments /// a curved segment into sub segments /// -/// @param phiMin the minimum Phi of the bounds object -/// @param phiMax the maximum Phi of the bounds object +/// @param phiMin the minimum phi value +/// @param phiMax The second phi value /// @param phiRef is a vector of reference phi values to be included as well -/// @param phiTolerance is the tolerance for reference phi insertion -/// @return a vector +/// @param quarterSegments number of segments used to approximate a segment quarter +/// +/// @return a vector of generated phi values std::vector phiSegments(ActsScalar phiMin = -M_PI, ActsScalar phiMax = M_PI, const std::vector& phiRefs = {}, - ActsScalar phiTolerance = 1e-6); + unsigned int quarterSegments = 2u); /// Helper method to create a regular 2 or 3 D segment -/// between two phi values +/// between two phi values with a given number of segments +/// +/// It will insert the phi at extrema points and reference points, it uses +/// a minimum approximation of a circle with 8 segments /// /// @tparam vertex_t Type of vertex to be applied /// @tparam transform_t Optional transform /// -/// @param vertices [in,out] The 3D vertices to be filled -/// @param rxy The radius description if first +/= second: ellipse -/// @param phi1 The first phi value -/// @param phi2 The second phi value -/// @param lseg The number of segments for full 2*PI -/// @param addon The additional segments to be built +/// @param rXY The radius description if first +/= second: ellipse +/// @param phiMin the minimum phi value +/// @param phiMax the second phi value +/// @param phiRef is a vector of reference phi values to be included as well +/// @param quarterSegments number of segments used to approximate a segment quarter /// @param offset The out of plane offset position of the bow /// @param transform The transform applied (optional) +/// +/// @return a vector of vertices template -void createSegment(std::vector& vertices, - std::pair rxy, ActsScalar phi1, - ActsScalar phi2, unsigned int lseg, int addon = 0, - const vertex_t& offset = vertex_t::Zero(), - const transform_t& transform = transform_t::Identity()) { - // Calculate the number of segments - 1 is the minimum - unsigned int segs = - static_cast(std::abs(phi2 - phi1) / (2 * M_PI) * lseg); - segs = segs > 0 ? segs : 1; - ActsScalar phistep = (phi2 - phi1) / segs; - // Create the segments - for (unsigned int iphi = 0; iphi < segs + addon; ++iphi) { - ActsScalar phi = phi1 + iphi * phistep; +std::vector segmentVertices( + std::pair rXY, ActsScalar phiMin, ActsScalar phiMax, + const std::vector& phiRefs = {}, + unsigned int quarterSegments = 2u, + const vertex_t& offset = vertex_t::Zero(), + const transform_t& transform = transform_t::Identity()) { + std::vector vertices; + std::vector phis = + phiSegments(phiMin, phiMax, phiRefs, quarterSegments); + for (ActsScalar phi : phis) { vertex_t vertex = vertex_t::Zero(); - vertex(0) = rxy.first * std::cos(phi); - vertex(1) = rxy.second * std::sin(phi); - + vertex(0) = rXY.first * std::cos(phi); + vertex(1) = rXY.second * std::sin(phi); vertex = vertex + offset; vertices.push_back(transform * vertex); } + return vertices; } /// Construct vertices on an ellipse-like bound object. @@ -76,14 +78,15 @@ void createSegment(std::vector& vertices, /// @param outerRx The radius of the outer ellipse (in x) /// @param outerRy The radius of the outer ellipse (in y) /// @param avgPhi The phi direction of the center if sector -/// @param halfPhi The half phi sector if sector -/// @param lseg The number of segments for for a full 2*pi segment +/// @param halfPhi The half phi sector of the ellipse +/// @param quarterSegments number of segments used to approximate a segment quarter +/// /// @return a vector of 2d-vectors std::vector ellipsoidVertices(ActsScalar innerRx, ActsScalar innerRy, ActsScalar outerRx, ActsScalar outerRy, ActsScalar avgPhi = 0., ActsScalar halfPhi = M_PI, - unsigned int lseg = 1); + unsigned int quarterSegments = 2u); /// Construct vertices on an disc/wheel-like bound object. /// @@ -91,12 +94,14 @@ std::vector ellipsoidVertices(ActsScalar innerRx, ActsScalar innerRy, /// @param outerR The radius of the outer circle (sector) /// @param avgPhi The phi direction of the center if sector /// @param halfPhi The half phi sector if sector -/// @param lseg The number of segments for for a full 2*pi segment +/// @param quarterSegments number of segments used to approximate a segment quarter +/// /// @return a vector of 2d-vectors std::vector circularVertices(ActsScalar innerR, ActsScalar outerR, ActsScalar avgPhi = 0., ActsScalar halfPhi = M_PI, - unsigned int lseg = 1); + unsigned int quarterSegments = 2u); + /// Check if the point is inside the polygon w/o any tolerances. /// /// @tparam vertex_container_t is an iterable container diff --git a/Core/include/Acts/Visualization/ViewConfig.hpp b/Core/include/Acts/Visualization/ViewConfig.hpp index 6fcf1b47984..0414fa58aba 100644 --- a/Core/include/Acts/Visualization/ViewConfig.hpp +++ b/Core/include/Acts/Visualization/ViewConfig.hpp @@ -112,8 +112,8 @@ struct ViewConfig { double lineThickness = 0.15; /// The visual surface thickness for this object double surfaceThickness = 0.15; - /// The number of segments to approximate full 2pi - unsigned int nSegments = 72; + /// The number of segments to approximate a quarter of the circle + unsigned int quarterSegments = 72; /// Whether to triangulate or not bool triangulate = false; /// Write name - non-empty string indicates writing diff --git a/Core/include/Acts/Visualization/detail/ObjVisualization3D.ipp b/Core/include/Acts/Visualization/detail/ObjVisualization3D.ipp index 2419ef8c546..354ef518bef 100644 --- a/Core/include/Acts/Visualization/detail/ObjVisualization3D.ipp +++ b/Core/include/Acts/Visualization/detail/ObjVisualization3D.ipp @@ -160,8 +160,8 @@ void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { } } os << "f"; - for (std::size_t i = 0; i < fc.size(); i++) { - os << " " << fc[i] + 1; + for (auto fi : fc) { + os << " " << fi + 1; } os << "\n"; ++is; diff --git a/Core/src/Detector/LayerStructureBuilder.cpp b/Core/src/Detector/LayerStructureBuilder.cpp index d936b27398a..94766a80d0d 100644 --- a/Core/src/Detector/LayerStructureBuilder.cpp +++ b/Core/src/Detector/LayerStructureBuilder.cpp @@ -256,7 +256,8 @@ Acts::Experimental::LayerStructureBuilder::construct( if (!support.internalConstraints.empty()) { // Estimate the extent from the surfaces for (const auto& s : internalSurfaces) { - auto sPolyhedron = s->polyhedronRepresentation(gctx, m_cfg.nSegments); + auto sPolyhedron = + s->polyhedronRepresentation(gctx, m_cfg.quarterSegments); supportExtent.extend(sPolyhedron.extent(), support.internalConstraints); } diff --git a/Core/src/Surfaces/AnnulusBounds.cpp b/Core/src/Surfaces/AnnulusBounds.cpp index d96b3bc7e80..34c7b5c468b 100644 --- a/Core/src/Surfaces/AnnulusBounds.cpp +++ b/Core/src/Surfaces/AnnulusBounds.cpp @@ -103,33 +103,30 @@ std::vector Acts::AnnulusBounds::corners() const { } std::vector Acts::AnnulusBounds::vertices( - unsigned int lseg) const { - if (lseg > 0) { - // List of vertices counter-clockwise starting with left inner - std::vector rvertices; - + unsigned int quarterSegments) const { + if (quarterSegments > 0u) { using VectorHelpers::phi; - auto phisInner = detail::VerticesHelper::phiSegments( - phi(m_inRightStripXY - m_moduleOrigin), - phi(m_inLeftStripXY - m_moduleOrigin)); - auto phisOuter = detail::VerticesHelper::phiSegments( - phi(m_outLeftStripXY - m_moduleOrigin), - phi(m_outRightStripXY - m_moduleOrigin)); - - // Inner bow from phi_min -> phi_max - for (unsigned int iseg = 0; iseg < phisInner.size() - 1; ++iseg) { - int addon = (iseg == phisInner.size() - 2) ? 1 : 0; - detail::VerticesHelper::createSegment( - rvertices, {get(eMinR), get(eMinR)}, phisInner[iseg], - phisInner[iseg + 1], lseg, addon); - } - // Upper bow from phi_max -> phi_min - for (unsigned int iseg = 0; iseg < phisOuter.size() - 1; ++iseg) { - int addon = (iseg == phisOuter.size() - 2) ? 1 : 0; - detail::VerticesHelper::createSegment( - rvertices, {get(eMaxR), get(eMaxR)}, phisOuter[iseg], - phisOuter[iseg + 1], lseg, addon); - } + + ActsScalar phiMinInner = phi(m_inRightStripXY - m_moduleOrigin); + ActsScalar phiMaxInner = phi(m_inLeftStripXY - m_moduleOrigin); + + ActsScalar phiMinOuter = phi(m_outRightStripXY - m_moduleOrigin); + ActsScalar phiMaxOuter = phi(m_outLeftStripXY - m_moduleOrigin); + + // Inner bow from phi_min -> phi_max (needs to be reversed) + std::vector rvertices = + detail::VerticesHelper::segmentVertices( + {get(eMinR), get(eMinR)}, phiMinInner, phiMaxInner, {}, + quarterSegments); + std::reverse(rvertices.begin(), rvertices.end()); + + // Outer bow from phi_min -> phi_max + auto overtices = + detail::VerticesHelper::segmentVertices( + {get(eMaxR), get(eMaxR)}, phiMinOuter, phiMaxOuter, {}, + quarterSegments); + rvertices.insert(rvertices.end(), overtices.begin(), overtices.end()); + std::for_each(rvertices.begin(), rvertices.end(), [&](Acts::Vector2& rv) { rv += m_moduleOrigin; }); return rvertices; diff --git a/Core/src/Surfaces/CMakeLists.txt b/Core/src/Surfaces/CMakeLists.txt index 2f704f595c6..07cc26cbfcf 100644 --- a/Core/src/Surfaces/CMakeLists.txt +++ b/Core/src/Surfaces/CMakeLists.txt @@ -24,7 +24,7 @@ target_sources( SurfaceArray.cpp SurfaceError.cpp TrapezoidBounds.cpp - VerticesHelper.cpp + detail/VerticesHelper.cpp RegularSurface.cpp CurvilinearSurface.cpp detail/AlignmentHelper.cpp diff --git a/Core/src/Surfaces/ConeSurface.cpp b/Core/src/Surfaces/ConeSurface.cpp index 98f1484609d..ce10c59815f 100644 --- a/Core/src/Surfaces/ConeSurface.cpp +++ b/Core/src/Surfaces/ConeSurface.cpp @@ -183,19 +183,18 @@ const Acts::ConeBounds& Acts::ConeSurface::bounds() const { } Acts::Polyhedron Acts::ConeSurface::polyhedronRepresentation( - const GeometryContext& gctx, std::size_t lseg) const { + const GeometryContext& gctx, unsigned int quarterSegments) const { // Prepare vertices and faces std::vector vertices; std::vector faces; std::vector triangularMesh; - - double minZ = bounds().get(ConeBounds::eMinZ); - double maxZ = bounds().get(ConeBounds::eMaxZ); + ActsScalar minZ = bounds().get(ConeBounds::eMinZ); + ActsScalar maxZ = bounds().get(ConeBounds::eMaxZ); if (minZ == -std::numeric_limits::infinity() || maxZ == std::numeric_limits::infinity()) { throw std::domain_error( - "Polyhedron repr of boundless surface not possible"); + "Polyhedron representation of boundless surface is not possible"); } auto ctransform = transform(gctx); @@ -208,64 +207,53 @@ Acts::Polyhedron Acts::ConeSurface::polyhedronRepresentation( } // Cone parameters - double hPhiSec = bounds().get(ConeBounds::eHalfPhiSector); - double avgPhi = bounds().get(ConeBounds::eAveragePhi); - bool fullCone = (hPhiSec == M_PI); - - // Get the phi segments from the helper - auto phiSegs = fullCone ? detail::VerticesHelper::phiSegments() - : detail::VerticesHelper::phiSegments( - avgPhi - hPhiSec, avgPhi + hPhiSec, - {static_cast(avgPhi)}); - - // Negative cone if exists - std::vector coneSides; + ActsScalar hPhiSec = bounds().get(ConeBounds::eHalfPhiSector); + ActsScalar avgPhi = bounds().get(ConeBounds::eAveragePhi); + std::vector refPhi = {}; + if (bool fullCone = (hPhiSec == M_PI); !fullCone) { + refPhi = {avgPhi}; + } + + // Add the cone sizes + std::vector coneSides; if (std::abs(minZ) > s_onSurfaceTolerance) { coneSides.push_back(minZ); } if (std::abs(maxZ) > s_onSurfaceTolerance) { coneSides.push_back(maxZ); } + for (auto& z : coneSides) { - // Remember the first vertex std::size_t firstIv = vertices.size(); // Radius and z offset double r = std::abs(z) * bounds().tanAlpha(); Vector3 zoffset(0., 0., z); - for (unsigned int iseg = 0; iseg < phiSegs.size() - 1; ++iseg) { - int addon = (iseg == phiSegs.size() - 2 && !fullCone) ? 1 : 0; - detail::VerticesHelper::createSegment(vertices, {r, r}, phiSegs[iseg], - phiSegs[iseg + 1], lseg, addon, - zoffset, ctransform); - } - // Create the faces + auto svertices = detail::VerticesHelper::segmentVertices( + {r, r}, avgPhi - hPhiSec, avgPhi + hPhiSec, refPhi, quarterSegments, + zoffset, ctransform); + vertices.insert(vertices.end(), svertices.begin(), svertices.end()); + // If the tip exists, the faces need to be triangular if (tipExists) { - for (std::size_t iv = firstIv + 2; iv < vertices.size() + 1; ++iv) { - std::size_t one = 0, two = iv - 1, three = iv - 2; + for (std::size_t iv = firstIv + 1; iv < svertices.size() + firstIv; + ++iv) { + std::size_t one = 0, two = iv, three = iv - 1; if (z < 0.) { std::swap(two, three); } faces.push_back({one, two, three}); } - // Complete cone if necessary - if (fullCone) { - if (z > 0.) { - faces.push_back({0, firstIv, vertices.size() - 1}); - } else { - faces.push_back({0, vertices.size() - 1, firstIv}); - } - } } } + // if no tip exists, connect the two bows if (tipExists) { triangularMesh = faces; } else { - auto facesMesh = - detail::FacesHelper::cylindricalFaceMesh(vertices, fullCone); + auto facesMesh = detail::FacesHelper::cylindricalFaceMesh(vertices); faces = facesMesh.first; triangularMesh = facesMesh.second; } + return Polyhedron(vertices, faces, triangularMesh, false); } diff --git a/Core/src/Surfaces/CylinderBounds.cpp b/Core/src/Surfaces/CylinderBounds.cpp index 76e3e902ea7..e7d5032c993 100644 --- a/Core/src/Surfaces/CylinderBounds.cpp +++ b/Core/src/Surfaces/CylinderBounds.cpp @@ -104,45 +104,40 @@ std::ostream& Acts::CylinderBounds::toStream(std::ostream& sl) const { return sl; } -std::vector Acts::CylinderBounds::createCircles( - const Transform3 ctrans, std::size_t lseg) const { +std::vector Acts::CylinderBounds::circleVertices( + const Transform3 transform, unsigned int quarterSegments) const { std::vector vertices; double avgPhi = get(eAveragePhi); double halfPhi = get(eHalfPhiSector); - bool fullCylinder = coversFullAzimuth(); - - // Get the phi segments from the helper - ensures extra points - auto phiSegs = fullCylinder ? detail::VerticesHelper::phiSegments() - : detail::VerticesHelper::phiSegments( - avgPhi - halfPhi, avgPhi + halfPhi, - {static_cast(avgPhi)}); + std::vector phiRef = {}; + if (bool fullCylinder = coversFullAzimuth(); fullCylinder) { + phiRef = {static_cast(avgPhi)}; + } // Write the two bows/circles on either side std::vector sides = {-1, 1}; for (auto& side : sides) { - for (std::size_t iseg = 0; iseg < phiSegs.size() - 1; ++iseg) { - int addon = (iseg == phiSegs.size() - 2 && !fullCylinder) ? 1 : 0; - /// Helper method to create the segment - detail::VerticesHelper::createSegment( - vertices, {get(eR), get(eR)}, phiSegs[iseg], phiSegs[iseg + 1], lseg, - addon, Vector3(0., 0., side * get(eHalfLengthZ)), ctrans); - } + /// Helper method to create the segment + auto svertices = detail::VerticesHelper::segmentVertices( + {get(eR), get(eR)}, avgPhi - halfPhi, avgPhi + halfPhi, phiRef, + quarterSegments, Vector3(0., 0., side * get(eHalfLengthZ)), transform); + vertices.insert(vertices.end(), svertices.begin(), svertices.end()); } - double bevelMinZ = get(eBevelMinZ); - double bevelMaxZ = get(eBevelMaxZ); + ActsScalar bevelMinZ = get(eBevelMinZ); + ActsScalar bevelMaxZ = get(eBevelMaxZ); // Modify the vertices position if bevel is defined if ((bevelMinZ != 0. || bevelMaxZ != 0.) && vertices.size() % 2 == 0) { auto halfWay = vertices.end() - vertices.size() / 2; - double mult{1}; - auto invCtrans = ctrans.inverse(); - auto func = [&mult, &ctrans, &invCtrans](Vector3& v) { - v = invCtrans * v; + ActsScalar mult{1}; + auto invTransform = transform.inverse(); + auto func = [&mult, &transform, &invTransform](Vector3& v) { + v = invTransform * v; v(2) += v(1) * mult; - v = ctrans * v; + v = transform * v; }; if (bevelMinZ != 0.) { mult = std::tan(-bevelMinZ); diff --git a/Core/src/Surfaces/CylinderSurface.cpp b/Core/src/Surfaces/CylinderSurface.cpp index 29ca1edf150..a39dce4a4fa 100644 --- a/Core/src/Surfaces/CylinderSurface.cpp +++ b/Core/src/Surfaces/CylinderSurface.cpp @@ -188,19 +188,15 @@ const Acts::CylinderBounds& Acts::CylinderSurface::bounds() const { } Acts::Polyhedron Acts::CylinderSurface::polyhedronRepresentation( - const GeometryContext& gctx, std::size_t lseg) const { + const GeometryContext& gctx, unsigned int quarterSegments) const { auto ctrans = transform(gctx); // Prepare vertices and faces - std::vector vertices = bounds().createCircles(ctrans, lseg); - std::vector faces; - std::vector triangularMesh; - - bool fullCylinder = bounds().coversFullAzimuth(); - - auto facesMesh = - detail::FacesHelper::cylindricalFaceMesh(vertices, fullCylinder); - return Polyhedron(vertices, facesMesh.first, facesMesh.second, false); + std::vector vertices = + bounds().circleVertices(ctrans, quarterSegments); + auto [faces, triangularMesh] = + detail::FacesHelper::cylindricalFaceMesh(vertices); + return Polyhedron(vertices, faces, triangularMesh, false); } Acts::Vector3 Acts::CylinderSurface::rotSymmetryAxis( diff --git a/Core/src/Surfaces/DiamondBounds.cpp b/Core/src/Surfaces/DiamondBounds.cpp index b0239eca3f3..7febf8e7f2d 100644 --- a/Core/src/Surfaces/DiamondBounds.cpp +++ b/Core/src/Surfaces/DiamondBounds.cpp @@ -27,7 +27,7 @@ bool Acts::DiamondBounds::inside( } std::vector Acts::DiamondBounds::vertices( - unsigned int /*lseg*/) const { + unsigned int /*ignoredSegments*/) const { // Vertices starting at lower left (min rel. phi) // counter-clockwise double x1 = get(DiamondBounds::eHalfLengthXnegY); diff --git a/Core/src/Surfaces/DiscSurface.cpp b/Core/src/Surfaces/DiscSurface.cpp index c46390ff1c9..aa2f3f7036f 100644 --- a/Core/src/Surfaces/DiscSurface.cpp +++ b/Core/src/Surfaces/DiscSurface.cpp @@ -154,12 +154,9 @@ const Acts::SurfaceBounds& Acts::DiscSurface::bounds() const { } Acts::Polyhedron Acts::DiscSurface::polyhedronRepresentation( - const GeometryContext& gctx, std::size_t lseg) const { + const GeometryContext& gctx, unsigned int quarterSegments) const { // Prepare vertices and faces std::vector vertices; - std::vector faces; - std::vector triangularMesh; - // Understand the disc bool fullDisc = m_bounds->coversFullAzimuth(); bool toCenter = m_bounds->rMin() < s_onSurfaceTolerance; @@ -167,7 +164,7 @@ Acts::Polyhedron Acts::DiscSurface::polyhedronRepresentation( bool exactPolyhedron = (m_bounds->type() == SurfaceBounds::eDiscTrapezoid); bool addCentreFromConvexFace = (m_bounds->type() != SurfaceBounds::eAnnulus); if (m_bounds) { - auto vertices2D = m_bounds->vertices(lseg); + auto vertices2D = m_bounds->vertices(quarterSegments); vertices.reserve(vertices2D.size() + 1); Vector3 wCenter(0., 0., 0); for (const auto& v2D : vertices2D) { @@ -182,22 +179,19 @@ Acts::Polyhedron Acts::DiscSurface::polyhedronRepresentation( if (addCentreFromConvexFace) { vertices.push_back(wCenter); } - auto facesMesh = detail::FacesHelper::convexFaceMesh(vertices, true); - faces = facesMesh.first; - triangularMesh = facesMesh.second; + auto [faces, triangularMesh] = + detail::FacesHelper::convexFaceMesh(vertices, true); + return Polyhedron(vertices, faces, triangularMesh, exactPolyhedron); } else { // Two concentric rings, we use the pure concentric method momentarily, // but that creates too many unneccesarry faces, when only two // are needed to describe the mesh, @todo investigate merging flag - auto facesMesh = detail::FacesHelper::cylindricalFaceMesh(vertices, true); - faces = facesMesh.first; - triangularMesh = facesMesh.second; + auto [faces, triangularMesh] = + detail::FacesHelper::cylindricalFaceMesh(vertices); + return Polyhedron(vertices, faces, triangularMesh, exactPolyhedron); } - } else { - throw std::domain_error( - "Polyhedron repr of boundless surface not possible."); } - return Polyhedron(vertices, faces, triangularMesh, exactPolyhedron); + throw std::domain_error("Polyhedron repr of boundless surface not possible."); } Acts::Vector2 Acts::DiscSurface::localPolarToCartesian( diff --git a/Core/src/Surfaces/DiscTrapezoidBounds.cpp b/Core/src/Surfaces/DiscTrapezoidBounds.cpp index 6cebe5433d5..ed02bac17de 100644 --- a/Core/src/Surfaces/DiscTrapezoidBounds.cpp +++ b/Core/src/Surfaces/DiscTrapezoidBounds.cpp @@ -64,7 +64,7 @@ bool Acts::DiscTrapezoidBounds::inside( } std::vector Acts::DiscTrapezoidBounds::vertices( - unsigned int /*lseg*/) const { + unsigned int /*ignoredSegments*/) const { Vector2 cAxis(std::cos(get(eAveragePhi)), std::sin(get(eAveragePhi))); Vector2 nAxis(cAxis.y(), -cAxis.x()); auto ymin = std::sqrt(get(eMinR) * get(eMinR) - diff --git a/Core/src/Surfaces/EllipseBounds.cpp b/Core/src/Surfaces/EllipseBounds.cpp index d6357eabcc3..485f36736d8 100644 --- a/Core/src/Surfaces/EllipseBounds.cpp +++ b/Core/src/Surfaces/EllipseBounds.cpp @@ -61,10 +61,10 @@ bool Acts::EllipseBounds::inside( } std::vector Acts::EllipseBounds::vertices( - unsigned int lseg) const { + unsigned int quarterSegments) const { return detail::VerticesHelper::ellipsoidVertices( get(eInnerRx), get(eInnerRy), get(eOuterRx), get(eOuterRy), - get(eAveragePhi), get(eHalfPhiSector), lseg); + get(eAveragePhi), get(eHalfPhiSector), quarterSegments); } const Acts::RectangleBounds& Acts::EllipseBounds::boundingBox() const { diff --git a/Core/src/Surfaces/PerigeeSurface.cpp b/Core/src/Surfaces/PerigeeSurface.cpp index 328db94478e..777d061b2b1 100644 --- a/Core/src/Surfaces/PerigeeSurface.cpp +++ b/Core/src/Surfaces/PerigeeSurface.cpp @@ -58,7 +58,7 @@ std::ostream& Acts::PerigeeSurface::toStreamImpl(const GeometryContext& gctx, } Acts::Polyhedron Acts::PerigeeSurface::polyhedronRepresentation( - const GeometryContext& gctx, std::size_t /*lseg*/) const { + const GeometryContext& gctx, unsigned int /*quarterSegments*/) const { // Prepare vertices and faces std::vector vertices; std::vector faces; diff --git a/Core/src/Surfaces/PlaneSurface.cpp b/Core/src/Surfaces/PlaneSurface.cpp index 414f2611eef..b33ef82eb46 100644 --- a/Core/src/Surfaces/PlaneSurface.cpp +++ b/Core/src/Surfaces/PlaneSurface.cpp @@ -88,16 +88,14 @@ const Acts::SurfaceBounds& Acts::PlaneSurface::bounds() const { } Acts::Polyhedron Acts::PlaneSurface::polyhedronRepresentation( - const GeometryContext& gctx, std::size_t lseg) const { + const GeometryContext& gctx, unsigned int quarterSegments) const { // Prepare vertices and faces std::vector vertices; - std::vector faces; - std::vector triangularMesh; bool exactPolyhedron = true; // If you have bounds you can create a polyhedron representation if (m_bounds) { - auto vertices2D = m_bounds->vertices(lseg); + auto vertices2D = m_bounds->vertices(quarterSegments); vertices.reserve(vertices2D.size() + 1); for (const auto& v2D : vertices2D) { vertices.push_back(transform(gctx) * Vector3(v2D.x(), v2D.y(), 0.)); @@ -116,22 +114,20 @@ Acts::Polyhedron Acts::PlaneSurface::polyhedronRepresentation( // @todo same as for Discs: coversFull is not the right criterium // for triangulation if (!isEllipse || !innerExists || !coversFull) { - auto facesMesh = detail::FacesHelper::convexFaceMesh(vertices); - faces = facesMesh.first; - triangularMesh = facesMesh.second; + auto [faces, triangularMesh] = + detail::FacesHelper::convexFaceMesh(vertices); + return Polyhedron(vertices, faces, triangularMesh, exactPolyhedron); } else { // Two concentric rings, we use the pure concentric method momentarily, // but that creates too many unneccesarry faces, when only two // are needed to describe the mesh, @todo investigate merging flag - auto facesMesh = detail::FacesHelper::cylindricalFaceMesh(vertices, true); - faces = facesMesh.first; - triangularMesh = facesMesh.second; + auto [faces, triangularMesh] = + detail::FacesHelper::cylindricalFaceMesh(vertices); + return Polyhedron(vertices, faces, triangularMesh, exactPolyhedron); } - } else { - throw std::domain_error( - "Polyhedron repr of boundless surface not possible."); } - return Polyhedron(vertices, faces, triangularMesh, exactPolyhedron); + throw std::domain_error( + "Polyhedron representation of boundless surface not possible."); } Acts::Vector3 Acts::PlaneSurface::normal(const GeometryContext& gctx, diff --git a/Core/src/Surfaces/StrawSurface.cpp b/Core/src/Surfaces/StrawSurface.cpp index 1ac8f8eb264..2ce1ef74b42 100644 --- a/Core/src/Surfaces/StrawSurface.cpp +++ b/Core/src/Surfaces/StrawSurface.cpp @@ -48,7 +48,7 @@ Acts::StrawSurface& Acts::StrawSurface::operator=(const StrawSurface& other) { } Acts::Polyhedron Acts::StrawSurface::polyhedronRepresentation( - const GeometryContext& gctx, std::size_t lseg) const { + const GeometryContext& gctx, unsigned int quarterSegments) const { // Prepare vertices and faces std::vector vertices; std::vector faces; @@ -56,20 +56,17 @@ Acts::Polyhedron Acts::StrawSurface::polyhedronRepresentation( const Transform3& ctransform = transform(gctx); // Draw the bounds if more than one segment are chosen - if (lseg > 1) { + if (quarterSegments > 0u) { double r = m_bounds->get(LineBounds::eR); - auto phiSegs = detail::VerticesHelper::phiSegments(); // Write the two bows/circles on either side std::vector sides = {-1, 1}; for (auto& side : sides) { - for (std::size_t iseg = 0; iseg < phiSegs.size() - 1; ++iseg) { - int addon = (iseg == phiSegs.size() - 2) ? 1 : 0; - /// Helper method to create the segment - detail::VerticesHelper::createSegment( - vertices, {r, r}, phiSegs[iseg], phiSegs[iseg + 1], lseg, addon, - Vector3(0., 0., side * m_bounds->get(LineBounds::eHalfLengthZ)), - ctransform); - } + /// Helper method to create the segment + auto svertices = detail::VerticesHelper::segmentVertices( + {r, r}, -M_PI, M_PI, {}, quarterSegments, + Vector3(0., 0., side * m_bounds->get(LineBounds::eHalfLengthZ)), + ctransform); + vertices.insert(vertices.end(), svertices.begin(), svertices.end()); } auto facesMesh = detail::FacesHelper::cylindricalFaceMesh(vertices); faces = facesMesh.first; diff --git a/Core/src/Surfaces/Surface.cpp b/Core/src/Surfaces/Surface.cpp index 3ebf11d8e92..cadef176cda 100644 --- a/Core/src/Surfaces/Surface.cpp +++ b/Core/src/Surfaces/Surface.cpp @@ -359,6 +359,7 @@ void Acts::Surface::associateLayer(const Acts::Layer& lay) { void Acts::Surface::visualize(IVisualization3D& helper, const GeometryContext& gctx, const ViewConfig& viewConfig) const { - Polyhedron polyhedron = polyhedronRepresentation(gctx, viewConfig.nSegments); + Polyhedron polyhedron = + polyhedronRepresentation(gctx, viewConfig.quarterSegments); polyhedron.visualize(helper, viewConfig); } diff --git a/Core/src/Surfaces/TrapezoidBounds.cpp b/Core/src/Surfaces/TrapezoidBounds.cpp index 06da2fa0fef..e74285e445e 100644 --- a/Core/src/Surfaces/TrapezoidBounds.cpp +++ b/Core/src/Surfaces/TrapezoidBounds.cpp @@ -96,7 +96,7 @@ bool Acts::TrapezoidBounds::inside( } std::vector Acts::TrapezoidBounds::vertices( - unsigned int /*lseg*/) const { + unsigned int /*ignoredSegments*/) const { const double hlXnY = get(TrapezoidBounds::eHalfLengthXnegY); const double hlXpY = get(TrapezoidBounds::eHalfLengthXposY); const double hlY = get(TrapezoidBounds::eHalfLengthY); diff --git a/Core/src/Surfaces/VerticesHelper.cpp b/Core/src/Surfaces/detail/VerticesHelper.cpp similarity index 55% rename from Core/src/Surfaces/VerticesHelper.cpp rename to Core/src/Surfaces/detail/VerticesHelper.cpp index 448ee97e8da..b8bed1fb50f 100644 --- a/Core/src/Surfaces/VerticesHelper.cpp +++ b/Core/src/Surfaces/detail/VerticesHelper.cpp @@ -14,42 +14,61 @@ std::vector Acts::detail::VerticesHelper::phiSegments( ActsScalar phiMin, ActsScalar phiMax, - const std::vector& phiRefs, ActsScalar phiTolerance) { - // This is to ensure that the extrema are built regardless of number - // of segments - std::vector phiSegments; - std::vector quarters = {-M_PI, -0.5 * M_PI, 0., 0.5 * M_PI, M_PI}; - // It does not cover the full azimuth - if (phiMin != -M_PI || phiMax != M_PI) { - phiSegments.push_back(phiMin); - for (unsigned int iq = 1; iq < 4; ++iq) { - if (phiMin < quarters[iq] && phiMax > quarters[iq]) { - phiSegments.push_back(quarters[iq]); - } + const std::vector& phiRefs, unsigned int quarterSegments) { + // Check that the phi range is valid + if (phiMin > phiMax) { + throw std::invalid_argument( + "VerticesHelper::phiSegments ... Minimum phi must be smaller than " + "maximum phi"); + } + + // First check that no reference phi is outside the range + for (ActsScalar phiRef : phiRefs) { + if (phiRef < phiMin || phiRef > phiMax) { + throw std::invalid_argument( + "VerticesHelper::phiSegments ... Reference phi is outside the range " + "of the segment"); } - phiSegments.push_back(phiMax); - } else { - phiSegments = quarters; } - // Insert the reference phis if - if (!phiRefs.empty()) { - for (const auto& phiRef : phiRefs) { - // Trying to find the right patch - if (std::ranges::none_of(phiSegments, [&](ActsScalar phiSeg) { - return std::abs(phiSeg - phiRef) < phiTolerance; + if (quarterSegments == 0u) { + throw std::invalid_argument( + "VerticesHelper::phiSegments ... Number of segments must be larger " + "than 0."); + } + std::vector phiSegments = {phiMin, phiMax}; + // Minimum approximation for a circle need + // - if the circle is closed the last point is given twice + for (unsigned int i = 0; i < 4 * quarterSegments + 1; ++i) { + ActsScalar phiExt = -M_PI + i * 2 * M_PI / (4 * quarterSegments); + if (phiExt > phiMin && phiExt < phiMax && + std::ranges::none_of(phiSegments, [&phiExt](ActsScalar phi) { + return std::abs(phi - phiExt) < + std::numeric_limits::epsilon(); + })) { + phiSegments.push_back(phiExt); + } + } + // Add the reference phis + for (const auto& phiRef : phiRefs) { + if (phiRef > phiMin && phiRef < phiMax) { + if (std::ranges::none_of(phiSegments, [&phiRef](ActsScalar phi) { + return std::abs(phi - phiRef) < + std::numeric_limits::epsilon(); })) { phiSegments.push_back(phiRef); } } - std::ranges::sort(phiSegments); } + + // Sort the phis + std::ranges::sort(phiSegments); return phiSegments; } std::vector Acts::detail::VerticesHelper::ellipsoidVertices( ActsScalar innerRx, ActsScalar innerRy, ActsScalar outerRx, ActsScalar outerRy, ActsScalar avgPhi, ActsScalar halfPhi, - unsigned int lseg) { + unsigned int quarterSegments) { // List of vertices counter-clockwise starting at smallest phi w.r.t center, // for both inner/outer ring/segment std::vector rvertices; // return vertices @@ -59,22 +78,20 @@ std::vector Acts::detail::VerticesHelper::ellipsoidVertices( bool innerExists = (innerRx > 0. && innerRy > 0.); bool closed = std::abs(halfPhi - M_PI) < s_onSurfaceTolerance; - // Get the phi segments from the helper method - auto phiSegs = detail::VerticesHelper::phiSegments( - avgPhi - halfPhi, avgPhi + halfPhi, {avgPhi}); + std::vector refPhi = {}; + if (avgPhi != 0.) { + refPhi.push_back(avgPhi); + } // The inner (if exists) and outer bow - for (unsigned int iseg = 0; iseg < phiSegs.size() - 1; ++iseg) { - int addon = (iseg == phiSegs.size() - 2 && !closed) ? 1 : 0; - if (innerExists) { - createSegment(ivertices, {innerRx, innerRy}, - phiSegs[iseg], phiSegs[iseg + 1], lseg, - addon); - } - createSegment(overtices, {outerRx, outerRy}, - phiSegs[iseg], phiSegs[iseg + 1], lseg, - addon); + if (innerExists) { + ivertices = segmentVertices( + {innerRx, innerRy}, avgPhi - halfPhi, avgPhi + halfPhi, refPhi, + quarterSegments); } + overtices = segmentVertices( + {outerRx, outerRy}, avgPhi - halfPhi, avgPhi + halfPhi, refPhi, + quarterSegments); // We want to keep the same counter-clockwise orientation for displaying if (!innerExists) { @@ -95,9 +112,9 @@ std::vector Acts::detail::VerticesHelper::ellipsoidVertices( std::vector Acts::detail::VerticesHelper::circularVertices( ActsScalar innerR, ActsScalar outerR, ActsScalar avgPhi, ActsScalar halfPhi, - unsigned int lseg) { + unsigned int quarterSegments) { return ellipsoidVertices(innerR, innerR, outerR, outerR, avgPhi, halfPhi, - lseg); + quarterSegments); } bool Acts::detail::VerticesHelper::onHyperPlane( diff --git a/Core/src/Visualization/EventDataView3D.cpp b/Core/src/Visualization/EventDataView3D.cpp index 63644d0204f..ac3a62a1e79 100644 --- a/Core/src/Visualization/EventDataView3D.cpp +++ b/Core/src/Visualization/EventDataView3D.cpp @@ -27,12 +27,13 @@ void Acts::EventDataView3D::drawCovarianceCartesian( std::vector ellipse = createEllipse( lambda0 * locErrorScale, lambda1 * locErrorScale, theta, - viewConfig.nSegments, viewConfig.offset, lposition, transform); + viewConfig.quarterSegments, viewConfig.offset, lposition, transform); ellipse.push_back(transform * Vector3(lposition.x(), lposition.y(), viewConfig.offset)); - auto faces = detail::FacesHelper::convexFaceMesh(ellipse, true); - Polyhedron ellipseHedron(ellipse, faces.first, faces.second); + auto [faces, triangularMesh] = + detail::FacesHelper::convexFaceMesh(ellipse, true); + Polyhedron ellipseHedron(ellipse, faces, triangularMesh); Acts::GeometryView3D::drawPolyhedron(helper, ellipseHedron, viewConfig); } @@ -56,12 +57,13 @@ void Acts::EventDataView3D::drawCovarianceAngular( std::vector ellipse = createEllipse(angularErrorScale * directionScale * lambda0 * sin(dtheta), angularErrorScale * directionScale * lambda1, theta, - viewConfig.nSegments, 0., {0., 0.}, eplane); + viewConfig.quarterSegments, 0., {0., 0.}, eplane); std::vector coneTop = ellipse; coneTop.push_back(anker); - auto coneTopFaces = detail::FacesHelper::convexFaceMesh(coneTop, true); - Polyhedron coneTopHedron(coneTop, coneTopFaces.first, coneTopFaces.second); + auto [faces, triangularMesh] = + detail::FacesHelper::convexFaceMesh(coneTop, true); + Polyhedron coneTopHedron(coneTop, faces, triangularMesh); GeometryView3D::drawPolyhedron(helper, coneTopHedron, viewConfig); std::vector cone = ellipse; @@ -69,7 +71,8 @@ void Acts::EventDataView3D::drawCovarianceAngular( // Force triangular ViewConfig coneViewConfig = viewConfig; coneViewConfig.triangulate = true; - auto coneFaces = detail::FacesHelper::convexFaceMesh(cone, true); - Polyhedron coneHedron(cone, coneFaces.first, coneFaces.second); + auto [facesCone, triangularMeshCone] = + detail::FacesHelper::convexFaceMesh(cone, true); + Polyhedron coneHedron(cone, facesCone, triangularMeshCone); GeometryView3D::drawPolyhedron(helper, coneHedron, coneViewConfig); } diff --git a/Core/src/Visualization/GeometryView3D.cpp b/Core/src/Visualization/GeometryView3D.cpp index e0a7c52a5a7..17b7b5c7df9 100644 --- a/Core/src/Visualization/GeometryView3D.cpp +++ b/Core/src/Visualization/GeometryView3D.cpp @@ -95,7 +95,6 @@ void Acts::GeometryView3D::drawSurfaceArray( auto phiValues = axes[0]->getBinEdges(); auto zValues = axes[1]->getBinEdges(); ViewConfig gridRadConfig = gridConfig; - gridRadConfig.nSegments = phiValues.size(); // Longitudinal lines for (auto phi : phiValues) { double cphi = std::cos(phi); @@ -120,7 +119,7 @@ void Acts::GeometryView3D::drawSurfaceArray( auto rValues = axes[0]->getBinEdges(); auto phiValues = axes[1]->getBinEdges(); ViewConfig gridRadConfig = gridConfig; - gridRadConfig.nSegments = phiValues.size(); + gridRadConfig.quarterSegments = phiValues.size(); for (auto r : rValues) { CylinderVolumeBounds cvb(r - 0.5 * thickness, r + 0.5 * thickness, 0.5 * thickness); @@ -244,7 +243,7 @@ void Acts::GeometryView3D::drawTrackingVolume( ViewConfig lConfig = layerView; ViewConfig sConfig = sensitiveView; ViewConfig gConfig = gridView; - gConfig.nSegments = 8; + gConfig.quarterSegments = 8; ViewConfig vcConfig = cConfig; std::string vname = tVolume.volumeName(); diff --git a/Examples/Algorithms/Geant4/src/SensitiveSurfaceMapper.cpp b/Examples/Algorithms/Geant4/src/SensitiveSurfaceMapper.cpp index ced44d89e94..2fd1a924d94 100644 --- a/Examples/Algorithms/Geant4/src/SensitiveSurfaceMapper.cpp +++ b/Examples/Algorithms/Geant4/src/SensitiveSurfaceMapper.cpp @@ -331,7 +331,7 @@ bool ActsExamples::SensitiveSurfaceMapper::checkMapping( if (writeMissingSurfacesAsObj) { Acts::ObjVisualization3D visualizer; Acts::ViewConfig vcfg; - vcfg.nSegments = 720; + vcfg.quarterSegments = 720; for (auto srf : missing) { Acts::GeometryView3D::drawSurface(visualizer, *srf, gctx, Acts::Transform3::Identity(), vcfg); diff --git a/Examples/Io/Svg/include/ActsExamples/Io/Svg/SvgDefaults.hpp b/Examples/Io/Svg/include/ActsExamples/Io/Svg/SvgDefaults.hpp index 14d0474776e..b4e6c4f8178 100644 --- a/Examples/Io/Svg/include/ActsExamples/Io/Svg/SvgDefaults.hpp +++ b/Examples/Io/Svg/include/ActsExamples/Io/Svg/SvgDefaults.hpp @@ -22,7 +22,7 @@ static inline Acts::Svg::Style layerStyle() { lStyle.highlights = {"mouseover", "mouseout"}; lStyle.strokeColor = {25, 25, 25}; lStyle.strokeWidth = 0.5; - lStyle.nSegments = 72u; + lStyle.quarterSegments = 72u; return lStyle; } @@ -43,7 +43,7 @@ static inline Acts::Svg::Style backgroundStyle() { bgStyle.highlights = {}; bgStyle.strokeColor = {25, 25, 25}; bgStyle.strokeWidth = 0.5; - bgStyle.nSegments = 72u; + bgStyle.quarterSegments = 72u; return bgStyle; } @@ -55,7 +55,7 @@ static inline Acts::Svg::Style pointStyle() { pStyle.highlights = {"mouseover", "mouseout"}; pStyle.strokeColor = {0, 0, 0}; pStyle.strokeWidth = 0.5; - pStyle.nSegments = 72u; + pStyle.quarterSegments = 72u; return pStyle; } diff --git a/Examples/Python/src/Geometry.cpp b/Examples/Python/src/Geometry.cpp index 4fb0f07d07a..51188ee93e4 100644 --- a/Examples/Python/src/Geometry.cpp +++ b/Examples/Python/src/Geometry.cpp @@ -333,7 +333,7 @@ void addExperimentalGeometry(Context& ctx) { ACTS_PYTHON_MEMBER(surfacesProvider); ACTS_PYTHON_MEMBER(supports); ACTS_PYTHON_MEMBER(binnings); - ACTS_PYTHON_MEMBER(nSegments); + ACTS_PYTHON_MEMBER(quarterSegments); ACTS_PYTHON_MEMBER(auxiliary); ACTS_PYTHON_STRUCT_END(); diff --git a/Examples/Python/src/Obj.cpp b/Examples/Python/src/Obj.cpp index ce03e60a3fe..5ca2df40033 100644 --- a/Examples/Python/src/Obj.cpp +++ b/Examples/Python/src/Obj.cpp @@ -35,7 +35,7 @@ void addObj(Context& ctx) { /// @param surfaces is the collection of surfaces /// @param viewContext is the geometry context /// @param viewRgb is the color of the surfaces - /// @param viewSegements is the number of segments to approximate a full circle + /// @param viewSegments is the number of segments to approximate a quarter of a circle /// @param fileName is the path to the output file /// mex.def("writeSurfacesObj", diff --git a/Examples/Python/src/Output.cpp b/Examples/Python/src/Output.cpp index 328ae9ecd92..b53ba905700 100644 --- a/Examples/Python/src/Output.cpp +++ b/Examples/Python/src/Output.cpp @@ -119,7 +119,7 @@ void addOutput(Context& ctx) { ACTS_PYTHON_MEMBER(offset); ACTS_PYTHON_MEMBER(lineThickness); ACTS_PYTHON_MEMBER(surfaceThickness); - ACTS_PYTHON_MEMBER(nSegments); + ACTS_PYTHON_MEMBER(quarterSegments); ACTS_PYTHON_MEMBER(triangulate); ACTS_PYTHON_MEMBER(outputName); ACTS_PYTHON_STRUCT_END(); diff --git a/Examples/Python/src/Svg.cpp b/Examples/Python/src/Svg.cpp index 2c0219d0466..f1d46cadcd8 100644 --- a/Examples/Python/src/Svg.cpp +++ b/Examples/Python/src/Svg.cpp @@ -225,7 +225,7 @@ void addSvg(Context& ctx) { ACTS_PYTHON_MEMBER(highlights); ACTS_PYTHON_MEMBER(strokeWidth); ACTS_PYTHON_MEMBER(strokeColor); - ACTS_PYTHON_MEMBER(nSegments); + ACTS_PYTHON_MEMBER(quarterSegments); ACTS_PYTHON_STRUCT_END(); } diff --git a/Plugins/ActSVG/include/Acts/Plugins/ActSVG/SvgUtils.hpp b/Plugins/ActSVG/include/Acts/Plugins/ActSVG/SvgUtils.hpp index a6faa5ed42c..0b36d7f82c9 100644 --- a/Plugins/ActSVG/include/Acts/Plugins/ActSVG/SvgUtils.hpp +++ b/Plugins/ActSVG/include/Acts/Plugins/ActSVG/SvgUtils.hpp @@ -19,6 +19,7 @@ namespace Acts::Svg { +/// @brief Style struct struct Style { // Fill parameters std::array fillColor = {255, 255, 255}; @@ -38,7 +39,8 @@ struct Style { unsigned int fontSize = 14u; - unsigned int nSegments = 72u; + /// Number of segments to approximate a quarter of a circle + unsigned int quarterSegments = 72u; /// Conversion to fill and stroke object from the base library /// @return a tuple of actsvg digestable objects diff --git a/Plugins/ActSVG/src/SurfaceSvgConverter.cpp b/Plugins/ActSVG/src/SurfaceSvgConverter.cpp index c5bf2bba429..d9fb864a1f4 100644 --- a/Plugins/ActSVG/src/SurfaceSvgConverter.cpp +++ b/Plugins/ActSVG/src/SurfaceSvgConverter.cpp @@ -21,7 +21,7 @@ Acts::Svg::ProtoSurface Acts::Svg::SurfaceConverter::convert( if (!cOptions.templateSurface) { // Polyhedron surface for vertices needed anyway Polyhedron surfaceHedron = - surface.polyhedronRepresentation(gctx, cOptions.style.nSegments); + surface.polyhedronRepresentation(gctx, cOptions.style.quarterSegments); auto vertices3D = surfaceHedron.vertices; pSurface._vertices = vertices3D; } else { @@ -30,7 +30,7 @@ Acts::Svg::ProtoSurface Acts::Svg::SurfaceConverter::convert( auto planarBounds = dynamic_cast(&(surface.bounds())); if (planarBounds != nullptr) { - auto vertices2D = planarBounds->vertices(cOptions.style.nSegments); + auto vertices2D = planarBounds->vertices(cOptions.style.quarterSegments); pSurface._vertices.reserve(vertices2D.size()); for (const auto& v2 : vertices2D) { pSurface._vertices.push_back({v2[0], v2[1], 0.}); @@ -40,7 +40,8 @@ Acts::Svg::ProtoSurface Acts::Svg::SurfaceConverter::convert( auto annulusBounds = dynamic_cast(&(surface.bounds())); if (annulusBounds != nullptr) { - auto vertices2D = annulusBounds->vertices(cOptions.style.nSegments); + auto vertices2D = + annulusBounds->vertices(cOptions.style.quarterSegments); pSurface._vertices.reserve(vertices2D.size()); for (const auto& v2 : vertices2D) { pSurface._vertices.push_back({v2[0], v2[1], 0.}); diff --git a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp index 0a283433ab4..d6855443af2 100644 --- a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp +++ b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp @@ -71,8 +71,8 @@ class DD4hepDetectorSurfaceFactory { std::optional pExtent = std::nullopt; /// Optionally provide an Extent constraints to measure the layers std::vector extentConstraints = {}; - /// The approximination for extent measuring - std::size_t nExtentSegments = 1u; + /// The approximination of a circle quarter for extent measuring + std::size_t nExtentQSegments = 1u; }; /// Nested options struct to steer the conversion diff --git a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepLayerStructure.hpp b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepLayerStructure.hpp index bdf4780fb2f..a44e4341feb 100644 --- a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepLayerStructure.hpp +++ b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepLayerStructure.hpp @@ -65,8 +65,8 @@ class DD4hepLayerStructure { std::optional extent = std::nullopt; /// The extent constraints - optionally std::vector extentConstraints = {}; - /// Approximation for the polyhedron binning nSegments - unsigned int nSegments = 1u; + /// Approximation for the polyhedron binning + unsigned int quarterSegments = 1u; /// Patch the binning with the extent if possible bool patchBinningWithExtent = true; /// Conversion options diff --git a/Plugins/DD4hep/src/DD4hepDetectorSurfaceFactory.cpp b/Plugins/DD4hep/src/DD4hepDetectorSurfaceFactory.cpp index f3059fbeed5..d628ff76379 100644 --- a/Plugins/DD4hep/src/DD4hepDetectorSurfaceFactory.cpp +++ b/Plugins/DD4hep/src/DD4hepDetectorSurfaceFactory.cpp @@ -108,7 +108,7 @@ Acts::DD4hepDetectorSurfaceFactory::constructSensitiveComponents( // Measure if configured to do so if (cache.sExtent.has_value()) { auto sExtent = - sSurface->polyhedronRepresentation(gctx, cache.nExtentSegments) + sSurface->polyhedronRepresentation(gctx, cache.nExtentQSegments) .extent(); cache.sExtent.value().extend(sExtent, cache.extentConstraints); } @@ -137,7 +137,7 @@ Acts::DD4hepDetectorSurfaceFactory::constructPassiveComponents( // Measure if configured to do so if (cache.pExtent.has_value()) { auto sExtent = - pSurface->polyhedronRepresentation(gctx, cache.nExtentSegments) + pSurface->polyhedronRepresentation(gctx, cache.nExtentQSegments) .extent(); cache.pExtent.value().extend(sExtent, cache.extentConstraints); } diff --git a/Plugins/DD4hep/src/DD4hepLayerStructure.cpp b/Plugins/DD4hep/src/DD4hepLayerStructure.cpp index 64b6e8cf32e..10a4e6eb9f0 100644 --- a/Plugins/DD4hep/src/DD4hepLayerStructure.cpp +++ b/Plugins/DD4hep/src/DD4hepLayerStructure.cpp @@ -38,7 +38,7 @@ Acts::Experimental::DD4hepLayerStructure::builder( fCache.sExtent = options.extent; fCache.pExtent = options.extent; fCache.extentConstraints = options.extentConstraints; - fCache.nExtentSegments = options.nSegments; + fCache.nExtentQSegments = options.quarterSegments; m_surfaceFactory->construct(fCache, gctx, dd4hepElement, options.conversionOptions); diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelBlueprintCreater.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelBlueprintCreater.hpp index f382a49543a..df895eb0741 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelBlueprintCreater.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelBlueprintCreater.hpp @@ -40,8 +40,8 @@ class GeoModelBlueprintCreater { std::vector> detectorSurfaces = {}; /// The binning values for the KDTree sorting std::vector kdtBinning = {}; - /// Polyhedron approximations - unsigned int nSegments = 1u; + /// Polyhedron approximation: number of segments per circlequarter + unsigned int quarterSegments = 1u; }; /// The cache struct diff --git a/Plugins/GeoModel/src/GeoModelBlueprintCreater.cpp b/Plugins/GeoModel/src/GeoModelBlueprintCreater.cpp index 9d31eeaaffc..93712d5d911 100644 --- a/Plugins/GeoModel/src/GeoModelBlueprintCreater.cpp +++ b/Plugins/GeoModel/src/GeoModelBlueprintCreater.cpp @@ -354,7 +354,7 @@ Acts::GeoModelBlueprintCreater::createInternalStructureBuilder( // Loop over surfaces and create an internal extent for (auto& sf : surfaces) { auto sfExtent = - sf->polyhedronRepresentation(gctx, m_cfg.nSegments).extent(); + sf->polyhedronRepresentation(gctx, m_cfg.quarterSegments).extent(); internalExtent.extend(sfExtent, internalConstraints); } ACTS_VERBOSE("Found " << surfaces.size() << " surfaces in range " diff --git a/Tests/CommonHelpers/Acts/Tests/CommonHelpers/LineSurfaceStub.hpp b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/LineSurfaceStub.hpp index 848e02cab01..662969bc450 100644 --- a/Tests/CommonHelpers/Acts/Tests/CommonHelpers/LineSurfaceStub.hpp +++ b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/LineSurfaceStub.hpp @@ -52,11 +52,11 @@ class LineSurfaceStub : public LineSurface { /// Return a Polyhedron for the surfaces /// /// @param gctx The current geometry context object, e.g. alignment - /// @param lseg is ignored for a perigee @note ignored + /// @param ingoredSegmeent is ignored for the srub /// /// @return A list of vertices and a face/facett description of it Polyhedron polyhedronRepresentation(const GeometryContext& /*gctx*/, - std::size_t /*lseg*/) const final { + unsigned int /*lseg*/) const final { return Polyhedron({}, {}, {}); } }; diff --git a/Tests/UnitTests/Core/Surfaces/AnnulusBoundsTests.cpp b/Tests/UnitTests/Core/Surfaces/AnnulusBoundsTests.cpp index c284d6d4796..9f09fb2c213 100644 --- a/Tests/UnitTests/Core/Surfaces/AnnulusBoundsTests.cpp +++ b/Tests/UnitTests/Core/Surfaces/AnnulusBoundsTests.cpp @@ -23,10 +23,10 @@ namespace Acts::Test { BOOST_AUTO_TEST_SUITE(Surfaces) -double minRadius = 7.2; -double maxRadius = 12.0; -double minPhi = 0.74195; -double maxPhi = 1.33970; +ActsScalar minRadius = 7.2; +ActsScalar maxRadius = 12.0; +ActsScalar minPhi = 0.74195; +ActsScalar maxPhi = 1.33970; Vector2 offset(-2., 2.); @@ -123,6 +123,25 @@ BOOST_AUTO_TEST_CASE(AnnulusBoundsProperties) { BOOST_CHECK_EQUAL(aBounds.get(AnnulusBounds::eMaxPhiRel), maxPhi); } +/// Unit tests for AnnulusBounds vertices +BOOST_AUTO_TEST_CASE(AnnulusBoundsVertices) { + /// Test construction with radii and default sector + AnnulusBounds aBounds(minRadius, maxRadius, minPhi, maxPhi, offset); + + // Retrieve the corners + auto corners = aBounds.corners(); + BOOST_CHECK_EQUAL(corners.size(), 4); + + // Retrieve the vertices + auto vertices = aBounds.vertices(0u); + BOOST_CHECK_EQUAL(vertices.size(), 4); + + // Now generate with more segments + unsigned int nQuarterSegments = 12; + vertices = aBounds.vertices(nQuarterSegments); + BOOST_CHECK_EQUAL(vertices.size(), 14u); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace Acts::Test diff --git a/Tests/UnitTests/Core/Surfaces/ConvexPolygonBoundsTests.cpp b/Tests/UnitTests/Core/Surfaces/ConvexPolygonBoundsTests.cpp index bdb4c2948be..6b6712c230b 100644 --- a/Tests/UnitTests/Core/Surfaces/ConvexPolygonBoundsTests.cpp +++ b/Tests/UnitTests/Core/Surfaces/ConvexPolygonBoundsTests.cpp @@ -101,6 +101,10 @@ BOOST_AUTO_TEST_CASE(ConvexPolygonBoundsRecreation) { std::copy_n(valvector.begin(), poly<4>::eSize, values.begin()); poly<4> recreated(values); BOOST_CHECK_EQUAL(original, recreated); + + // Get the vertices back + auto rvertices = original.vertices(); + BOOST_CHECK_EQUAL(rvertices.size(), 4u); } BOOST_AUTO_TEST_CASE(ConvexPolygonBoundsDynamicTest) { diff --git a/Tests/UnitTests/Core/Surfaces/PolyhedronSurfacesTests.cpp b/Tests/UnitTests/Core/Surfaces/PolyhedronSurfacesTests.cpp index c858f10f6db..184d69e341f 100644 --- a/Tests/UnitTests/Core/Surfaces/PolyhedronSurfacesTests.cpp +++ b/Tests/UnitTests/Core/Surfaces/PolyhedronSurfacesTests.cpp @@ -42,7 +42,7 @@ namespace Acts::Test { const GeometryContext tgContext = GeometryContext(); const std::vector> testModes = { - {"Triangulate", 72}, {"Extrema", 1}}; + {"Triangulate", 18}, {"Extrema", 1}}; const Transform3 transform = Transform3::Identity(); const double epsAbs = 1e-12; @@ -61,9 +61,8 @@ BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) { const double rMax = hzPos * std::tan(alpha); - for (const auto& mode : testModes) { - ACTS_INFO("\tMode: " << std::get(mode)); - const unsigned int segments = std::get(mode); + for (const auto& [mode, segments] : testModes) { + ACTS_INFO("\tMode: " << mode); /// The full cone on one side { @@ -81,9 +80,10 @@ BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) { CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).min(), 0_mm, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).max(), hzPos, epsAbs); - const unsigned int expectedFaces = segments < 4 ? 4 : segments; + const unsigned int expectedFaces = 4 * segments; BOOST_CHECK_EQUAL(oneConePh.faces.size(), expectedFaces); - BOOST_CHECK_EQUAL(oneConePh.vertices.size(), expectedFaces + 1); + // full segments + overlap at (pi/pi) + tip + BOOST_CHECK_EQUAL(oneConePh.vertices.size(), expectedFaces + 2); } /// The full cone on one side @@ -106,6 +106,11 @@ BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) { CHECK_CLOSE_ABS(extent.range(BinningValue::binR).max(), rMax, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).min(), hzpMin, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).max(), hzPos, epsAbs); + + const unsigned int expectedFaces = 4 * segments; + BOOST_CHECK_EQUAL(oneConePiecePh.faces.size(), expectedFaces); + BOOST_CHECK_EQUAL(oneConePiecePh.vertices.size(), + (expectedFaces + 1) * 2); } /// The full cone on both sides @@ -124,9 +129,11 @@ BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) { CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).min(), hzNeg, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).max(), hzPos, epsAbs); - const unsigned int expectedFaces = segments < 4 ? 8 : 2 * segments; + const unsigned int expectedFaces = 2 * segments * 4; + const unsigned int expectedVertices = 2 * (4 * segments + 1) + 1; + BOOST_CHECK_EQUAL(twoConesPh.faces.size(), expectedFaces); - BOOST_CHECK_EQUAL(twoConesPh.vertices.size(), expectedFaces + 1); + BOOST_CHECK_EQUAL(twoConesPh.vertices.size(), expectedVertices); } /// A centered sectoral cone on both sides @@ -143,13 +150,16 @@ BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) { const auto extent = sectoralConesPh.extent(); CHECK_CLOSE_ABS(extent.range(BinningValue::binX).min(), 0, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binX).max(), rMax, epsAbs); - // CHECK_CLOSE_ABS(extent.range(BinningValue::binY).min(), ???, - // epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binY).max(), - // ???, epsAbs); + CHECK_CLOSE_ABS(extent.range(BinningValue::binY).min(), + -rMax * std::sin(phiSector), epsAbs); + CHECK_CLOSE_ABS(extent.range(BinningValue::binY).max(), + rMax * std::sin(phiSector), epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binR).min(), 0_mm, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binR).max(), rMax, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).min(), hzNeg, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).max(), hzPos, epsAbs); + + // Segment numbers are further checked with the VertexHelper checks } } } @@ -185,8 +195,8 @@ BOOST_AUTO_TEST_CASE(CylinderSurfacePolyhedrons) { CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).min(), -hZ, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).max(), hZ, epsAbs); - const unsigned int expectedFaces = segments < 4 ? 4 : segments; - const unsigned int expectedVertices = segments < 4 ? 8 : 2 * segments; + const unsigned int expectedFaces = 4 * segments; + const unsigned int expectedVertices = (4 * segments + 1) * 2; BOOST_CHECK_EQUAL(fullCylinderPh.faces.size(), expectedFaces); BOOST_CHECK_EQUAL(fullCylinderPh.vertices.size(), expectedVertices); } @@ -248,7 +258,8 @@ BOOST_AUTO_TEST_CASE(DiscSurfacePolyhedrons) { CHECK_CLOSE_ABS(extent.range(BinningValue::binZ).max(), 0., epsAbs); const unsigned int expectedFaces = 1; - const unsigned int expectedVertices = segments > 4 ? segments + 1 : 4 + 1; + // Segments + overlap + center + const unsigned int expectedVertices = 4 * segments + 1 + 1; BOOST_CHECK_EQUAL(fullDiscPh.faces.size(), expectedFaces); BOOST_CHECK_EQUAL(fullDiscPh.vertices.size(), expectedVertices); } @@ -353,14 +364,7 @@ BOOST_AUTO_TEST_CASE(DiscSurfacePolyhedrons) { auto annulusDisc = Surface::makeShared(transform, annulus); auto annulusDiscPh = annulusDisc->polyhedronRepresentation(tgContext, segments); - const auto extent = annulusDiscPh.extent(); - // CHECK_CLOSE_ABS(extent.range(BinningValue::binX).min(), ???, - // epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binX).max(), - // ???, epsAbs); - // CHECK_CLOSE_ABS(extent.range(BinningValue::binY).min(), ???, - // epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binY).max(), - // ???, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binR).min(), minRadius, epsAbs); CHECK_CLOSE_ABS(extent.range(BinningValue::binR).max(), maxRadius, diff --git a/Tests/UnitTests/Core/Surfaces/SurfaceStub.hpp b/Tests/UnitTests/Core/Surfaces/SurfaceStub.hpp index 573c9f55ce9..ce745bec85c 100644 --- a/Tests/UnitTests/Core/Surfaces/SurfaceStub.hpp +++ b/Tests/UnitTests/Core/Surfaces/SurfaceStub.hpp @@ -102,7 +102,7 @@ class SurfaceStub : public RegularSurface { /// Return a Polyhedron for the surfaces Polyhedron polyhedronRepresentation(const GeometryContext& /*gctx*/, - std::size_t /*lseg */) const final { + unsigned int /* ignored */) const final { std::vector vertices; std::vector> faces; std::vector> triangularMesh; diff --git a/Tests/UnitTests/Core/Surfaces/VerticesHelperTests.cpp b/Tests/UnitTests/Core/Surfaces/VerticesHelperTests.cpp index d2838760081..2b52064cb8d 100644 --- a/Tests/UnitTests/Core/Surfaces/VerticesHelperTests.cpp +++ b/Tests/UnitTests/Core/Surfaces/VerticesHelperTests.cpp @@ -92,6 +92,127 @@ BOOST_AUTO_TEST_CASE(VerticesHelperOnHyperPlane) { } } +BOOST_AUTO_TEST_CASE(GeneratePhiSegments) { + // Case (1): a small segment is given, no cartesian maximum vertex + ActsScalar minPhi = 0.1; + ActsScalar maxPhi = 0.3; + + auto phis = VerticesHelper::phiSegments(minPhi, maxPhi); + BOOST_CHECK_EQUAL(phis.size(), 2u); + BOOST_CHECK(phis[0] == minPhi); + BOOST_CHECK(phis[1] == maxPhi); + + // Case (2) a small segment is given, with one maximum vertex at phi = 0 + minPhi = -0.1; + phis = VerticesHelper::phiSegments(minPhi, maxPhi); + BOOST_CHECK_EQUAL(phis.size(), 3u); + BOOST_CHECK(phis[0] == minPhi); + BOOST_CHECK(phis[1] == 0.); + BOOST_CHECK(phis[2] == maxPhi); + + // Case (3) a small segment is given, with one maximum vertex at phi = 2pi, + // and one extra value + phis = VerticesHelper::phiSegments(minPhi, maxPhi, {0.25}); + BOOST_CHECK_EQUAL(phis.size(), 4u); + BOOST_CHECK(phis[0] == minPhi); + BOOST_CHECK(phis[1] == 0.); + BOOST_CHECK(phis[2] == 0.25); + BOOST_CHECK(phis[3] == maxPhi); + + // Case (4) a small segment is given, with one maximum vertex at phi = 2pi, + // and two extra values, one outside & hence throw an exception + BOOST_CHECK_THROW(VerticesHelper::phiSegments(minPhi, maxPhi, {0.25, 0.5}), + std::invalid_argument); + + // Case (5) an invalid phi range is given + BOOST_CHECK_THROW(VerticesHelper::phiSegments(0.8, 0.2, {0.25, 0.5}), + std::invalid_argument); + + // Case (6) a wrong number of minimum segments is given + BOOST_CHECK_THROW(VerticesHelper::phiSegments(0.1, 0.3, {0.25, 0.5}, 3), + std::invalid_argument); +} + +BOOST_AUTO_TEST_CASE(GenerateSegmentVertices) { + // Case (1): a small segment is given, no cartesian maximum vertex & 1 step + // segment + ActsScalar rx = 10.; + ActsScalar ry = 10.; + ActsScalar minPhi = 0.1; + ActsScalar maxPhi = 0.3; + + auto vertices = VerticesHelper::segmentVertices( + {rx, ry}, minPhi, maxPhi, {}, 1); + std::size_t expectedVertices = 2u; + BOOST_CHECK_EQUAL(vertices.size(), expectedVertices); + + // Now with a reference phi value + vertices = VerticesHelper::segmentVertices( + {rx, ry}, minPhi, maxPhi, {0.2}, 1); + expectedVertices = 3u; // the reference is inserted + BOOST_CHECK_EQUAL(vertices.size(), expectedVertices); + + // Now with more vertices - the the two corners and the ones from the + // reference + unsigned int quarterVertices = 36; + vertices = VerticesHelper::segmentVertices( + {rx, ry}, minPhi, maxPhi, {}, quarterVertices); + expectedVertices = + static_cast((maxPhi - minPhi) / M_PI_2 * quarterVertices) + + 2u; + BOOST_CHECK_EQUAL(vertices.size(), expectedVertices); + + // Case (2) a small segment is given, with one maximum vertex at phi = 0 + minPhi = -0.1; + vertices = VerticesHelper::segmentVertices( + {rx, ry}, minPhi, maxPhi, {}, 1); + expectedVertices = 3u; + BOOST_CHECK_EQUAL(vertices.size(), expectedVertices); + + // Same with more segments + quarterVertices = 12; + vertices = VerticesHelper::segmentVertices( + {rx, ry}, minPhi, maxPhi, {}, quarterVertices); + // Extrema will be covered by the segments + expectedVertices = + static_cast((maxPhi - minPhi) / M_PI_2 * quarterVertices) + + 2u; + BOOST_CHECK_EQUAL(vertices.size(), expectedVertices); +} + +BOOST_AUTO_TEST_CASE(GenerateCircleEllipseVertices) { + // Case (1): A full disc + ActsScalar ri = 0.; + ActsScalar ro = 10.; + + // Extreme points in phi - only outer radius + auto vertices = VerticesHelper::circularVertices(ri, ro, 0., M_PI, 1u); + unsigned int expectedVertices = 5u; + BOOST_CHECK_EQUAL(vertices.size(), expectedVertices); + + // Case (2): A ring + ri = 3.; + + // Extreme points in phi - only outer radius + vertices = VerticesHelper::circularVertices(ri, ro, 0., M_PI, 1u); + expectedVertices = 10u; + BOOST_CHECK_EQUAL(vertices.size(), expectedVertices); + + // Now with 10 bins per sector + ri = 0.; + + vertices = VerticesHelper::circularVertices(ri, ro, 0., M_PI, 10u); + expectedVertices = 41u; // 4 sectors + 1 overlap at (-pi/pi) + BOOST_CHECK_EQUAL(vertices.size(), expectedVertices); + + // Now ellipsiod + ActsScalar riy = 4.; + ActsScalar roy = 14.; + vertices = VerticesHelper::ellipsoidVertices(ri, riy, ro, roy, 0., M_PI, 10u); + expectedVertices = 41u; // 4 sectors + 1 overlap at (-pi/pi) + BOOST_CHECK_EQUAL(vertices.size(), expectedVertices); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace Acts::detail::Test diff --git a/Tests/UnitTests/Core/TrackFitting/Gx2fTests.cpp b/Tests/UnitTests/Core/TrackFitting/Gx2fTests.cpp index 7ef5373f41b..bce69cba0b2 100644 --- a/Tests/UnitTests/Core/TrackFitting/Gx2fTests.cpp +++ b/Tests/UnitTests/Core/TrackFitting/Gx2fTests.cpp @@ -1054,7 +1054,7 @@ BOOST_AUTO_TEST_CASE(Material) { ViewConfig viewContainer = {.color = {220, 220, 0}}; viewContainer.triangulate = triangulate; ViewConfig viewGrid = {.color = {220, 0, 0}}; - viewGrid.nSegments = 8; + viewGrid.quarterSegments = 8; viewGrid.offset = 3.; viewGrid.triangulate = triangulate; diff --git a/Tests/UnitTests/Core/Visualization/EventDataView3DTests.cpp b/Tests/UnitTests/Core/Visualization/EventDataView3DTests.cpp index 36f823a02b6..bac538e4b58 100644 --- a/Tests/UnitTests/Core/Visualization/EventDataView3DTests.cpp +++ b/Tests/UnitTests/Core/Visualization/EventDataView3DTests.cpp @@ -29,7 +29,7 @@ BOOST_AUTO_TEST_CASE(BoundTrackParametersVisualizationObj) { for (const auto& objerr : objErrors) { std::cout << objerr << std::endl; } - BOOST_CHECK_EQUAL(std::count(objTest.begin(), objTest.end(), '\n'), 1458); + BOOST_CHECK_EQUAL(std::count(objTest.begin(), objTest.end(), '\n'), 4924); } BOOST_AUTO_TEST_CASE(BoundTrackParametersVisualizationPly) { @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE(BoundTrackParametersVisualizationPly) { for (const auto& plyerr : plyErrors) { std::cout << plyerr << std::endl; } - BOOST_CHECK_EQUAL(std::count(plyTest.begin(), plyTest.end(), '\n'), 973); + BOOST_CHECK_EQUAL(std::count(plyTest.begin(), plyTest.end(), '\n'), 3143); } BOOST_AUTO_TEST_CASE(MeasurementVisualizationObj) { @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE(MultiTrajectoryVisualizationObj) { for (const auto& objerr : objErrors) { std::cout << objerr << std::endl; } - BOOST_CHECK_EQUAL(std::count(objTest.begin(), objTest.end(), '\n'), 31010); + BOOST_CHECK_EQUAL(std::count(objTest.begin(), objTest.end(), '\n'), 103796); } BOOST_AUTO_TEST_CASE(MultiTrajectoryVisualizationPly) { @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(MultiTrajectoryVisualizationPly) { for (const auto& plyerr : plyErrors) { std::cout << plyerr << std::endl; } - BOOST_CHECK_EQUAL(std::count(plyTest.begin(), plyTest.end(), '\n'), 20521); + BOOST_CHECK_EQUAL(std::count(plyTest.begin(), plyTest.end(), '\n'), 66091); } BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Core/Visualization/SurfaceView3DBase.hpp b/Tests/UnitTests/Core/Visualization/SurfaceView3DBase.hpp index be83a27cb7b..146935279f0 100644 --- a/Tests/UnitTests/Core/Visualization/SurfaceView3DBase.hpp +++ b/Tests/UnitTests/Core/Visualization/SurfaceView3DBase.hpp @@ -68,7 +68,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, coneSurfaces.push_back(cone); GeometryView3D::drawSurface(helper, *cone, gctx, Transform3::Identity(), sConfig); - ; + helper.write(std::string("Surfaces_ConeSurface") + tag); helper.write(cStream); helper.clear(); @@ -80,7 +80,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, coneSurfaces.push_back(cone); GeometryView3D::drawSurface(helper, *cone, gctx, Transform3::Identity(), sConfig); - ; + helper.write(std::string("Surfaces_ConeSurfaceSector") + tag); helper.write(cStream); helper.clear(); @@ -92,7 +92,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, coneSurfaces.push_back(cone); GeometryView3D::drawSurface(helper, *cone, gctx, Transform3::Identity(), sConfig); - ; + helper.write(std::string("Surfaces_ConeSurfaceSectorShifted") + tag); helper.write(cStream); helper.clear(); @@ -126,7 +126,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, cylinderSurfaces.push_back(cylinder); GeometryView3D::drawSurface(helper, *cylinder, gctx, Transform3::Identity(), sConfig); - ; + helper.write(std::string("Surfaces_CylinderSurface") + tag); helper.write(cStream); helper.clear(); @@ -138,7 +138,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, cylinderSurfaces.push_back(cylinder); GeometryView3D::drawSurface(helper, *cylinder, gctx, Transform3::Identity(), sConfig); - ; + helper.write(std::string("Surfaces_CylinderSurfaceSector") + tag); helper.write(cStream); helper.clear(); @@ -150,7 +150,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, cylinderSurfaces.push_back(cylinder); GeometryView3D::drawSurface(helper, *cylinder, gctx, Transform3::Identity(), sConfig); - ; + helper.write(std::string("Surfaces_CylinderSurfaceSectorShifted") + tag); helper.write(cStream); helper.clear(); @@ -179,7 +179,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, auto bbSurface = Surface::makeShared(identity, bbBounds); GeometryView3D::drawSurface(helper, *bbSurface, gctx, Transform3::Identity(), sConfig); - ; + helper.write(bbPath); helper.write(cStream); helper.clear(); @@ -199,7 +199,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, radialSurfaces.push_back(disc); GeometryView3D::drawSurface(helper, *disc, gctx, Transform3::Identity(), sConfig); - ; + helper.write(std::string("Surfaces_DiscSurfaceFull") + tag); helper.write(cStream); helper.clear(); @@ -335,7 +335,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, planarSurfaces.push_back(plane); GeometryView3D::drawSurface(helper, *plane, gctx, Transform3::Identity(), sConfig); - ; + helper.write(name + tag); helper.write(cStream); helper.clear(); @@ -349,7 +349,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, planarSurfaces.push_back(plane); GeometryView3D::drawSurface(helper, *plane, gctx, Transform3::Identity(), sConfig); - ; + helper.write(name + tag); helper.write(cStream); helper.clear(); @@ -363,7 +363,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, planarSurfaces.push_back(plane); GeometryView3D::drawSurface(helper, *plane, gctx, Transform3::Identity(), sConfig); - ; + helper.write(name + tag); helper.write(cStream); helper.clear(); @@ -377,7 +377,7 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, planarSurfaces.push_back(plane); GeometryView3D::drawSurface(helper, *plane, gctx, Transform3::Identity(), sConfig); - ; + helper.write(name + tag); helper.write(cStream); helper.clear(); diff --git a/Tests/UnitTests/Core/Visualization/TrackingGeometryView3DBase.hpp b/Tests/UnitTests/Core/Visualization/TrackingGeometryView3DBase.hpp index b2fb89c0ee8..ea2e409222d 100644 --- a/Tests/UnitTests/Core/Visualization/TrackingGeometryView3DBase.hpp +++ b/Tests/UnitTests/Core/Visualization/TrackingGeometryView3DBase.hpp @@ -37,18 +37,22 @@ static inline std::string run(IVisualization3D& helper, bool triangulate, const std::string& tag) { std::stringstream cStream; - ViewConfig viewSensitive = {.color = {0, 180, 240}}; - viewSensitive.triangulate = triangulate; - ViewConfig viewPassive = {.color = {240, 280, 0}}; - viewPassive.triangulate = triangulate; - ViewConfig viewVolume = {.color = {220, 220, 0}}; - viewVolume.triangulate = triangulate; - ViewConfig viewContainer = {.color = {220, 220, 0}}; - viewContainer.triangulate = triangulate; - ViewConfig viewGrid = {.color = {220, 0, 0}}; - viewGrid.nSegments = 8; - viewGrid.offset = 3.; - viewGrid.triangulate = triangulate; + ViewConfig viewSensitive = {.color = {0, 180, 240}, + .quarterSegments = 72, + .triangulate = triangulate}; + ViewConfig viewPassive = {.color = {240, 280, 0}, + .quarterSegments = 72, + .triangulate = triangulate}; + ViewConfig viewVolume = {.color = {220, 220, 0}, + .quarterSegments = 72, + .triangulate = triangulate}; + ViewConfig viewContainer = {.color = {220, 220, 0}, + .quarterSegments = 72, + .triangulate = triangulate}; + ViewConfig viewGrid = {.color = {220, 0, 0}, + .offset = 3., + .quarterSegments = 8, + .triangulate = triangulate}; const Acts::TrackingVolume& tgVolume = *(tGeometry->highestTrackingVolume()); diff --git a/Tests/UnitTests/Fatras/Digitization/SegmentizerTests.cpp b/Tests/UnitTests/Fatras/Digitization/SegmentizerTests.cpp index 844122027d2..ad74a9024d1 100644 --- a/Tests/UnitTests/Fatras/Digitization/SegmentizerTests.cpp +++ b/Tests/UnitTests/Fatras/Digitization/SegmentizerTests.cpp @@ -217,9 +217,9 @@ BOOST_DATA_TEST_CASE( ".csv"); /// Run the Segmentizer - auto cSegement = cl.segments(geoCtx, *surface, segmentation, {start, end}); + auto cSegments = cl.segments(geoCtx, *surface, segmentation, {start, end}); - for (const auto& cs : cSegement) { + for (const auto& cs : cSegments) { csvHelper.writeLine(segments, cs.path2D[0], cs.path2D[1]); } diff --git a/Tests/UnitTests/Plugins/ActSVG/IndexedSurfacesSvgConverterTests.cpp b/Tests/UnitTests/Plugins/ActSVG/IndexedSurfacesSvgConverterTests.cpp index bc33298431a..6f2c78620e9 100644 --- a/Tests/UnitTests/Plugins/ActSVG/IndexedSurfacesSvgConverterTests.cpp +++ b/Tests/UnitTests/Plugins/ActSVG/IndexedSurfacesSvgConverterTests.cpp @@ -42,7 +42,7 @@ IndexedSurfacesConverter::Options generateDrawOptions() { sensitiveStyle.highlights = {"onmouseover", "onmouseout"}; sensitiveStyle.strokeWidth = 0.5; sensitiveStyle.strokeColor = {0, 0, 0}; - sensitiveStyle.nSegments = 72u; + sensitiveStyle.quarterSegments = 72u; std::pair allSensitives = {GeometryIdentifier(0u), sensitiveStyle}; diff --git a/Tests/UnitTests/Plugins/ActSVG/LayerSvgConverterTests.cpp b/Tests/UnitTests/Plugins/ActSVG/LayerSvgConverterTests.cpp index 7dd3a93fe95..ff4afc789b6 100644 --- a/Tests/UnitTests/Plugins/ActSVG/LayerSvgConverterTests.cpp +++ b/Tests/UnitTests/Plugins/ActSVG/LayerSvgConverterTests.cpp @@ -45,16 +45,17 @@ void setupTools() { std::shared_ptr generateDiscLayer(Acts::ActsScalar rInner, Acts::ActsScalar rOuter, - unsigned int nSegments, + unsigned int quarterSegments, unsigned int nRings, bool useTrapezoids = false) { // Some preparations setupTools(); + unsigned int fullSegments = 4 * quarterSegments; std::vector> moduleSurfaces; - Acts::ActsScalar phiStep = 2 * M_PI / nSegments; + Acts::ActsScalar phiStep = 2 * M_PI / fullSegments; Acts::ActsScalar rStep = (rOuter - rInner) / nRings; // Reserve & fill - moduleSurfaces.reserve(nSegments * nRings); + moduleSurfaces.reserve(fullSegments * nRings); // Radial disc if (!useTrapezoids) { for (unsigned int ir = 0; ir < nRings; ++ir) { @@ -62,7 +63,7 @@ std::shared_ptr generateDiscLayer(Acts::ActsScalar rInner, rBounds = std::make_shared( rInner + ir * rStep - 0.025 * rInner, rInner + (ir + 1u) * rStep + 0.025 * rInner, 0.55 * phiStep, 0.); - for (unsigned int is = 0; is < nSegments; ++is) { + for (unsigned int is = 0; is < fullSegments; ++is) { // Place the module auto placement = Acts::Transform3::Identity(); if ((is % 2) != 0u) { @@ -82,14 +83,14 @@ std::shared_ptr generateDiscLayer(Acts::ActsScalar rInner, Acts::ActsScalar yHalf = rStep * 0.5125; Acts::ActsScalar xHalfMin = - 1.15 * (rInner + ir * rStep) * M_PI / nSegments; + 1.15 * (rInner + ir * rStep) * M_PI / fullSegments; Acts::ActsScalar xHalfMax = - 1.15 * (rInner + (ir + 1) * rStep) * M_PI / nSegments; + 1.15 * (rInner + (ir + 1) * rStep) * M_PI / fullSegments; std::shared_ptr tBounds = std::make_shared(xHalfMin, xHalfMax, yHalf); - for (unsigned int is = 0; is < nSegments; ++is) { + for (unsigned int is = 0; is < fullSegments; ++is) { // Setting the phi Acts::ActsScalar cphi = -M_PI + is * phiStep; Acts::Vector3 center(radius * std::cos(cphi), radius * std::sin(cphi), @@ -111,7 +112,7 @@ std::shared_ptr generateDiscLayer(Acts::ActsScalar rInner, } } // Let's create the disc layer - return lCreator->discLayer(tgContext, moduleSurfaces, nRings, nSegments); + return lCreator->discLayer(tgContext, moduleSurfaces, nRings, fullSegments); } } // namespace @@ -125,7 +126,7 @@ BOOST_AUTO_TEST_CASE(DiscLayerRadialSvg) { discLayerStyle.highlights = {"mouseover", "mouseout"}; discLayerStyle.strokeColor = {25, 25, 25}; discLayerStyle.strokeWidth = 0.5; - discLayerStyle.nSegments = 72u; + discLayerStyle.quarterSegments = 72u; Acts::GeometryIdentifier geoID{0}; @@ -155,7 +156,7 @@ BOOST_AUTO_TEST_CASE(DiscLayerTrapezoidSvg) { discLayerStyle.highlights = {"mouseover", "mouseout"}; discLayerStyle.strokeColor = {25, 25, 25}; discLayerStyle.strokeWidth = 0.5; - discLayerStyle.nSegments = 72u; + discLayerStyle.quarterSegments = 72u; Acts::GeometryIdentifier geoID{0}; @@ -185,7 +186,7 @@ BOOST_AUTO_TEST_CASE(CylinderLayerSvg) { cylinderLayerStyle.highlights = {"mouseover", "mouseout"}; cylinderLayerStyle.strokeColor = {25, 25, 25}; cylinderLayerStyle.strokeWidth = 0.5; - cylinderLayerStyle.nSegments = 72u; + cylinderLayerStyle.quarterSegments = 72u; Acts::GeometryIdentifier geoID{0}; diff --git a/Tests/UnitTests/Plugins/ActSVG/PortalSvgConverterTests.cpp b/Tests/UnitTests/Plugins/ActSVG/PortalSvgConverterTests.cpp index 7f4cfa5d425..9fb1fdffa40 100644 --- a/Tests/UnitTests/Plugins/ActSVG/PortalSvgConverterTests.cpp +++ b/Tests/UnitTests/Plugins/ActSVG/PortalSvgConverterTests.cpp @@ -35,7 +35,7 @@ BOOST_AUTO_TEST_CASE(CylinderPortalsSvg) { portalStyle.highlights = {}; portalStyle.strokeColor = {25, 25, 25}; portalStyle.strokeWidth = 0.5; - portalStyle.nSegments = 72u; + portalStyle.quarterSegments = 72u; Acts::ActsScalar rInner = 10.; Acts::ActsScalar rOuter = 100.; @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(CylinderContainerPortalsSvg) { portalStyle.highlights = {}; portalStyle.strokeColor = {25, 25, 25}; portalStyle.strokeWidth = 0.5; - portalStyle.nSegments = 72u; + portalStyle.quarterSegments = 72u; Acts::ActsScalar rInner = 10.; Acts::ActsScalar rMiddle = 100.; diff --git a/Tests/UnitTests/Plugins/ActSVG/SurfaceSvgConverterTests.cpp b/Tests/UnitTests/Plugins/ActSVG/SurfaceSvgConverterTests.cpp index 49c92f3aaf9..8450453720c 100644 --- a/Tests/UnitTests/Plugins/ActSVG/SurfaceSvgConverterTests.cpp +++ b/Tests/UnitTests/Plugins/ActSVG/SurfaceSvgConverterTests.cpp @@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(PlanarSurfaces) { planarStyle.highlightColor = {255, 153, 51}; planarStyle.highlights = {"mouseover", "mouseout"}; planarStyle.strokeWidth = 0.5; - planarStyle.nSegments = 0u; + planarStyle.quarterSegments = 0u; // Rectangle case auto rectangleBounds = std::make_shared(36., 64.); @@ -169,7 +169,7 @@ BOOST_AUTO_TEST_CASE(DiscSurfaces) { discStyle.highlightColor = {153, 204, 0}; discStyle.highlights = {"mouseover", "mouseout"}; discStyle.strokeWidth = 0.5; - discStyle.nSegments = 72u; + discStyle.quarterSegments = 72u; auto transform = Acts::Transform3::Identity(); transform.pretranslate(Acts::Vector3{20., 20., 100.}); diff --git a/Tests/UnitTests/Plugins/ActSVG/TrackingGeometrySvgConverterTests.cpp b/Tests/UnitTests/Plugins/ActSVG/TrackingGeometrySvgConverterTests.cpp index 7c869e90de7..3b7a8856875 100644 --- a/Tests/UnitTests/Plugins/ActSVG/TrackingGeometrySvgConverterTests.cpp +++ b/Tests/UnitTests/Plugins/ActSVG/TrackingGeometrySvgConverterTests.cpp @@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(CylindricalTrackingGeometrySvg) { cylinderLayerStyle.highlights = {"mouseover", "mouseout"}; cylinderLayerStyle.strokeColor = {25, 25, 25}; cylinderLayerStyle.strokeWidth = 0.5; - cylinderLayerStyle.nSegments = 72u; + cylinderLayerStyle.quarterSegments = 72u; Acts::GeometryIdentifier geoID{0}; diff --git a/Tests/UnitTests/Plugins/TGeo/TGeoTubeConversionTests.cpp b/Tests/UnitTests/Plugins/TGeo/TGeoTubeConversionTests.cpp index 3309895866b..2f18c391958 100644 --- a/Tests/UnitTests/Plugins/TGeo/TGeoTubeConversionTests.cpp +++ b/Tests/UnitTests/Plugins/TGeo/TGeoTubeConversionTests.cpp @@ -99,7 +99,6 @@ BOOST_AUTO_TEST_CASE(TGeoTube_to_CylinderSurface) { objVis, center, center + 1.2 * bR * rotation.col(1), 4., 2.5, green); GeometryView3D::drawArrowForward( objVis, center, center + 1.2 * bhZ * rotation.col(2), 4., 2.5, blue); - objVis.write("TGeoConversion_TGeoTube_CylinderSurface_" + std::to_string(icyl)); objVis.clear(); From dfc2aff43e3beecdbe62d521d114c47bb75336a7 Mon Sep 17 00:00:00 2001 From: "Alexander J. Pfleger" <70842573+AJPfleger@users.noreply.github.com> Date: Thu, 3 Oct 2024 20:01:49 +0200 Subject: [PATCH 2/5] refactor: use `std::ranges::all_of`, `any_of`, `none_of` (#3593) I couldn't replace all instances, since https://github.com/acts-project/acts/blame/464675980c50a6070f5635127ee27fd29de5a679/Core/include/Acts/Propagator/MultiEigenStepperLoop.hpp#L458 seems not to return an iterator, that can be interpreted by ranges algorithms. --- Core/include/Acts/Surfaces/DiamondBounds.hpp | 3 +-- Core/src/Geometry/Extent.cpp | 6 ++---- .../Geant4/src/SensitiveSteppingAction.cpp | 10 +++++----- .../src/TrackFindingAlgorithmExaTrkX.cpp | 5 +++-- .../src/Utilities/EventDataTransforms.cpp | 2 +- Examples/Io/Root/src/RootMaterialDecorator.cpp | 4 ++-- Plugins/ExaTrkX/src/ExaTrkXPipeline.cpp | 7 ++++--- .../src/GeoModelDetectorObjectFactory.cpp | 17 +++++++++-------- Tests/Benchmarks/RayFrustumBenchmark.cpp | 16 ++++++++-------- .../Acts/Tests/CommonHelpers/Assertions.hpp | 18 +++++++++--------- .../Io/Csv/MeasurementReaderWriterTests.cpp | 3 ++- 11 files changed, 46 insertions(+), 45 deletions(-) diff --git a/Core/include/Acts/Surfaces/DiamondBounds.hpp b/Core/include/Acts/Surfaces/DiamondBounds.hpp index a23b8831125..7497bd22309 100644 --- a/Core/include/Acts/Surfaces/DiamondBounds.hpp +++ b/Core/include/Acts/Surfaces/DiamondBounds.hpp @@ -126,8 +126,7 @@ inline std::vector DiamondBounds::values() const { } inline void DiamondBounds::checkConsistency() noexcept(false) { - if (std::any_of(m_values.begin(), m_values.end(), - [](auto v) { return v <= 0.; })) { + if (std::ranges::any_of(m_values, [](auto v) { return v <= 0.; })) { throw std::invalid_argument("DiamondBounds: negative half length."); } if (get(eHalfLengthXnegY) > get(eHalfLengthXzeroY) || diff --git a/Core/src/Geometry/Extent.cpp b/Core/src/Geometry/Extent.cpp index 9e520d171a3..2f07f6358bc 100644 --- a/Core/src/Geometry/Extent.cpp +++ b/Core/src/Geometry/Extent.cpp @@ -144,8 +144,7 @@ bool Acts::Extent::contains(const Extent& rhs, // Check all if (!bValue.has_value()) { - return std::all_of(allBinningValues().begin(), allBinningValues().end(), - checkContainment); + return std::ranges::all_of(allBinningValues(), checkContainment); } // Check specific return checkContainment(bValue.value()); @@ -163,8 +162,7 @@ bool Acts::Extent::intersects(const Extent& rhs, // Check all if (!bValue.has_value()) { - return std::any_of(allBinningValues().begin(), allBinningValues().end(), - checkIntersect); + return std::ranges::any_of(allBinningValues(), checkIntersect); } // Check specific return checkIntersect(bValue.value()); diff --git a/Examples/Algorithms/Geant4/src/SensitiveSteppingAction.cpp b/Examples/Algorithms/Geant4/src/SensitiveSteppingAction.cpp index cb763ecc582..17df42bdb21 100644 --- a/Examples/Algorithms/Geant4/src/SensitiveSteppingAction.cpp +++ b/Examples/Algorithms/Geant4/src/SensitiveSteppingAction.cpp @@ -18,6 +18,7 @@ #include "ActsExamples/Geant4/SensitiveSurfaceMapper.hpp" #include "ActsFatras/EventData/Barcode.hpp" +#include #include #include #include @@ -254,11 +255,10 @@ void ActsExamples::SensitiveSteppingAction::UserSteppingAction( buffer.back().momentum4After(), eventStore().particleHitCount.at(particleId) - 1); - assert(std::all_of(buffer.begin(), buffer.end(), - [&](const auto& h) { return h.geometryId() == geoId; })); - assert(std::all_of(buffer.begin(), buffer.end(), [&](const auto& h) { - return h.particleId() == particleId; - })); + assert(std::ranges::all_of( + buffer, [&](const auto& h) { return h.geometryId() == geoId; })); + assert(std::ranges::all_of( + buffer, [&](const auto& h) { return h.particleId() == particleId; })); eventStore().numberGeantSteps += buffer.size(); eventStore().maxStepsForHit = diff --git a/Examples/Algorithms/TrackFindingExaTrkX/src/TrackFindingAlgorithmExaTrkX.cpp b/Examples/Algorithms/TrackFindingExaTrkX/src/TrackFindingAlgorithmExaTrkX.cpp index 06fcb1c9438..05fe35a6ea0 100644 --- a/Examples/Algorithms/TrackFindingExaTrkX/src/TrackFindingAlgorithmExaTrkX.cpp +++ b/Examples/Algorithms/TrackFindingExaTrkX/src/TrackFindingAlgorithmExaTrkX.cpp @@ -19,6 +19,7 @@ #include "ActsExamples/EventData/SimSpacePoint.hpp" #include "ActsExamples/Framework/WhiteBoard.hpp" +#include #include using namespace ActsExamples; @@ -97,8 +98,8 @@ ActsExamples::TrackFindingAlgorithmExaTrkX::TrackFindingAlgorithmExaTrkX( NodeFeature::eClusterX, NodeFeature::eClusterY, NodeFeature::eCellCount, NodeFeature::eCellSum, NodeFeature::eCluster1R, NodeFeature::eCluster2R}; - auto wantClFeatures = std::any_of( - m_cfg.nodeFeatures.begin(), m_cfg.nodeFeatures.end(), + auto wantClFeatures = std::ranges::any_of( + m_cfg.nodeFeatures, [&](const auto& f) { return Acts::rangeContainsValue(clFeatures, f); }); if (wantClFeatures && !m_inputClusters.isInitialized()) { diff --git a/Examples/Framework/src/Utilities/EventDataTransforms.cpp b/Examples/Framework/src/Utilities/EventDataTransforms.cpp index a82df0cf5a3..79d3d543a05 100644 --- a/Examples/Framework/src/Utilities/EventDataTransforms.cpp +++ b/Examples/Framework/src/Utilities/EventDataTransforms.cpp @@ -32,7 +32,7 @@ const ActsExamples::SimSpacePoint* ActsExamples::findSpacePointForIndex( ActsExamples::Index index, const SimSpacePointContainer& spacepoints) { auto match = [&](const SimSpacePoint& sp) { const auto& sls = sp.sourceLinks(); - return std::any_of(sls.begin(), sls.end(), [&](const auto& sl) { + return std::ranges::any_of(sls, [&](const auto& sl) { return sl.template get().index() == index; }); }; diff --git a/Examples/Io/Root/src/RootMaterialDecorator.cpp b/Examples/Io/Root/src/RootMaterialDecorator.cpp index b8f49c53ea1..37f396bb86c 100644 --- a/Examples/Io/Root/src/RootMaterialDecorator.cpp +++ b/Examples/Io/Root/src/RootMaterialDecorator.cpp @@ -148,8 +148,8 @@ ActsExamples::RootMaterialDecorator::RootMaterialDecorator( std::vector hists{n, v, o, min, max, t, x0, l0, A, Z, rho}; // Only go on when you have all histograms - if (std::all_of(hists.begin(), hists.end(), - [](const auto* hist) { return hist != nullptr; })) { + if (std::ranges::all_of( + hists, [](const auto* hist) { return hist != nullptr; })) { // Get the number of bins int nbins0 = t->GetNbinsX(); int nbins1 = t->GetNbinsY(); diff --git a/Plugins/ExaTrkX/src/ExaTrkXPipeline.cpp b/Plugins/ExaTrkX/src/ExaTrkXPipeline.cpp index a3d6dfe1148..d53de1d3071 100644 --- a/Plugins/ExaTrkX/src/ExaTrkXPipeline.cpp +++ b/Plugins/ExaTrkX/src/ExaTrkXPipeline.cpp @@ -8,6 +8,8 @@ #include "Acts/Plugins/ExaTrkX/ExaTrkXPipeline.hpp" +#include "Acts/Utilities/Helpers.hpp" + #include namespace Acts { @@ -27,9 +29,8 @@ ExaTrkXPipeline::ExaTrkXPipeline( if (!m_trackBuilder) { throw std::invalid_argument("Missing track building module"); } - if (m_edgeClassifiers.empty() or - not std::all_of(m_edgeClassifiers.begin(), m_edgeClassifiers.end(), - [](const auto &a) { return static_cast(a); })) { + if (m_edgeClassifiers.empty() || + rangeContainsValue(m_edgeClassifiers, nullptr)) { throw std::invalid_argument("Missing graph construction module"); } } diff --git a/Plugins/GeoModel/src/GeoModelDetectorObjectFactory.cpp b/Plugins/GeoModel/src/GeoModelDetectorObjectFactory.cpp index 91580a7bfda..a8844d9fa5d 100644 --- a/Plugins/GeoModel/src/GeoModelDetectorObjectFactory.cpp +++ b/Plugins/GeoModel/src/GeoModelDetectorObjectFactory.cpp @@ -19,6 +19,7 @@ #include "Acts/Plugins/GeoModel/GeoModelConverters.hpp" #include "Acts/Plugins/GeoModel/IGeoShapeConverter.hpp" +#include #include #include @@ -141,9 +142,9 @@ Acts::GeoModelDetectorObjectFactory::findAllSubVolumes(const PVConstLink &vol) { } bool Acts::GeoModelDetectorObjectFactory::convertBox(std::string name) { - auto convB = std::any_of( - m_cfg.convertBox.begin(), m_cfg.convertBox.end(), - [&](const auto &n) { return name.find(n) != std::string::npos; }); + auto convB = std::ranges::any_of(m_cfg.convertBox, [&](const auto &n) { + return name.find(n) != std::string::npos; + }); return convB; } @@ -192,14 +193,14 @@ bool Acts::GeoModelDetectorObjectFactory::matches(const std::string &name, return true; } - auto matchName = std::any_of( - m_cfg.nameList.begin(), m_cfg.nameList.end(), - [&](const auto &n) { return name.find(n) != std::string::npos; }); + auto matchName = std::ranges::any_of(m_cfg.nameList, [&](const auto &n) { + return name.find(n) != std::string::npos; + }); std::string matStr = physvol->getLogVol()->getMaterial()->getName(); - auto matchMaterial = std::any_of( - m_cfg.materialList.begin(), m_cfg.materialList.end(), + auto matchMaterial = std::ranges::any_of( + m_cfg.materialList, [&](const auto &m) { return matStr.find(m) != std::string::npos; }); bool match = matchMaterial && matchName; diff --git a/Tests/Benchmarks/RayFrustumBenchmark.cpp b/Tests/Benchmarks/RayFrustumBenchmark.cpp index 2d0069da1b1..e4f11e60991 100644 --- a/Tests/Benchmarks/RayFrustumBenchmark.cpp +++ b/Tests/Benchmarks/RayFrustumBenchmark.cpp @@ -187,10 +187,10 @@ int main(int /*argc*/, char** /*argv[]*/) { return {name, func(testBox, ray)}; }); - bool all = std::all_of(results.begin(), results.end(), - [](const auto& r) { return r.second; }); - bool none = std::none_of(results.begin(), results.end(), - [](const auto& r) { return r.second; }); + bool all = + std::ranges::all_of(results, [](const auto& r) { return r.second; }); + bool none = + std::ranges::none_of(results, [](const auto& r) { return r.second; }); if (!all && !none) { std::cerr << "Discrepancy: " << std::endl; @@ -369,10 +369,10 @@ int main(int /*argc*/, char** /*argv[]*/) { return {name, func(testBox, fr)}; }); - bool all = std::all_of(results.begin(), results.end(), - [](const auto& r) { return r.second; }); - bool none = std::none_of(results.begin(), results.end(), - [](const auto& r) { return r.second; }); + bool all = + std::ranges::all_of(results, [](const auto& r) { return r.second; }); + bool none = + std::ranges::none_of(results, [](const auto& r) { return r.second; }); if (!all && !none) { std::cerr << "Discrepancy: " << std::endl; diff --git a/Tests/CommonHelpers/Acts/Tests/CommonHelpers/Assertions.hpp b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/Assertions.hpp index 6bc19dc0431..3fee5af18ae 100644 --- a/Tests/CommonHelpers/Acts/Tests/CommonHelpers/Assertions.hpp +++ b/Tests/CommonHelpers/Acts/Tests/CommonHelpers/Assertions.hpp @@ -10,15 +10,15 @@ #include +#include #include -#define CHECK_NE_COLLECTIONS(col1, col2) \ - do { \ - BOOST_CHECK_EQUAL(col1.size(), col2.size()); \ - std::vector result; \ - for (std::size_t i = 0; i < col1.size(); i++) { \ - result.push_back(col1[i] == col2[i]); \ - } \ - BOOST_CHECK( \ - !std::all_of(result.begin(), result.end(), [](bool r) { return r; })); \ +#define CHECK_NE_COLLECTIONS(col1, col2) \ + do { \ + BOOST_CHECK_EQUAL(col1.size(), col2.size()); \ + std::vector result; \ + for (std::size_t i = 0; i < col1.size(); i++) { \ + result.push_back(col1[i] == col2[i]); \ + } \ + BOOST_CHECK(!std::ranges::all_of(result, [](bool r) { return r; })); \ } while (0) diff --git a/Tests/UnitTests/Examples/Io/Csv/MeasurementReaderWriterTests.cpp b/Tests/UnitTests/Examples/Io/Csv/MeasurementReaderWriterTests.cpp index 1a3d9662a2a..7786a5ec8a1 100644 --- a/Tests/UnitTests/Examples/Io/Csv/MeasurementReaderWriterTests.cpp +++ b/Tests/UnitTests/Examples/Io/Csv/MeasurementReaderWriterTests.cpp @@ -20,6 +20,7 @@ #include "ActsExamples/Io/Csv/CsvMeasurementReader.hpp" #include "ActsExamples/Io/Csv/CsvMeasurementWriter.hpp" +#include #include #include #include @@ -152,7 +153,7 @@ BOOST_AUTO_TEST_CASE(CsvMeasurementRoundTrip) { std::abs(ca.activation - cb.activation) < 1.e-4; }; - BOOST_CHECK(std::any_of(b.channels.begin(), b.channels.end(), match)); + BOOST_CHECK(std::ranges::any_of(b.channels, match)); } } From a42ce7c116cea43d0f43b385171c14b5c63f698c Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Thu, 3 Oct 2024 21:46:30 +0200 Subject: [PATCH 3/5] fix: Correct initial `q/p` covariance term in `TrackParamsEstimationAlgorithm` in Examples (#3665) I seem to have made a mistake calculating the covariance term on the first try in https://github.com/acts-project/acts/pull/3422. This is corrected here --- .../performance_ckf.root | Bin 31176 -> 31236 bytes .../performance_ckf_ambi.root | Bin 27720 -> 27753 bytes ...ance_vertexing_amvf_gauss_notime_hist.root | Bin 48479 -> 48551 bytes ...ormance_vertexing_amvf_grid_time_hist.root | Bin 48977 -> 48768 bytes .../src/TrackParamsEstimationAlgorithm.cpp | 15 ++++---- .../TruthTracking/ParticleSmearing.cpp | 2 +- Examples/Python/tests/root_file_hashes.txt | 32 +++++++++--------- 7 files changed, 24 insertions(+), 25 deletions(-) diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf.root index f7fb66f24ab29839e053027bc7629112e88fbdcb..b02aa3773acb66183310e6abacdafc30284ce3e8 100644 GIT binary patch delta 29195 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 RzWsXn7URwV?^T2S{{UHY1L*(& delta 29094 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 diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf_ambi.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf_ambi.root index 8fbd66c0abb73f0c6e3246214e1e439dab5565d0..35c6a2c8519e1b829695dc2bb8045d47472b6b75 100644 GIT binary patch delta 25521 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 delta 26523 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 rQ(I?2$(_naYRk|Rd}LEw4xb^AD{jBpF zJ^^r$U*?eO4FG`20sy=Ss6Gg2!9Ga2kGp@9VMh)I)-#|s0UmqVx(AP{#5udkK>mBY z1ORZ-9!G$DAR|Bi6e~Xt&~EWKK*h@M0e;{4_iy0y$D!agAD^#c1+oEQA1{nyp8dXv zg=Ge!GC;eiK6U|j!BGHD!JBXapvngTO<)^PafL46xZb!pM6IL@?iKo&Vo8Yc!`qU; zS7@eYuo%>LOzn7Nciak5#` zVhCEssz4y;+^{T40LMTq!m2>qliX8Fr1zl!X{5G36ad$psK#%Kf0GPm1(JhN5Ktef z1{=eWVE_O?ZYa4rP;z5oDIc3yADd9%piO$uiNVnb&!A5PmJow~BGiKJTfR=Wj}9)w zqdrtO6Pscxz6UY~k3LxdG#JJP;y=+8Z9}`@{P5iP_W7;UO3ZT^31coe1TQ2krYa=9 zO!d3q0eTvdk#k(<#e!Q)B(!cU0ATc|L@5+N$cvfiA72a*1pt4;3V02#sc7Zmil*V} zY;Iy_?p%e5B*z4uc)jP;KvWJW1IoXtEhT}|RYbZ6UvpD|`#Ft4MS*RU%fRF=DPDH= zwIDkJ>B@SX*PK09ow`WpLOnP)m=riXj&1fP_=7BPp_izL7~yXN65j&ThP*BtUfRpV zc07wqG&`pfN2KctSU2I4e1U^J!O+u&g2qH)9D4Iq4#*z#bj;XS+ytn>qqCL0vCxiV zpSw@N24}pD4&X+5A_);Q-~^OHODJ1Bk8E+3fLpm}K=D9;B|N|rSfeha04s)-t}n

KqXvy2PW!9ORJcEL*`kKyZN2? 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 delta 27411 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 Date: Fri, 4 Oct 2024 00:46:56 +0200 Subject: [PATCH 4/5] fix: Fit iterator traits for ContainerIndexIterator (#3689) It looks like that `std:: iterator_traits< Acts::ContainerIndexIterator< whatever ...> >::iterator_category ` was evaluated to `std::output_iterator_tag` instead of `Iter::iterator_category` (i.e. `std::random_access_iterator_tag`). This made it impossible to use `std::distance` with this iterator class. See https://en.cppreference.com/w/cpp/iterator/iterator_traits to see why. This PR fixes it. --- Core/include/Acts/Utilities/Iterator.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/include/Acts/Utilities/Iterator.hpp b/Core/include/Acts/Utilities/Iterator.hpp index ccdff61c061..a69e6c77faa 100644 --- a/Core/include/Acts/Utilities/Iterator.hpp +++ b/Core/include/Acts/Utilities/Iterator.hpp @@ -22,6 +22,8 @@ class ContainerIndexIterator { using container_type = std::conditional_t; using difference_type = std::ptrdiff_t; + using pointer = void; + using reference = void; ContainerIndexIterator() : m_container(nullptr), m_index(0) {} From bcf1a194db044a45b7e025a72c7180ac10e04d50 Mon Sep 17 00:00:00 2001 From: Andreas Salzburger Date: Fri, 4 Oct 2024 02:02:54 +0200 Subject: [PATCH 5/5] feat: Allow Style setting for IndexedSurfaceGrid in Svg (#3686) This PR allows to define the style of the grid when displaying the `IndexedSurfaceGrid` in SVG. --- Examples/Python/src/Svg.cpp | 28 +++++++++++++++++++ .../ActSVG/DetectorVolumeSvgConverter.hpp | 2 ++ .../ActSVG/src/DetectorVolumeSvgConverter.cpp | 3 +- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Examples/Python/src/Svg.cpp b/Examples/Python/src/Svg.cpp index f1d46cadcd8..ee011920947 100644 --- a/Examples/Python/src/Svg.cpp +++ b/Examples/Python/src/Svg.cpp @@ -328,6 +328,21 @@ void addSvg(Context& ctx) { }); } + { + auto gco = py::class_(svg, "GridOptions") + .def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(gco, Svg::GridConverter::Options); + ACTS_PYTHON_MEMBER(style); + ACTS_PYTHON_STRUCT_END(); + + auto isco = py::class_( + svg, "IndexedSurfacesOptions") + .def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(isco, Svg::IndexedSurfacesConverter::Options); + ACTS_PYTHON_MEMBER(gridOptions); + ACTS_PYTHON_STRUCT_END(); + } + // How detector volumes are drawn: Svg DetectorVolume options & drawning { auto c = py::class_( @@ -338,12 +353,16 @@ void addSvg(Context& ctx) { ACTS_PYTHON_MEMBER(portalIndices); ACTS_PYTHON_MEMBER(portalOptions); ACTS_PYTHON_MEMBER(surfaceOptions); + ACTS_PYTHON_MEMBER(indexedSurfacesOptions); ACTS_PYTHON_STRUCT_END(); // Define the proto volume & indexed surface grid py::class_(svg, "ProtoVolume"); py::class_(svg, "ProtoIndexedSurfaceGrid"); + // Define the proto grid + py::class_(svg, "ProtoGrid"); + // Convert an Acts::Experimental::DetectorVolume object into an // acts::svg::proto::volume svg.def("convertDetectorVolume", &Svg::DetectorVolumeConverter::convert); @@ -352,6 +371,15 @@ void addSvg(Context& ctx) { svg.def("drawDetectorVolume", &drawDetectorVolume); } + // Draw the ProtoIndexedSurfaceGrid + { + svg.def("drawIndexedSurfaces", + [](const Svg::ProtoIndexedSurfaceGrid& pIndexedSurfaceGrid, + const std::string& identification) { + return Svg::View::xy(pIndexedSurfaceGrid, identification); + }); + } + // How a detector is drawn: Svg Detector options & drawning { svg.def("drawDetector", &drawDetector); } diff --git a/Plugins/ActSVG/include/Acts/Plugins/ActSVG/DetectorVolumeSvgConverter.hpp b/Plugins/ActSVG/include/Acts/Plugins/ActSVG/DetectorVolumeSvgConverter.hpp index 6ac84da77ee..f27db472439 100644 --- a/Plugins/ActSVG/include/Acts/Plugins/ActSVG/DetectorVolumeSvgConverter.hpp +++ b/Plugins/ActSVG/include/Acts/Plugins/ActSVG/DetectorVolumeSvgConverter.hpp @@ -41,6 +41,8 @@ struct Options { PortalConverter::Options portalOptions; /// The Surface converter options SurfaceConverter::Options surfaceOptions; + /// The Grid converter options + IndexedSurfacesConverter::Options indexedSurfacesOptions; }; /// Write/create the detector volume diff --git a/Plugins/ActSVG/src/DetectorVolumeSvgConverter.cpp b/Plugins/ActSVG/src/DetectorVolumeSvgConverter.cpp index c187e69569b..93527488538 100644 --- a/Plugins/ActSVG/src/DetectorVolumeSvgConverter.cpp +++ b/Plugins/ActSVG/src/DetectorVolumeSvgConverter.cpp @@ -68,7 +68,8 @@ Acts::Svg::DetectorVolumeConverter::convert( // Make dedicated surface grid sheets const auto& internalNavigationDelegate = dVolume.internalNavigation(); - IndexedSurfacesConverter::Options isOptions; + IndexedSurfacesConverter::Options isOptions = + volumeOptions.indexedSurfacesOptions; // Use or transfer the surface style if (isOptions.surfaceStyles.empty()) { std::pair style{