From 04f506b37d6425d06f4e3b946388ac5c6d880e3c Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 19 Sep 2024 18:07:20 +0200 Subject: [PATCH 01/24] feat: Add mutable surface getter to Portal --- Core/include/Acts/Geometry/Portal.hpp | 4 ++++ Core/src/Geometry/Portal.cpp | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/Core/include/Acts/Geometry/Portal.hpp b/Core/include/Acts/Geometry/Portal.hpp index c6ec526a42d..ffaad3e2ccb 100644 --- a/Core/include/Acts/Geometry/Portal.hpp +++ b/Core/include/Acts/Geometry/Portal.hpp @@ -212,6 +212,10 @@ class Portal { /// @return The portal surface const RegularSurface& surface() const; + /// Access the portal surface that is shared between the two links + /// @return The portal surface + RegularSurface& surface(); + private: /// Helper to check surface equivalence without checking material status. This /// is needed because we allow fusing portals with surfaces that are diff --git a/Core/src/Geometry/Portal.cpp b/Core/src/Geometry/Portal.cpp index fac9041b40f..dafe42f9e6c 100644 --- a/Core/src/Geometry/Portal.cpp +++ b/Core/src/Geometry/Portal.cpp @@ -172,6 +172,11 @@ const RegularSurface& Portal::surface() const { return *m_surface; } +RegularSurface& Portal::surface() { + assert(m_surface != nullptr); + return *m_surface; +} + Portal Portal::merge(const GeometryContext& gctx, Portal& aPortal, Portal& bPortal, BinningValue direction, const Logger& logger) { From 2029567748db85b109f6492dd4dc00b7fc18e22a Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 16 Sep 2024 17:44:12 +0200 Subject: [PATCH 02/24] feat(geo): TrackingVolume gets portal storage --- Core/include/Acts/Geometry/TrackingVolume.hpp | 22 ++++++++++++++++ Core/src/Geometry/TrackingVolume.cpp | 25 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/Core/include/Acts/Geometry/TrackingVolume.hpp b/Core/include/Acts/Geometry/TrackingVolume.hpp index c5590e1168d..799f3802957 100644 --- a/Core/include/Acts/Geometry/TrackingVolume.hpp +++ b/Core/include/Acts/Geometry/TrackingVolume.hpp @@ -48,6 +48,7 @@ class IVolumeMaterial; class Surface; class TrackingVolume; struct GeometryIdentifierHook; +class Portal; /// Interface types of the Gen1 geometry model /// @note This interface is being replaced, and is subject to removal @@ -301,6 +302,26 @@ class TrackingVolume : public Volume { /// @return the range of volumes MutableVolumeRange volumes(); + using MutablePortalRange = + detail::TransformRange>>; + + using PortalRange = + detail::TransformRange>>; + + /// Return all portals registered under this tracking volume + /// @return the range of portals + PortalRange portals() const; + + /// Return mutable view of the registered portals under this tracking volume + /// @return the range of portals + MutablePortalRange portals(); + + /// Add a portal to this tracking volume + /// @param portal The portal to add + void addPortal(std::shared_ptr portal); + /// Add a child volume to this tracking volume /// @param volume The volume to add /// @note The @p volume will have its mother volume assigned to @p this. @@ -494,6 +515,7 @@ class TrackingVolume : public Volume { std::string m_name; std::vector> m_volumes; + std::vector> m_portals; }; } // namespace Acts diff --git a/Core/src/Geometry/TrackingVolume.cpp b/Core/src/Geometry/TrackingVolume.cpp index 5e9bab8a742..4a91784ce6b 100644 --- a/Core/src/Geometry/TrackingVolume.cpp +++ b/Core/src/Geometry/TrackingVolume.cpp @@ -11,6 +11,7 @@ #include "Acts/Definitions/Direction.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" #include "Acts/Geometry/GlueVolumesDescriptor.hpp" +#include "Acts/Geometry/Portal.hpp" #include "Acts/Geometry/VolumeBounds.hpp" #include "Acts/Material/IMaterialDecorator.hpp" #include "Acts/Material/IVolumeMaterial.hpp" @@ -424,6 +425,18 @@ void TrackingVolume::closeGeometry( logger); } } + + GeometryIdentifier::Value iportal = 0; + for (auto& portal : portals()) { + auto portalId = GeometryIdentifier(volumeID).setBoundary(++iportal); + assert(portal.isValid() && "Invalid portal encountered during closing"); + + portal.surface().assignGeometryId(portalId); + } + + for (auto& volume : volumes()) { + volume.closeGeometry(materialDecorator, volumeMap, vol, hook, logger); + } } // Returns the boundary surfaces ordered in probability to hit them based on @@ -641,4 +654,16 @@ TrackingVolume& TrackingVolume::addVolume( return *m_volumes.back(); } +TrackingVolume::PortalRange TrackingVolume::portals() const { + return PortalRange{m_portals}; +} + +TrackingVolume::MutablePortalRange TrackingVolume::portals() { + return MutablePortalRange{m_portals}; +} + +void TrackingVolume::addPortal(std::shared_ptr portal) { + m_portals.push_back(std::move(portal)); +} + } // namespace Acts From 16850a506fa164c43373aebea1da0a35ae461a12 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 20 Sep 2024 13:41:17 +0200 Subject: [PATCH 03/24] fix: pybind11 compatibility for paths --- Examples/Python/src/Obj.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/Python/src/Obj.cpp b/Examples/Python/src/Obj.cpp index ce03e60a3fe..56fd1804554 100644 --- a/Examples/Python/src/Obj.cpp +++ b/Examples/Python/src/Obj.cpp @@ -19,6 +19,7 @@ #include #include +#include namespace py = pybind11; using namespace pybind11::literals; From f8e1fd83111003183c3ff49116d60399e81277af Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 17 Sep 2024 11:36:55 +0200 Subject: [PATCH 04/24] refactor: ViewConfig python bindings Turns this from a typedef over an array to a struct with constructors from ints, doubles and hex strings. color renaming continued fixes after fstream removal refactor: Move visualization logic into Surface, Volume, Polyhedron refactor: Update `ColorRGB` to `Color` --- .../include/Acts/Visualization/ViewConfig.hpp | 1 - Examples/Python/src/Obj.cpp | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Core/include/Acts/Visualization/ViewConfig.hpp b/Core/include/Acts/Visualization/ViewConfig.hpp index 6fcf1b47984..98a96d89f5b 100644 --- a/Core/include/Acts/Visualization/ViewConfig.hpp +++ b/Core/include/Acts/Visualization/ViewConfig.hpp @@ -85,7 +85,6 @@ struct Color { /// @param rhs The second color /// @return True if the colors are equal friend bool operator==(const Color& lhs, const Color& rhs) = default; - /// Output stream operator /// @param os The output stream /// @param color The color to be printed diff --git a/Examples/Python/src/Obj.cpp b/Examples/Python/src/Obj.cpp index 56fd1804554..46c6ec55ed4 100644 --- a/Examples/Python/src/Obj.cpp +++ b/Examples/Python/src/Obj.cpp @@ -30,6 +30,25 @@ namespace Acts::Python { void addObj(Context& ctx) { auto [m, mex] = ctx.get("main", "examples"); + { + py::class_(m, "ViewConfig") + .def_readwrite("visible", &ViewConfig::visible) + .def_readwrite("color", &ViewConfig::color) + .def_readwrite("offset", &ViewConfig::offset) + .def_readwrite("lineThickness", &ViewConfig::lineThickness) + .def_readwrite("surfaceThickness", &ViewConfig::surfaceThickness) + .def_readwrite("nSegments", &ViewConfig::nSegments) + .def_readwrite("triangulate", &ViewConfig::triangulate) + .def_readwrite("outputName", &ViewConfig::outputName); + + py::class_(m, "Color") + .def(py::init<>()) + .def(py::init()) + .def(py::init()) + .def(py::init()) + .def_readonly("rgb", &Color::rgb); + } + { /// Write a collection of surfaces to an '.obj' file /// From 202bec6c7be3bbb4801d5a23f49341906ab3ad71 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 17 Sep 2024 17:01:45 +0200 Subject: [PATCH 05/24] refactor: Move ObjVisualization to cpp file --- .../Acts/Visualization/ObjVisualization3D.hpp | 10 +----- Core/src/Visualization/CMakeLists.txt | 5 ++- .../Visualization/ObjVisualization3D.cpp} | 36 +++++++++---------- 3 files changed, 21 insertions(+), 30 deletions(-) rename Core/{include/Acts/Visualization/detail/ObjVisualization3D.ipp => src/Visualization/ObjVisualization3D.cpp} (83%) diff --git a/Core/include/Acts/Visualization/ObjVisualization3D.hpp b/Core/include/Acts/Visualization/ObjVisualization3D.hpp index 941e719f870..1f03b558b6a 100644 --- a/Core/include/Acts/Visualization/ObjVisualization3D.hpp +++ b/Core/include/Acts/Visualization/ObjVisualization3D.hpp @@ -26,14 +26,10 @@ namespace Acts { /// This helper produces output in the OBJ format. Note that colors are not /// supported in this implementation. /// -template class ObjVisualization3D : public IVisualization3D { public: - static_assert(std::is_same_v || std::is_same_v, - "Use either double or float"); - /// Stored value type, should be double or float - using ValueType = T; + using ValueType = double; /// Type of a vertex based on the value type using VertexType = Eigen::Matrix; @@ -91,8 +87,4 @@ class ObjVisualization3D : public IVisualization3D { std::map m_faceColors; }; -#ifndef DOXYGEN -#include "detail/ObjVisualization3D.ipp" -#endif - } // namespace Acts diff --git a/Core/src/Visualization/CMakeLists.txt b/Core/src/Visualization/CMakeLists.txt index 5d4f916af1c..567b1e1e236 100644 --- a/Core/src/Visualization/CMakeLists.txt +++ b/Core/src/Visualization/CMakeLists.txt @@ -1 +1,4 @@ -target_sources(ActsCore PRIVATE GeometryView3D.cpp EventDataView3D.cpp) +target_sources( + ActsCore + PRIVATE GeometryView3D.cpp EventDataView3D.cpp ObjVisualization3D.cpp +) diff --git a/Core/include/Acts/Visualization/detail/ObjVisualization3D.ipp b/Core/src/Visualization/ObjVisualization3D.cpp similarity index 83% rename from Core/include/Acts/Visualization/detail/ObjVisualization3D.ipp rename to Core/src/Visualization/ObjVisualization3D.cpp index 2419ef8c546..f0ac76f4145 100644 --- a/Core/include/Acts/Visualization/detail/ObjVisualization3D.ipp +++ b/Core/src/Visualization/ObjVisualization3D.cpp @@ -6,15 +6,16 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -template -void ObjVisualization3D::vertex(const Vector3& vtx, Color color) { +#include "Acts/Visualization/ObjVisualization3D.hpp" + +namespace Acts { + +void ObjVisualization3D::vertex(const Vector3& vtx, Color color) { m_vertexColors[m_vertices.size()] = color; m_vertices.push_back(vtx.template cast()); } -template -void ObjVisualization3D::line(const Vector3& a, const Vector3& b, - Color color) { +void ObjVisualization3D::line(const Vector3& a, const Vector3& b, Color color) { if (color != Color{0, 0, 0}) { m_lineColors[m_lines.size()] = color; } @@ -24,9 +25,7 @@ void ObjVisualization3D::line(const Vector3& a, const Vector3& b, m_lines.push_back({m_vertices.size() - 2, m_vertices.size() - 1}); } -template -void ObjVisualization3D::face(const std::vector& vtxs, - Color color) { +void ObjVisualization3D::face(const std::vector& vtxs, Color color) { if (color != Color{0, 0, 0}) { m_faceColors[m_faces.size()] = color; } @@ -39,10 +38,9 @@ void ObjVisualization3D::face(const std::vector& vtxs, m_faces.push_back(std::move(idxs)); } -template -void ObjVisualization3D::faces(const std::vector& vtxs, - const std::vector& faces, - Color color) { +void ObjVisualization3D::faces(const std::vector& vtxs, + const std::vector& faces, + Color color) { // No faces given - call the face() method if (faces.empty()) { face(vtxs, color); @@ -68,8 +66,7 @@ void ObjVisualization3D::faces(const std::vector& vtxs, } } -template -void ObjVisualization3D::write(const std::filesystem::path& path) const { +void ObjVisualization3D::write(const std::filesystem::path& path) const { std::ofstream os; std::filesystem::path objectpath = path; if (!objectpath.has_extension()) { @@ -89,14 +86,12 @@ void ObjVisualization3D::write(const std::filesystem::path& path) const { mtlos.close(); } -template -void ObjVisualization3D::write(std::ostream& os) const { +void ObjVisualization3D::write(std::ostream& os) const { std::stringstream sterile; write(os, sterile); } -template -void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { +void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { std::map materials; auto mixColor = [&](const Color& color) -> std::string { @@ -168,8 +163,7 @@ void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { } } -template -void ObjVisualization3D::clear() { +void ObjVisualization3D::clear() { m_vertices.clear(); m_faces.clear(); m_lines.clear(); @@ -177,3 +171,5 @@ void ObjVisualization3D::clear() { m_vertexColors.clear(); m_faceColors.clear(); } + +} // namespace Acts From 4ee20a4082680a437970251d9618117ea0544513 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 20 Sep 2024 14:10:04 +0200 Subject: [PATCH 06/24] fix: IVisualization gets virtual destructor --- Core/include/Acts/Visualization/IVisualization3D.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/include/Acts/Visualization/IVisualization3D.hpp b/Core/include/Acts/Visualization/IVisualization3D.hpp index 734ab3fe129..bf84c909d7f 100644 --- a/Core/include/Acts/Visualization/IVisualization3D.hpp +++ b/Core/include/Acts/Visualization/IVisualization3D.hpp @@ -72,6 +72,8 @@ class IVisualization3D { /// Remove all contents of this helper /// virtual void clear() = 0; + + virtual ~IVisualization3D() = default; }; /// Overload of the << operator to facilitate writing to streams. From f7c4d816bb880bcabba338d53b5fb8a32801dfec Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 17 Sep 2024 17:31:20 +0200 Subject: [PATCH 07/24] feat: (Obj)Visualization gets sub object support --- .../Acts/Visualization/IVisualization3D.hpp | 4 + .../Acts/Visualization/ObjVisualization3D.hpp | 30 +++- .../Acts/Visualization/PlyVisualization3D.hpp | 4 + Core/src/Visualization/ObjVisualization3D.cpp | 150 +++++++++++------- 4 files changed, 122 insertions(+), 66 deletions(-) diff --git a/Core/include/Acts/Visualization/IVisualization3D.hpp b/Core/include/Acts/Visualization/IVisualization3D.hpp index bf84c909d7f..be8c5b96226 100644 --- a/Core/include/Acts/Visualization/IVisualization3D.hpp +++ b/Core/include/Acts/Visualization/IVisualization3D.hpp @@ -74,6 +74,10 @@ class IVisualization3D { virtual void clear() = 0; virtual ~IVisualization3D() = default; + + /// Start a new object context + /// @param name The name of the object + virtual void object(const std::string& name) = 0; }; /// Overload of the << operator to facilitate writing to streams. diff --git a/Core/include/Acts/Visualization/ObjVisualization3D.hpp b/Core/include/Acts/Visualization/ObjVisualization3D.hpp index 1f03b558b6a..168885bfcff 100644 --- a/Core/include/Acts/Visualization/ObjVisualization3D.hpp +++ b/Core/include/Acts/Visualization/ObjVisualization3D.hpp @@ -73,18 +73,32 @@ class ObjVisualization3D : public IVisualization3D { /// @copydoc Acts::IVisualization3D::clear() void clear() final; + /// Start a new object context with a name + /// @param name The name of the object + void object(const std::string& name) final; + private: + struct Object { + std::string name; + std::vector vertices{}; + std::vector faces{}; + std::vector lines{}; + + /// The object data to be written + /// Map of colors to be written at given index position + std::map lineColors; + std::map vertexColors; + std::map faceColors; + }; + + Object& object(); + const Object& object() const; + /// The output parameters unsigned int m_outputPrecision = 4; double m_outputScalor = 1.; - /// The object data to be written - std::vector m_vertices; - std::vector m_faces; - std::vector m_lines; - /// Map of colors to be written at given index position - std::map m_lineColors; - std::map m_vertexColors; - std::map m_faceColors; + + std::vector m_objects; }; } // namespace Acts diff --git a/Core/include/Acts/Visualization/PlyVisualization3D.hpp b/Core/include/Acts/Visualization/PlyVisualization3D.hpp index e2c94481b9c..a4367dc7e02 100644 --- a/Core/include/Acts/Visualization/PlyVisualization3D.hpp +++ b/Core/include/Acts/Visualization/PlyVisualization3D.hpp @@ -60,6 +60,10 @@ class PlyVisualization3D : public IVisualization3D { /// @copydoc Acts::IVisualization3D::clear() void clear() final; + void object(const std::string& /*name*/) final { + // Unimplemented + } + private: std::vector> m_vertices; std::vector m_faces; diff --git a/Core/src/Visualization/ObjVisualization3D.cpp b/Core/src/Visualization/ObjVisualization3D.cpp index f0ac76f4145..d532adc99a1 100644 --- a/Core/src/Visualization/ObjVisualization3D.cpp +++ b/Core/src/Visualization/ObjVisualization3D.cpp @@ -8,59 +8,65 @@ #include "Acts/Visualization/ObjVisualization3D.hpp" +#include + namespace Acts { void ObjVisualization3D::vertex(const Vector3& vtx, Color color) { - m_vertexColors[m_vertices.size()] = color; - m_vertices.push_back(vtx.template cast()); + auto& o = object(); + o.vertexColors[o.vertices.size()] = color; + o.vertices.push_back(vtx.template cast()); } void ObjVisualization3D::line(const Vector3& a, const Vector3& b, Color color) { + auto& o = object(); if (color != Color{0, 0, 0}) { - m_lineColors[m_lines.size()] = color; + o.lineColors[o.lines.size()] = color; } // not implemented vertex(a, color); vertex(b, color); - m_lines.push_back({m_vertices.size() - 2, m_vertices.size() - 1}); + o.lines.push_back({o.vertices.size() - 2, o.vertices.size() - 1}); } void ObjVisualization3D::face(const std::vector& vtxs, Color color) { + auto& o = object(); if (color != Color{0, 0, 0}) { - m_faceColors[m_faces.size()] = color; + o.faceColors[o.faces.size()] = color; } FaceType idxs; idxs.reserve(vtxs.size()); for (const auto& vtx : vtxs) { vertex(vtx, color); - idxs.push_back(m_vertices.size() - 1); + idxs.push_back(o.vertices.size() - 1); } - m_faces.push_back(std::move(idxs)); + o.faces.push_back(std::move(idxs)); } void ObjVisualization3D::faces(const std::vector& vtxs, const std::vector& faces, Color color) { + auto& o = object(); // No faces given - call the face() method if (faces.empty()) { face(vtxs, color); } else { if (color != Color{0, 0, 0}) { - m_faceColors[m_faces.size()] = color; + o.faceColors[o.faces.size()] = color; } - auto vtxoffs = m_vertices.size(); + auto vtxoffs = o.vertices.size(); if (color != Color{0, 0, 0}) { - m_vertexColors[m_vertices.size()] = color; + o.vertexColors[o.vertices.size()] = color; } - m_vertices.insert(m_vertices.end(), vtxs.begin(), vtxs.end()); + o.vertices.insert(o.vertices.end(), vtxs.begin(), vtxs.end()); for (const auto& face : faces) { if (face.size() == 2) { - m_lines.push_back({face[0] + vtxoffs, face[2] + vtxoffs}); + o.lines.push_back({face[0] + vtxoffs, face[2] + vtxoffs}); } else { FaceType rawFace = face; std::transform(rawFace.begin(), rawFace.end(), rawFace.begin(), [&](std::size_t& iv) { return (iv + vtxoffs); }); - m_faces.push_back(rawFace); + o.faces.push_back(rawFace); } } } @@ -101,7 +107,7 @@ void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { materialName += std::to_string(color[1]) + std::string("_"); materialName += std::to_string(color[2]); - if (!materials.contains(materialName)) { + if (materials.find(materialName) == materials.end()) { mos << "newmtl " << materialName << "\n"; std::vector shadings = {"Ka", "Kd", "Ks"}; for (const auto& shd : shadings) { @@ -115,61 +121,89 @@ void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { return std::string("usemtl ") + materialName; }; - std::size_t iv = 0; - Color lastVertexColor = {0, 0, 0}; - for (const VertexType& vtx : m_vertices) { - if (m_vertexColors.contains(iv)) { - auto color = m_vertexColors.find(iv)->second; - if (color != lastVertexColor) { - os << mixColor(color) << "\n"; - lastVertexColor = color; - } + std::size_t vertexOffset = 0; + for (const auto& o : m_objects) { + if (!o.name.empty()) { + os << "o " << o.name << "\n"; } - os << "v " << std::setprecision(m_outputPrecision) - << m_outputScalor * vtx.x() << " " << m_outputScalor * vtx.y() << " " - << m_outputScalor * vtx.z() << "\n"; - ++iv; - } - std::size_t il = 0; - Color lastLineColor = {0, 0, 0}; - for (const LineType& ln : m_lines) { - if (m_lineColors.contains(il)) { - auto color = m_lineColors.find(il)->second; - if (color != lastLineColor) { - os << mixColor(color) << "\n"; - lastLineColor = color; + std::size_t iv = 0; + Color lastVertexColor = {0, 0, 0}; + for (const VertexType& vtx : o.vertices) { + if (o.vertexColors.find(iv) != o.vertexColors.end()) { + auto color = o.vertexColors.find(iv)->second; + if (color != lastVertexColor) { + os << mixColor(color) << "\n"; + lastVertexColor = color; + } } + + os << "v " << std::setprecision(m_outputPrecision) + << m_outputScalor * vtx.x() << " " << m_outputScalor * vtx.y() << " " + << m_outputScalor * vtx.z() << "\n"; + ++iv; } - os << "l " << ln.first + 1 << " " << ln.second + 1 << "\n"; - ++il; - } - std::size_t is = 0; - Color lastFaceColor = {0, 0, 0}; - for (const FaceType& fc : m_faces) { - if (m_faceColors.contains(is)) { - auto color = m_faceColors.find(is)->second; - if (color != lastFaceColor) { - os << mixColor(color) << "\n"; - lastFaceColor = color; + std::size_t il = 0; + Color lastLineColor = {0, 0, 0}; + for (const LineType& ln : o.lines) { + if (o.lineColors.find(il) != o.lineColors.end()) { + auto color = o.lineColors.find(il)->second; + if (color != lastLineColor) { + os << mixColor(color) << "\n"; + lastLineColor = color; + } } + os << "l " << vertexOffset + ln.first + 1 << " " + << vertexOffset + ln.second + 1 << "\n"; + ++il; } - os << "f"; - for (std::size_t i = 0; i < fc.size(); i++) { - os << " " << fc[i] + 1; + std::size_t is = 0; + Color lastFaceColor = {0, 0, 0}; + for (const FaceType& fc : o.faces) { + if (o.faceColors.find(is) != o.faceColors.end()) { + auto color = o.faceColors.find(is)->second; + if (color != lastFaceColor) { + os << mixColor(color) << "\n"; + lastFaceColor = color; + } + } + os << "f"; + for (std::size_t i = 0; i < fc.size(); i++) { + os << " " << vertexOffset + fc[i] + 1; + } + os << "\n"; + ++is; } - os << "\n"; - ++is; + + vertexOffset += iv; } } void ObjVisualization3D::clear() { - m_vertices.clear(); - m_faces.clear(); - m_lines.clear(); - m_lineColors.clear(); - m_vertexColors.clear(); - m_faceColors.clear(); + m_objects.clear(); +} + +void ObjVisualization3D::object(const std::string& name) { + if (name.empty()) { + throw std::invalid_argument{"Object name can not be empty"}; + } + m_objects.push_back(Object{.name = name}); +} + +ObjVisualization3D::Object& ObjVisualization3D::object() { + if (m_objects.empty()) { + m_objects.push_back(Object{.name = ""}); + } + + return m_objects.back(); +} + +const ObjVisualization3D::Object& ObjVisualization3D::object() const { + if (m_objects.empty()) { + throw std::runtime_error{"No objects present"}; + } + + return m_objects.back(); } } // namespace Acts From 261703a6529edb06d14702988ec5dbef1c19316d Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 1 Oct 2024 10:09:48 +0200 Subject: [PATCH 08/24] refactor(util): Locate default visualization colors with ViewConfig struct --- Core/include/Acts/Visualization/GeometryView3D.hpp | 6 ------ Core/include/Acts/Visualization/ViewConfig.hpp | 8 ++++++++ Core/src/Visualization/GeometryView3D.cpp | 10 ---------- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Core/include/Acts/Visualization/GeometryView3D.hpp b/Core/include/Acts/Visualization/GeometryView3D.hpp index 05053de31ef..fed07697a87 100644 --- a/Core/include/Acts/Visualization/GeometryView3D.hpp +++ b/Core/include/Acts/Visualization/GeometryView3D.hpp @@ -31,12 +31,6 @@ class DetectorVolume; class Portal; } // namespace Experimental -static const ViewConfig s_viewSensitive; -static const ViewConfig s_viewPassive; -static const ViewConfig s_viewVolume; -static const ViewConfig s_viewGrid; -static const ViewConfig s_viewLine; - struct GeometryView3D { /// Helper method to draw Polyhedron objects /// diff --git a/Core/include/Acts/Visualization/ViewConfig.hpp b/Core/include/Acts/Visualization/ViewConfig.hpp index 98a96d89f5b..4267407e0ac 100644 --- a/Core/include/Acts/Visualization/ViewConfig.hpp +++ b/Core/include/Acts/Visualization/ViewConfig.hpp @@ -119,4 +119,12 @@ struct ViewConfig { std::filesystem::path outputName = std::filesystem::path(""); }; +static const ViewConfig s_viewSurface = {.color{170, 170, 170}}; +static const ViewConfig s_viewPortal = {.color{"#308c48"}}; +static const ViewConfig s_viewSensitive = {.color = {0, 180, 240}}; +static const ViewConfig s_viewPassive = {.color = {240, 280, 0}}; +static const ViewConfig s_viewVolume = {.color = {220, 220, 0}}; +static const ViewConfig s_viewGrid = {.color = {220, 0, 0}}; +static const ViewConfig s_viewLine = {.color = {0, 0, 220}}; + } // namespace Acts diff --git a/Core/src/Visualization/GeometryView3D.cpp b/Core/src/Visualization/GeometryView3D.cpp index e0a7c52a5a7..6c536841b3e 100644 --- a/Core/src/Visualization/GeometryView3D.cpp +++ b/Core/src/Visualization/GeometryView3D.cpp @@ -26,7 +26,6 @@ #include "Acts/Surfaces/RadialBounds.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Surfaces/SurfaceArray.hpp" -#include "Acts/Utilities/BinnedArray.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/IAxis.hpp" #include "Acts/Utilities/UnitVectors.hpp" @@ -36,18 +35,9 @@ #include #include #include -#include #include #include -namespace Acts::Experimental { -ViewConfig s_viewSensitive = {.color = {0, 180, 240}}; -ViewConfig s_viewPassive = {.color = {240, 280, 0}}; -ViewConfig s_viewVolume = {.color = {220, 220, 0}}; -ViewConfig s_viewGrid = {.color = {220, 0, 0}}; -ViewConfig s_viewLine = {.color = {0, 0, 220}}; -} // namespace Acts::Experimental - void Acts::GeometryView3D::drawPolyhedron(IVisualization3D& helper, const Polyhedron& polyhedron, const ViewConfig& viewConfig) { From 762d968e4113a35ad329b74eba3853fdf77d2be9 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 20 Sep 2024 14:14:50 +0200 Subject: [PATCH 09/24] feat: python bindings for visualization writing --- Examples/Python/src/Obj.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Examples/Python/src/Obj.cpp b/Examples/Python/src/Obj.cpp index 46c6ec55ed4..1b030a96138 100644 --- a/Examples/Python/src/Obj.cpp +++ b/Examples/Python/src/Obj.cpp @@ -6,6 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. +#include "Acts/Visualization/IVisualization3D.hpp" #include #include #include @@ -107,5 +108,15 @@ void addObj(Context& ctx) { obj.write(fileName); }); } + + py::class_(m, "IVisualization3D") + .def("write", py::overload_cast( + &IVisualization3D::write, py::const_)); + + py::class_, IVisualization3D>(m, + "ObjVisualization3D") + .def(py::init<>()) + .def("write", py::overload_cast( + &ObjVisualization3D::write, py::const_)); } } // namespace Acts::Python From 66a74ec2f4c125755dc8c18ed428fe7790859b23 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 20 Sep 2024 11:43:16 +0200 Subject: [PATCH 10/24] feat(geo): Add visualization method to Tracking{Volume,Geometry} --- Core/include/Acts/Geometry/TrackingGeometry.hpp | 9 +++++++++ Core/include/Acts/Geometry/TrackingVolume.hpp | 9 +++++++++ Core/src/Geometry/TrackingGeometry.cpp | 7 +++++++ Core/src/Geometry/TrackingVolume.cpp | 12 ++++++++++++ 4 files changed, 37 insertions(+) diff --git a/Core/include/Acts/Geometry/TrackingGeometry.hpp b/Core/include/Acts/Geometry/TrackingGeometry.hpp index b0ac658eecd..ae96ebb632d 100644 --- a/Core/include/Acts/Geometry/TrackingGeometry.hpp +++ b/Core/include/Acts/Geometry/TrackingGeometry.hpp @@ -145,6 +145,15 @@ class TrackingGeometry { const std::unordered_map& geoIdSurfaceMap() const; + /// Visualize a tracking geometry including substructure + /// @param helper The visualization helper that implement the output + /// @param gctx The geometry context + /// @param viewConfig Global view config + /// @param portalViewConfig View config for portals + void visualize(IVisualization3D& helper, const GeometryContext& gctx, + const ViewConfig& viewConfig = {}, + const ViewConfig& portalViewConfig = {}) const; + private: // the known world std::shared_ptr m_world; diff --git a/Core/include/Acts/Geometry/TrackingVolume.hpp b/Core/include/Acts/Geometry/TrackingVolume.hpp index b208eefa54b..2568ef0d191 100644 --- a/Core/include/Acts/Geometry/TrackingVolume.hpp +++ b/Core/include/Acts/Geometry/TrackingVolume.hpp @@ -473,6 +473,15 @@ class TrackingVolume : public Volume { /// - positiveFaceXY GlueVolumesDescriptor& glueVolumesDescriptor(); + /// Produces a 3D visualization of this tracking volume + /// @param helper The visualization helper describing the output format + /// @param gctx The geometry context + /// @param viewConfig The view configuration + void visualize(IVisualization3D& helper, const GeometryContext& gctx, + const ViewConfig& viewConfig = {}, + const ViewConfig& portalViewConfig = { + .color{"#308c48"}}) const; + private: void connectDenseBoundarySurfaces( MutableTrackingVolumeVector& confinedDenseVolumes); diff --git a/Core/src/Geometry/TrackingGeometry.cpp b/Core/src/Geometry/TrackingGeometry.cpp index b68d788d08b..e209f644b5a 100644 --- a/Core/src/Geometry/TrackingGeometry.cpp +++ b/Core/src/Geometry/TrackingGeometry.cpp @@ -85,3 +85,10 @@ const std::unordered_map& Acts::TrackingGeometry::geoIdSurfaceMap() const { return m_surfacesById; } + +void Acts::TrackingGeometry::visualize( + IVisualization3D& helper, const GeometryContext& gctx, + const ViewConfig& viewConfig, const ViewConfig& portalViewConfig) const { + highestTrackingVolume()->visualize(helper, gctx, viewConfig, + portalViewConfig); +} diff --git a/Core/src/Geometry/TrackingVolume.cpp b/Core/src/Geometry/TrackingVolume.cpp index 79ffdc9d180..c4b4f7e9755 100644 --- a/Core/src/Geometry/TrackingVolume.cpp +++ b/Core/src/Geometry/TrackingVolume.cpp @@ -684,4 +684,16 @@ void TrackingVolume::addSurface(std::shared_ptr surface) { m_surfaces.push_back(std::move(surface)); } +void TrackingVolume::visualize(IVisualization3D& helper, + const GeometryContext& gctx, + const ViewConfig& viewConfig, + const ViewConfig& portalViewConfig) const { + helper.object(volumeName()); + Volume::visualize(helper, gctx, viewConfig); + + for (const auto& child : volumes()) { + child.visualize(helper, gctx, viewConfig, portalViewConfig); + } +} + } // namespace Acts From 48c3011768e0457ebab735b5eb5db52c3c7abf44 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 1 Oct 2024 10:00:07 +0200 Subject: [PATCH 11/24] refactor(util): Make Color hex construction actually constexpr --- .../include/Acts/Visualization/ViewConfig.hpp | 25 ++++++++++++++++--- .../Visualization/Visualization3DTests.cpp | 2 ++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Core/include/Acts/Visualization/ViewConfig.hpp b/Core/include/Acts/Visualization/ViewConfig.hpp index 4267407e0ac..2714cbb925b 100644 --- a/Core/include/Acts/Visualization/ViewConfig.hpp +++ b/Core/include/Acts/Visualization/ViewConfig.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace Acts { @@ -52,11 +53,23 @@ struct Color { /// Constructor from hex string. The expected format is `#RRGGBB` /// @param hex The hex string constexpr explicit Color(std::string_view hex) { - auto hexToInt = [](std::string_view hexStr) { + constexpr auto hexToInt = [](std::string_view hex) -> int { + constexpr auto hexCharToInt = [](char c) -> int { + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } else { + throw std::invalid_argument("Invalid hex character"); + } + }; + int value = 0; - std::stringstream ss; - ss << std::hex << hexStr; - ss >> value; + for (char c : hex) { + value = (value << 4) + hexCharToInt(c); + } return value; }; @@ -98,6 +111,10 @@ struct Color { std::array rgb{}; }; +constexpr Color s_defaultSurfaceColor{"#0000aa"}; +constexpr Color s_defaultPortalColor{"#308c48"}; +constexpr Color s_defaultVolumColor{"#ffaa00"}; + /// @brief Struct to concentrate all visualization configurations /// in order to harmonize visualization interfaces struct ViewConfig { diff --git a/Tests/UnitTests/Core/Visualization/Visualization3DTests.cpp b/Tests/UnitTests/Core/Visualization/Visualization3DTests.cpp index 58958bbbe6c..ea3e810d119 100644 --- a/Tests/UnitTests/Core/Visualization/Visualization3DTests.cpp +++ b/Tests/UnitTests/Core/Visualization/Visualization3DTests.cpp @@ -335,6 +335,8 @@ BOOST_AUTO_TEST_CASE(ColorTests) { BOOST_CHECK_EQUAL(grey, Color(std::array{128 / 255.0, 128 / 255.0, 128 / 255.0})); BOOST_CHECK_EQUAL(grey, Color(128 / 255.0, 128 / 255.0, 128 / 255.0)); + + static_assert(Color{"#0000ff"} == Color(0, 0, 255)); } BOOST_AUTO_TEST_SUITE_END() From caccbfcdf224588e6dac7832b7200b1315ec17b8 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 20 Sep 2024 14:13:17 +0200 Subject: [PATCH 12/24] fix: Obj python bindings filsystem update --- Examples/Python/src/Obj.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/Python/src/Obj.cpp b/Examples/Python/src/Obj.cpp index 1b030a96138..87bcad8900d 100644 --- a/Examples/Python/src/Obj.cpp +++ b/Examples/Python/src/Obj.cpp @@ -110,13 +110,13 @@ void addObj(Context& ctx) { } py::class_(m, "IVisualization3D") - .def("write", py::overload_cast( + .def("write", py::overload_cast( &IVisualization3D::write, py::const_)); py::class_, IVisualization3D>(m, "ObjVisualization3D") .def(py::init<>()) - .def("write", py::overload_cast( + .def("write", py::overload_cast( &ObjVisualization3D::write, py::const_)); } } // namespace Acts::Python From b5a90d3d8dcf1554f736bbd772961b561b342f11 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 20 Sep 2024 11:59:48 +0200 Subject: [PATCH 13/24] fix: Obj python bindings --- Examples/Python/src/Obj.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Examples/Python/src/Obj.cpp b/Examples/Python/src/Obj.cpp index 87bcad8900d..1a5a7cc8cb1 100644 --- a/Examples/Python/src/Obj.cpp +++ b/Examples/Python/src/Obj.cpp @@ -113,10 +113,9 @@ void addObj(Context& ctx) { .def("write", py::overload_cast( &IVisualization3D::write, py::const_)); - py::class_, IVisualization3D>(m, - "ObjVisualization3D") + py::class_(m, "ObjVisualization3D") .def(py::init<>()) .def("write", py::overload_cast( - &ObjVisualization3D::write, py::const_)); + &ObjVisualization3D::write, py::const_)); } } // namespace Acts::Python From 45c9487d0d5c7948659e61c490445b14e630a4d9 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 20 Sep 2024 12:04:05 +0200 Subject: [PATCH 14/24] refactor: Geometry python binding improvements --- Examples/Python/src/Geometry.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Examples/Python/src/Geometry.cpp b/Examples/Python/src/Geometry.cpp index 4fb0f07d07a..b205ab073c1 100644 --- a/Examples/Python/src/Geometry.cpp +++ b/Examples/Python/src/Geometry.cpp @@ -109,13 +109,12 @@ void addGeometry(Context& ctx) { { py::class_>(m, "Surface") + // Can't bind directly because GeometryObject is virtual base of Surface .def("geometryId", - [](Acts::Surface& self) { return self.geometryId(); }) - .def("center", - [](Acts::Surface& self) { - return self.center(Acts::GeometryContext{}); - }) - .def("type", [](Acts::Surface& self) { return self.type(); }); + [](const Surface& self) { return self.geometryId(); }) + .def("center", &Surface::center) + .def("type", &Surface::type) + .def("visualize", &Surface::visualize); } { @@ -287,7 +286,7 @@ void addExperimentalGeometry(Context& ctx) { for (const auto& surface : smap) { auto gid = surface->geometryId(); // Exclusion criteria - if (sensitiveOnly and gid.sensitive() == 0) { + if (sensitiveOnly && gid.sensitive() == 0) { continue; }; surfaceVolumeLayerMap[gid.volume()][gid.layer()].push_back(surface); From fe02d824730d6d2ab426a97340d623adf0679316 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 1 Oct 2024 10:23:51 +0200 Subject: [PATCH 15/24] feat(geo): Visualize surface, use view config default colors --- Core/include/Acts/Geometry/TrackingGeometry.hpp | 6 ++++-- Core/include/Acts/Geometry/TrackingVolume.hpp | 9 ++++++--- Core/include/Acts/Surfaces/Surface.hpp | 2 +- Core/src/Geometry/TrackingGeometry.cpp | 7 ++++--- Core/src/Geometry/TrackingVolume.cpp | 7 ++++++- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Core/include/Acts/Geometry/TrackingGeometry.hpp b/Core/include/Acts/Geometry/TrackingGeometry.hpp index ae96ebb632d..e8d48c5ae5e 100644 --- a/Core/include/Acts/Geometry/TrackingGeometry.hpp +++ b/Core/include/Acts/Geometry/TrackingGeometry.hpp @@ -150,9 +150,11 @@ class TrackingGeometry { /// @param gctx The geometry context /// @param viewConfig Global view config /// @param portalViewConfig View config for portals + /// @param sensitiveViewConfig View configuration for sensitive surfaces void visualize(IVisualization3D& helper, const GeometryContext& gctx, - const ViewConfig& viewConfig = {}, - const ViewConfig& portalViewConfig = {}) const; + const ViewConfig& viewConfig = s_viewVolume, + const ViewConfig& portalViewConfig = s_viewPortal, + const ViewConfig& sensitiveViewConfig = s_viewSensitive) const; private: // the known world diff --git a/Core/include/Acts/Geometry/TrackingVolume.hpp b/Core/include/Acts/Geometry/TrackingVolume.hpp index 2568ef0d191..2f1461cbe70 100644 --- a/Core/include/Acts/Geometry/TrackingVolume.hpp +++ b/Core/include/Acts/Geometry/TrackingVolume.hpp @@ -25,6 +25,7 @@ #include "Acts/Utilities/BinnedArray.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/TransformRange.hpp" +#include "Acts/Visualization/ViewConfig.hpp" #include #include @@ -477,10 +478,12 @@ class TrackingVolume : public Volume { /// @param helper The visualization helper describing the output format /// @param gctx The geometry context /// @param viewConfig The view configuration + /// @param portalViewConfig View configuration for portals + /// @param sensitiveViewConfig View configuration for sensitive surfaces void visualize(IVisualization3D& helper, const GeometryContext& gctx, - const ViewConfig& viewConfig = {}, - const ViewConfig& portalViewConfig = { - .color{"#308c48"}}) const; + const ViewConfig& viewConfig = s_viewVolume, + const ViewConfig& portalViewConfig = s_viewPortal, + const ViewConfig& sensitiveViewConfig = s_viewSensitive) const; private: void connectDenseBoundarySurfaces( diff --git a/Core/include/Acts/Surfaces/Surface.hpp b/Core/include/Acts/Surfaces/Surface.hpp index c93e7d3c9aa..cc1dd635474 100644 --- a/Core/include/Acts/Surfaces/Surface.hpp +++ b/Core/include/Acts/Surfaces/Surface.hpp @@ -481,7 +481,7 @@ class Surface : public virtual GeometryObject, const GeometryContext& gctx, const Vector3& position) const = 0; void visualize(IVisualization3D& helper, const GeometryContext& gctx, - const ViewConfig& viewConfig = {}) const; + const ViewConfig& viewConfig = s_viewSurface) const; protected: /// Output Method for std::ostream, to be overloaded by child classes diff --git a/Core/src/Geometry/TrackingGeometry.cpp b/Core/src/Geometry/TrackingGeometry.cpp index e209f644b5a..f9207afbd18 100644 --- a/Core/src/Geometry/TrackingGeometry.cpp +++ b/Core/src/Geometry/TrackingGeometry.cpp @@ -88,7 +88,8 @@ Acts::TrackingGeometry::geoIdSurfaceMap() const { void Acts::TrackingGeometry::visualize( IVisualization3D& helper, const GeometryContext& gctx, - const ViewConfig& viewConfig, const ViewConfig& portalViewConfig) const { - highestTrackingVolume()->visualize(helper, gctx, viewConfig, - portalViewConfig); + const ViewConfig& viewConfig, const ViewConfig& portalViewConfig, + const ViewConfig& sensitiveViewConfig) const { + highestTrackingVolume()->visualize(helper, gctx, viewConfig, portalViewConfig, + sensitiveViewConfig); } diff --git a/Core/src/Geometry/TrackingVolume.cpp b/Core/src/Geometry/TrackingVolume.cpp index c4b4f7e9755..d15821295d2 100644 --- a/Core/src/Geometry/TrackingVolume.cpp +++ b/Core/src/Geometry/TrackingVolume.cpp @@ -687,10 +687,15 @@ void TrackingVolume::addSurface(std::shared_ptr surface) { void TrackingVolume::visualize(IVisualization3D& helper, const GeometryContext& gctx, const ViewConfig& viewConfig, - const ViewConfig& portalViewConfig) const { + const ViewConfig& portalViewConfig, + const ViewConfig& sensitiveViewConfig) const { helper.object(volumeName()); Volume::visualize(helper, gctx, viewConfig); + for (const auto& surface : surfaces()) { + surface.visualize(helper, gctx, sensitiveViewConfig); + } + for (const auto& child : volumes()) { child.visualize(helper, gctx, viewConfig, portalViewConfig); } From fb91bc6ff3fd78f2d5d684ef5f2df8b519de7a27 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 11:29:42 +0200 Subject: [PATCH 16/24] remove some unused headers --- Core/include/Acts/Visualization/ObjVisualization3D.hpp | 4 ---- Core/src/Visualization/ObjVisualization3D.cpp | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Core/include/Acts/Visualization/ObjVisualization3D.hpp b/Core/include/Acts/Visualization/ObjVisualization3D.hpp index 168885bfcff..6cba2139da1 100644 --- a/Core/include/Acts/Visualization/ObjVisualization3D.hpp +++ b/Core/include/Acts/Visualization/ObjVisualization3D.hpp @@ -12,12 +12,8 @@ #include "Acts/Visualization/IVisualization3D.hpp" #include "Acts/Visualization/ViewConfig.hpp" -#include #include -#include -#include #include -#include #include #include diff --git a/Core/src/Visualization/ObjVisualization3D.cpp b/Core/src/Visualization/ObjVisualization3D.cpp index d532adc99a1..e2cdc8fdba6 100644 --- a/Core/src/Visualization/ObjVisualization3D.cpp +++ b/Core/src/Visualization/ObjVisualization3D.cpp @@ -8,6 +8,7 @@ #include "Acts/Visualization/ObjVisualization3D.hpp" +#include #include namespace Acts { From e4ff9b24d221f92154e7ab5e2077bc181ab100e4 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 11:29:58 +0200 Subject: [PATCH 17/24] fix warning related to missing initalizer --- Core/include/Acts/Visualization/ObjVisualization3D.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/include/Acts/Visualization/ObjVisualization3D.hpp b/Core/include/Acts/Visualization/ObjVisualization3D.hpp index 6cba2139da1..a9f496ce304 100644 --- a/Core/include/Acts/Visualization/ObjVisualization3D.hpp +++ b/Core/include/Acts/Visualization/ObjVisualization3D.hpp @@ -82,9 +82,9 @@ class ObjVisualization3D : public IVisualization3D { /// The object data to be written /// Map of colors to be written at given index position - std::map lineColors; - std::map vertexColors; - std::map faceColors; + std::map lineColors{}; + std::map vertexColors{}; + std::map faceColors{}; }; Object& object(); From 007a85462d0010154b8ea77502b8fd5eae15d472 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 11:36:34 +0200 Subject: [PATCH 18/24] move hex function --- .../include/Acts/Visualization/ViewConfig.hpp | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/Core/include/Acts/Visualization/ViewConfig.hpp b/Core/include/Acts/Visualization/ViewConfig.hpp index 2714cbb925b..c2f85716c43 100644 --- a/Core/include/Acts/Visualization/ViewConfig.hpp +++ b/Core/include/Acts/Visualization/ViewConfig.hpp @@ -10,8 +10,7 @@ #include #include -#include -#include +#include namespace Acts { @@ -50,29 +49,31 @@ struct Color { constexpr Color(double r, double g, double b) : Color{std::array{r, g, b}} {} - /// Constructor from hex string. The expected format is `#RRGGBB` - /// @param hex The hex string - constexpr explicit Color(std::string_view hex) { - constexpr auto hexToInt = [](std::string_view hex) -> int { - constexpr auto hexCharToInt = [](char c) -> int { - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c >= 'a' && c <= 'f') { - return c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - return c - 'A' + 10; - } else { - throw std::invalid_argument("Invalid hex character"); - } - }; - - int value = 0; - for (char c : hex) { - value = (value << 4) + hexCharToInt(c); + private: + constexpr int hexToInt(std::string_view hex) { + constexpr auto hexCharToInt = [](char c) -> int { + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } else { + throw std::invalid_argument("Invalid hex character"); } - return value; }; + int value = 0; + for (char c : hex) { + value = (value << 4) + hexCharToInt(c); + } + return value; + }; + + public: + /// Constructor from hex string. The expected format is `#RRGGBB` + /// @param hex The hex string + constexpr Color(std::string_view hex) { if (hex[0] == '#' && hex.size() == 7) { rgb[0] = hexToInt(hex.substr(1, 2)); // Extract R component rgb[1] = hexToInt(hex.substr(3, 2)); // Extract G component @@ -136,8 +137,8 @@ struct ViewConfig { std::filesystem::path outputName = std::filesystem::path(""); }; -static const ViewConfig s_viewSurface = {.color{170, 170, 170}}; -static const ViewConfig s_viewPortal = {.color{"#308c48"}}; +static const ViewConfig s_viewSurface = {.color = {170, 170, 170}}; +static const ViewConfig s_viewPortal = {.color = {"#308c48"}}; static const ViewConfig s_viewSensitive = {.color = {0, 180, 240}}; static const ViewConfig s_viewPassive = {.color = {240, 280, 0}}; static const ViewConfig s_viewVolume = {.color = {220, 220, 0}}; From 542e5e4cee093c6219270d92eb6f28d59c78d0d3 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 11:40:46 +0200 Subject: [PATCH 19/24] obj: separate objects for sensitives and portals --- Core/src/Geometry/TrackingVolume.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/src/Geometry/TrackingVolume.cpp b/Core/src/Geometry/TrackingVolume.cpp index d15821295d2..855064f21a1 100644 --- a/Core/src/Geometry/TrackingVolume.cpp +++ b/Core/src/Geometry/TrackingVolume.cpp @@ -692,6 +692,9 @@ void TrackingVolume::visualize(IVisualization3D& helper, helper.object(volumeName()); Volume::visualize(helper, gctx, viewConfig); + if (!surfaces().empty()) { + helper.object(volumeName() + "_sensitives"); + } for (const auto& surface : surfaces()) { surface.visualize(helper, gctx, sensitiveViewConfig); } From 2d34cbf13b30d741bf761ee3e43fbed30d6a1a66 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 13:46:18 +0200 Subject: [PATCH 20/24] fix overlapping view config bindings --- Examples/Python/src/Obj.cpp | 19 ------------------- Examples/Python/src/Output.cpp | 2 +- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/Examples/Python/src/Obj.cpp b/Examples/Python/src/Obj.cpp index 1a5a7cc8cb1..0a9771403aa 100644 --- a/Examples/Python/src/Obj.cpp +++ b/Examples/Python/src/Obj.cpp @@ -31,25 +31,6 @@ namespace Acts::Python { void addObj(Context& ctx) { auto [m, mex] = ctx.get("main", "examples"); - { - py::class_(m, "ViewConfig") - .def_readwrite("visible", &ViewConfig::visible) - .def_readwrite("color", &ViewConfig::color) - .def_readwrite("offset", &ViewConfig::offset) - .def_readwrite("lineThickness", &ViewConfig::lineThickness) - .def_readwrite("surfaceThickness", &ViewConfig::surfaceThickness) - .def_readwrite("nSegments", &ViewConfig::nSegments) - .def_readwrite("triangulate", &ViewConfig::triangulate) - .def_readwrite("outputName", &ViewConfig::outputName); - - py::class_(m, "Color") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def(py::init()) - .def_readonly("rgb", &Color::rgb); - } - { /// Write a collection of surfaces to an '.obj' file /// diff --git a/Examples/Python/src/Output.cpp b/Examples/Python/src/Output.cpp index 328ae9ecd92..17a5b32c177 100644 --- a/Examples/Python/src/Output.cpp +++ b/Examples/Python/src/Output.cpp @@ -130,7 +130,7 @@ void addOutput(Context& ctx) { .def(py::init<>()) .def(py::init()) .def(py::init()) - .def(py::init()) + .def(py::init()) .def_readonly("rgb", &Color::rgb); } From f2257f444e2c19bb7a9341f0f4b771c861c5e180 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 15:45:39 +0200 Subject: [PATCH 21/24] feat(geo): Visualization python bindings update --- Examples/Python/src/Geometry.cpp | 7 ++++++- Examples/Python/src/ModuleEntry.cpp | 2 +- Examples/Python/src/Obj.cpp | 8 +------- Examples/Python/src/Output.cpp | 8 ++++++++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Examples/Python/src/Geometry.cpp b/Examples/Python/src/Geometry.cpp index b205ab073c1..aa497e29a6f 100644 --- a/Examples/Python/src/Geometry.cpp +++ b/Examples/Python/src/Geometry.cpp @@ -37,6 +37,7 @@ #include "Acts/Surfaces/SurfaceArray.hpp" #include "Acts/Utilities/Helpers.hpp" #include "Acts/Utilities/RangeXD.hpp" +#include "Acts/Visualization/ViewConfig.hpp" #include "ActsExamples/Geometry/VolumeAssociationTest.hpp" #include @@ -166,7 +167,11 @@ void addGeometry(Context& ctx) { }) .def_property_readonly( "highestTrackingVolume", - &Acts::TrackingGeometry::highestTrackingVolumePtr); + &Acts::TrackingGeometry::highestTrackingVolumePtr) + .def("visualize", &Acts::TrackingGeometry::visualize, py::arg("helper"), + py::arg("gctx"), py::arg("viewConfig") = s_viewVolume, + py::arg("portalViewConfig") = s_viewPortal, + py::arg("sensitiveViewConfig") = s_viewSensitive); } { diff --git a/Examples/Python/src/ModuleEntry.cpp b/Examples/Python/src/ModuleEntry.cpp index 77348edaf1c..1a0e27db907 100644 --- a/Examples/Python/src/ModuleEntry.cpp +++ b/Examples/Python/src/ModuleEntry.cpp @@ -120,6 +120,7 @@ PYBIND11_MODULE(ActsPythonBindings, m) { addAlgebra(ctx); addBinning(ctx); addEventData(ctx); + addOutput(ctx); addPropagation(ctx); addGeometryBuildingGen1(ctx); @@ -128,7 +129,6 @@ PYBIND11_MODULE(ActsPythonBindings, m) { addMagneticField(ctx); addMaterial(ctx); - addOutput(ctx); addDetector(ctx); addExampleAlgorithms(ctx); addInput(ctx); diff --git a/Examples/Python/src/Obj.cpp b/Examples/Python/src/Obj.cpp index 0a9771403aa..6030c116a71 100644 --- a/Examples/Python/src/Obj.cpp +++ b/Examples/Python/src/Obj.cpp @@ -90,13 +90,7 @@ void addObj(Context& ctx) { }); } - py::class_(m, "IVisualization3D") - .def("write", py::overload_cast( - &IVisualization3D::write, py::const_)); - py::class_(m, "ObjVisualization3D") - .def(py::init<>()) - .def("write", py::overload_cast( - &ObjVisualization3D::write, py::const_)); + .def(py::init<>()); } } // namespace Acts::Python diff --git a/Examples/Python/src/Output.cpp b/Examples/Python/src/Output.cpp index 17a5b32c177..3879b05220e 100644 --- a/Examples/Python/src/Output.cpp +++ b/Examples/Python/src/Output.cpp @@ -10,6 +10,7 @@ #include "Acts/Geometry/GeometryHierarchyMap.hpp" #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Utilities/Logger.hpp" +#include "Acts/Visualization/IVisualization3D.hpp" #include "Acts/Visualization/ViewConfig.hpp" #include "ActsExamples/Digitization/DigitizationConfig.hpp" #include "ActsExamples/Framework/ProcessCode.hpp" @@ -134,6 +135,13 @@ void addOutput(Context& ctx) { .def_readonly("rgb", &Color::rgb); } + py::class_(m, "IVisualization3D") + .def("write", [](const IVisualization3D& self, const py::object& arg) { + std::stringstream ss; + self.write(ss); + arg.attr("write")(ss.str()); + }); + { using Writer = ActsExamples::ObjTrackingGeometryWriter; auto w = py::class_>( From 714729f53f6c6dca83cf2a49d04270c02702d364 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 15:53:22 +0200 Subject: [PATCH 22/24] adapt to center interface --- Examples/Python/python/acts/examples/odd.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Examples/Python/python/acts/examples/odd.py b/Examples/Python/python/acts/examples/odd.py index 4e1efb1c783..a28058af78b 100644 --- a/Examples/Python/python/acts/examples/odd.py +++ b/Examples/Python/python/acts/examples/odd.py @@ -76,8 +76,9 @@ def getOpenDataDetector( } def geoid_hook(geoid, surface): + gctx = acts.GeometryContext() if geoid.volume() in volumeRadiusCutsMap: - r = math.sqrt(surface.center()[0] ** 2 + surface.center()[1] ** 2) + r = math.sqrt(surface.center(gctx)[0] ** 2 + surface.center(gctx)[1] ** 2) geoid.setExtra(1) for cut in volumeRadiusCutsMap[geoid.volume()]: From d3116437938d8f1c6a3fbfa7b833af595535ae0d Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 17:27:50 +0200 Subject: [PATCH 23/24] sonar fixes --- Core/include/Acts/Geometry/TrackingVolume.hpp | 6 ++-- Core/include/Acts/Geometry/Volume.hpp | 2 +- .../include/Acts/Visualization/ViewConfig.hpp | 8 ++--- Core/src/Geometry/TrackingVolume.cpp | 3 +- Core/src/Visualization/ObjVisualization3D.cpp | 33 ++++++++++--------- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/Core/include/Acts/Geometry/TrackingVolume.hpp b/Core/include/Acts/Geometry/TrackingVolume.hpp index 2f1461cbe70..a65edbd74ae 100644 --- a/Core/include/Acts/Geometry/TrackingVolume.hpp +++ b/Core/include/Acts/Geometry/TrackingVolume.hpp @@ -481,9 +481,9 @@ class TrackingVolume : public Volume { /// @param portalViewConfig View configuration for portals /// @param sensitiveViewConfig View configuration for sensitive surfaces void visualize(IVisualization3D& helper, const GeometryContext& gctx, - const ViewConfig& viewConfig = s_viewVolume, - const ViewConfig& portalViewConfig = s_viewPortal, - const ViewConfig& sensitiveViewConfig = s_viewSensitive) const; + const ViewConfig& viewConfig, + const ViewConfig& portalViewConfig, + const ViewConfig& sensitiveViewConfig) const; private: void connectDenseBoundarySurfaces( diff --git a/Core/include/Acts/Geometry/Volume.hpp b/Core/include/Acts/Geometry/Volume.hpp index a59451efe09..9217e758444 100644 --- a/Core/include/Acts/Geometry/Volume.hpp +++ b/Core/include/Acts/Geometry/Volume.hpp @@ -122,7 +122,7 @@ class Volume : public GeometryObject { /// @param gctx The geometry context /// @param viewConfig The view configuration void visualize(IVisualization3D& helper, const GeometryContext& gctx, - const ViewConfig& viewConfig = {}) const; + const ViewConfig& viewConfig) const; protected: Transform3 m_transform; diff --git a/Core/include/Acts/Visualization/ViewConfig.hpp b/Core/include/Acts/Visualization/ViewConfig.hpp index c2f85716c43..8228e89a0fe 100644 --- a/Core/include/Acts/Visualization/ViewConfig.hpp +++ b/Core/include/Acts/Visualization/ViewConfig.hpp @@ -50,8 +50,8 @@ struct Color { : Color{std::array{r, g, b}} {} private: - constexpr int hexToInt(std::string_view hex) { - constexpr auto hexCharToInt = [](char c) -> int { + constexpr static int hexToInt(std::string_view hex) { + constexpr auto hexCharToInt = [](char c) { if (c >= '0' && c <= '9') { return c - '0'; } else if (c >= 'a' && c <= 'f') { @@ -73,7 +73,7 @@ struct Color { public: /// Constructor from hex string. The expected format is `#RRGGBB` /// @param hex The hex string - constexpr Color(std::string_view hex) { + constexpr explicit Color(std::string_view hex) { if (hex[0] == '#' && hex.size() == 7) { rgb[0] = hexToInt(hex.substr(1, 2)); // Extract R component rgb[1] = hexToInt(hex.substr(3, 2)); // Extract G component @@ -138,7 +138,7 @@ struct ViewConfig { }; static const ViewConfig s_viewSurface = {.color = {170, 170, 170}}; -static const ViewConfig s_viewPortal = {.color = {"#308c48"}}; +static const ViewConfig s_viewPortal = {.color = Color{"#308c48"}}; static const ViewConfig s_viewSensitive = {.color = {0, 180, 240}}; static const ViewConfig s_viewPassive = {.color = {240, 280, 0}}; static const ViewConfig s_viewVolume = {.color = {220, 220, 0}}; diff --git a/Core/src/Geometry/TrackingVolume.cpp b/Core/src/Geometry/TrackingVolume.cpp index 855064f21a1..aead2d7b0b0 100644 --- a/Core/src/Geometry/TrackingVolume.cpp +++ b/Core/src/Geometry/TrackingVolume.cpp @@ -700,7 +700,8 @@ void TrackingVolume::visualize(IVisualization3D& helper, } for (const auto& child : volumes()) { - child.visualize(helper, gctx, viewConfig, portalViewConfig); + child.visualize(helper, gctx, viewConfig, portalViewConfig, + sensitiveViewConfig); } } diff --git a/Core/src/Visualization/ObjVisualization3D.cpp b/Core/src/Visualization/ObjVisualization3D.cpp index e2cdc8fdba6..777e883b3d3 100644 --- a/Core/src/Visualization/ObjVisualization3D.cpp +++ b/Core/src/Visualization/ObjVisualization3D.cpp @@ -8,6 +8,7 @@ #include "Acts/Visualization/ObjVisualization3D.hpp" +#include #include #include @@ -64,9 +65,10 @@ void ObjVisualization3D::faces(const std::vector& vtxs, if (face.size() == 2) { o.lines.push_back({face[0] + vtxoffs, face[2] + vtxoffs}); } else { - FaceType rawFace = face; - std::transform(rawFace.begin(), rawFace.end(), rawFace.begin(), - [&](std::size_t& iv) { return (iv + vtxoffs); }); + FaceType rawFace; + std::ranges::transform( + face, std::back_inserter(rawFace), + [&](unsigned long iv) { return (iv + vtxoffs); }); o.faces.push_back(rawFace); } } @@ -99,23 +101,22 @@ void ObjVisualization3D::write(std::ostream& os) const { } void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { - std::map materials; + std::map> materials; - auto mixColor = [&](const Color& color) -> std::string { + auto mixColor = [&](const Color& color) { std::string materialName; materialName = "material_"; materialName += std::to_string(color[0]) + std::string("_"); materialName += std::to_string(color[1]) + std::string("_"); materialName += std::to_string(color[2]); - if (materials.find(materialName) == materials.end()) { + if (!materials.contains(materialName)) { mos << "newmtl " << materialName << "\n"; std::vector shadings = {"Ka", "Kd", "Ks"}; for (const auto& shd : shadings) { mos << shd << " " << std::to_string(color[0] / 256.) << " "; mos << std::to_string(color[1] / 256.) << " "; - mos << std::to_string(color[2] / 256.) << " " - << "\n"; + mos << std::to_string(color[2] / 256.) << " " << "\n"; } mos << "\n"; } @@ -131,7 +132,7 @@ void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { std::size_t iv = 0; Color lastVertexColor = {0, 0, 0}; for (const VertexType& vtx : o.vertices) { - if (o.vertexColors.find(iv) != o.vertexColors.end()) { + if (o.vertexColors.contains(iv)) { auto color = o.vertexColors.find(iv)->second; if (color != lastVertexColor) { os << mixColor(color) << "\n"; @@ -146,22 +147,22 @@ void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { } std::size_t il = 0; Color lastLineColor = {0, 0, 0}; - for (const LineType& ln : o.lines) { - if (o.lineColors.find(il) != o.lineColors.end()) { + for (const auto& [start, end] : o.lines) { + if (o.lineColors.contains(il)) { auto color = o.lineColors.find(il)->second; if (color != lastLineColor) { os << mixColor(color) << "\n"; lastLineColor = color; } } - os << "l " << vertexOffset + ln.first + 1 << " " - << vertexOffset + ln.second + 1 << "\n"; + os << "l " << vertexOffset + start + 1 << " " << vertexOffset + end + 1 + << "\n"; ++il; } std::size_t is = 0; Color lastFaceColor = {0, 0, 0}; for (const FaceType& fc : o.faces) { - if (o.faceColors.find(is) != o.faceColors.end()) { + if (o.faceColors.contains(is)) { auto color = o.faceColors.find(is)->second; if (color != lastFaceColor) { os << mixColor(color) << "\n"; @@ -169,8 +170,8 @@ void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const { } } os << "f"; - for (std::size_t i = 0; i < fc.size(); i++) { - os << " " << vertexOffset + fc[i] + 1; + for (std::size_t fi : fc) { + os << " " << vertexOffset + fi + 1; } os << "\n"; ++is; From 3c45762af5a0727ca1292cd972444ef351a290b4 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 3 Oct 2024 14:22:20 +0200 Subject: [PATCH 24/24] revert file handle change back to path argument --- Examples/Python/src/Output.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Examples/Python/src/Output.cpp b/Examples/Python/src/Output.cpp index 3879b05220e..56fedb969d3 100644 --- a/Examples/Python/src/Output.cpp +++ b/Examples/Python/src/Output.cpp @@ -58,6 +58,7 @@ #include #include +#include namespace Acts { class TrackingGeometry; @@ -136,11 +137,8 @@ void addOutput(Context& ctx) { } py::class_(m, "IVisualization3D") - .def("write", [](const IVisualization3D& self, const py::object& arg) { - std::stringstream ss; - self.write(ss); - arg.attr("write")(ss.str()); - }); + .def("write", py::overload_cast( + &IVisualization3D::write, py::const_)); { using Writer = ActsExamples::ObjTrackingGeometryWriter;