Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-11 08:01:08

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Visualization/GeometryView3D.hpp"
0010 
0011 #include "Acts/Geometry/BoundarySurfaceT.hpp"
0012 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0013 #include "Acts/Geometry/Extent.hpp"
0014 #include "Acts/Geometry/GeometryIdentifier.hpp"
0015 #include "Acts/Geometry/Layer.hpp"
0016 #include "Acts/Geometry/Polyhedron.hpp"
0017 #include "Acts/Geometry/TrackingVolume.hpp"
0018 #include "Acts/Geometry/Volume.hpp"
0019 #include "Acts/Surfaces/ConeBounds.hpp"
0020 #include "Acts/Surfaces/ConeSurface.hpp"
0021 #include "Acts/Surfaces/CylinderBounds.hpp"
0022 #include "Acts/Surfaces/CylinderSurface.hpp"
0023 #include "Acts/Surfaces/DiscSurface.hpp"
0024 #include "Acts/Surfaces/RadialBounds.hpp"
0025 #include "Acts/Surfaces/Surface.hpp"
0026 #include "Acts/Surfaces/SurfaceArray.hpp"
0027 #include "Acts/Utilities/BinningType.hpp"
0028 #include "Acts/Utilities/IAxis.hpp"
0029 #include "Acts/Utilities/UnitVectors.hpp"
0030 #include "Acts/Visualization/IVisualization3D.hpp"
0031 
0032 #include <algorithm>
0033 #include <cmath>
0034 #include <filesystem>
0035 #include <memory>
0036 #include <utility>
0037 #include <vector>
0038 
0039 void Acts::GeometryView3D::drawPolyhedron(IVisualization3D& helper,
0040                                           const Polyhedron& polyhedron,
0041                                           const ViewConfig& viewConfig) {
0042   polyhedron.visualize(helper, viewConfig);
0043 }
0044 
0045 void Acts::GeometryView3D::drawSurface(IVisualization3D& helper,
0046                                        const Surface& surface,
0047                                        const GeometryContext& gctx,
0048                                        const Transform3& /*transform*/,
0049                                        const ViewConfig& viewConfig) {
0050   surface.visualize(helper, gctx, viewConfig);
0051 }
0052 
0053 void Acts::GeometryView3D::drawSurfaceArray(
0054     IVisualization3D& helper, const SurfaceArray& surfaceArray,
0055     const GeometryContext& gctx, const Transform3& transform,
0056     const ViewConfig& sensitiveConfig, const ViewConfig& passiveConfig,
0057     const ViewConfig& gridConfig, const std::filesystem::path& outputDir) {
0058   // Draw all the surfaces
0059   Extent arrayExtent;
0060   for (const auto& sf : surfaceArray.surfaces()) {
0061     ViewConfig vConfig = sf->isSensitive() ? sensitiveConfig : passiveConfig;
0062     drawSurface(helper, *sf, gctx, transform, vConfig);
0063     auto sfExtent = sf->polyhedronRepresentation(gctx, 1).extent();
0064     arrayExtent.extend(sfExtent);
0065   }
0066 
0067   if (!sensitiveConfig.outputName.empty()) {
0068     helper.write(outputDir / sensitiveConfig.outputName);
0069     helper.clear();
0070   }
0071 
0072   double thickness = gridConfig.lineThickness;
0073   // Draw the grid itself
0074   auto binning = surfaceArray.binningValues();
0075   auto axes = surfaceArray.getAxes();
0076   if (!binning.empty() && binning.size() == 2 && axes.size() == 2) {
0077     // Cylinder surface array
0078     if (binning[0] == AxisDirection::AxisPhi &&
0079         binning[1] == AxisDirection::AxisZ) {
0080       double R = arrayExtent.medium(AxisDirection::AxisR) + gridConfig.offset;
0081       auto phiValues = axes[0]->getBinEdges();
0082       auto zValues = axes[1]->getBinEdges();
0083       ViewConfig gridRadConfig = gridConfig;
0084       // Longitudinal lines
0085       for (auto phi : phiValues) {
0086         double cphi = std::cos(phi);
0087         double sphi = std::sin(phi);
0088         Vector3 p1(R * cphi, R * sphi, axes[1]->getMin());
0089         Vector3 p0(R * cphi, R * sphi, axes[1]->getMax());
0090         drawSegment(helper, transform * p0, transform * p1, gridConfig);
0091       }
0092       CylinderVolumeBounds cvb(R - 0.5 * thickness, R + 0.5 * thickness,
0093                                0.5 * thickness);
0094       auto cvbOrientedSurfaces = cvb.orientedSurfaces();
0095       for (auto z : zValues) {
0096         for (const auto& cvbSf : cvbOrientedSurfaces) {
0097           drawSurface(helper, *cvbSf.surface, gctx,
0098                       Translation3(0., 0., z) * transform, gridRadConfig);
0099         }
0100       }
0101 
0102     } else if (binning[0] == AxisDirection::AxisR &&
0103                binning[1] == AxisDirection::AxisPhi) {
0104       double z = arrayExtent.medium(AxisDirection::AxisZ) + gridConfig.offset;
0105       auto rValues = axes[0]->getBinEdges();
0106       auto phiValues = axes[1]->getBinEdges();
0107       ViewConfig gridRadConfig = gridConfig;
0108       gridRadConfig.quarterSegments = phiValues.size();
0109       for (auto r : rValues) {
0110         CylinderVolumeBounds cvb(r - 0.5 * thickness, r + 0.5 * thickness,
0111                                  0.5 * thickness);
0112         auto cvbOrientedSurfaces = cvb.orientedSurfaces();
0113         for (const auto& cvbSf : cvbOrientedSurfaces) {
0114           drawSurface(helper, *cvbSf.surface, gctx,
0115                       Translation3(0., 0., z) * transform, gridRadConfig);
0116         }
0117       }
0118       double rMin = axes[0]->getMin();
0119       double rMax = axes[0]->getMax();
0120       for (auto phi : phiValues) {
0121         double cphi = std::cos(phi);
0122         double sphi = std::sin(phi);
0123         Vector3 p1(rMax * cphi, rMax * sphi, z);
0124         Vector3 p0(rMin * cphi, rMin * sphi, z);
0125         drawSegment(helper, transform * p0, transform * p1, gridConfig);
0126       }
0127     }
0128   }
0129 
0130   if (!gridConfig.outputName.empty()) {
0131     helper.write(outputDir / gridConfig.outputName);
0132     helper.clear();
0133   }
0134 }
0135 
0136 void Acts::GeometryView3D::drawVolume(IVisualization3D& helper,
0137                                       const Volume& volume,
0138                                       const GeometryContext& gctx,
0139                                       const Transform3& /*transform*/,
0140                                       const ViewConfig& viewConfig) {
0141   volume.visualize(helper, gctx, viewConfig);
0142 }
0143 
0144 void Acts::GeometryView3D::drawLayer(
0145     IVisualization3D& helper, const Layer& layer, const GeometryContext& gctx,
0146     const ViewConfig& layerConfig, const ViewConfig& sensitiveConfig,
0147     const ViewConfig& gridConfig, const std::filesystem::path& outputDir) {
0148   if (layerConfig.visible) {
0149     auto layerVolume = layer.representingVolume();
0150     if (layerVolume != nullptr) {
0151       drawVolume(helper, *layerVolume, gctx, Transform3::Identity(),
0152                  layerConfig);
0153     } else {
0154       const auto& layerSurface = layer.surfaceRepresentation();
0155       drawSurface(helper, layerSurface, gctx, Transform3::Identity(),
0156                   layerConfig);
0157     }
0158     if (!layerConfig.outputName.empty()) {
0159       helper.write(outputDir / layerConfig.outputName);
0160       helper.clear();
0161     }
0162   }
0163 
0164   if (sensitiveConfig.visible || gridConfig.visible) {
0165     auto surfaceArray = layer.surfaceArray();
0166     if (surfaceArray != nullptr) {
0167       drawSurfaceArray(helper, *surfaceArray, gctx, Transform3::Identity(),
0168                        sensitiveConfig, layerConfig, gridConfig, outputDir);
0169     }
0170   }
0171 }
0172 
0173 void Acts::GeometryView3D::drawTrackingVolume(
0174     IVisualization3D& helper, const TrackingVolume& tVolume,
0175     const GeometryContext& gctx, const ViewConfig& containerView,
0176     const ViewConfig& volumeView, const ViewConfig& layerView,
0177     const ViewConfig& sensitiveView, const ViewConfig& gridView, bool writeIt,
0178     const std::string& tag, const std::filesystem::path& outputDir) {
0179   if (tVolume.confinedVolumes() != nullptr) {
0180     const auto& subVolumes = tVolume.confinedVolumes()->arrayObjects();
0181     for (const auto& tv : subVolumes) {
0182       drawTrackingVolume(helper, *tv, gctx, containerView, volumeView,
0183                          layerView, sensitiveView, gridView, writeIt, tag,
0184                          outputDir);
0185     }
0186   }
0187 
0188   ViewConfig cConfig = containerView;
0189   ViewConfig vConfig = volumeView;
0190   ViewConfig lConfig = layerView;
0191   ViewConfig sConfig = sensitiveView;
0192   ViewConfig gConfig = gridView;
0193   gConfig.quarterSegments = 8;
0194 
0195   ViewConfig vcConfig = cConfig;
0196   std::string vname = tVolume.volumeName();
0197   if (writeIt) {
0198     std::vector<std::string> repChar = {"::" /*, "|", " ", "{", "}"*/};
0199     for (const auto& rchar : repChar) {
0200       while (vname.find(rchar) != std::string::npos) {
0201         vname.replace(vname.find(rchar), rchar.size(), std::string("_"));
0202       }
0203     }
0204     if (tVolume.confinedVolumes() == nullptr) {
0205       vcConfig = vConfig;
0206       vcConfig.outputName =
0207           std::filesystem::path(vname + std::string("_boundaries") + tag);
0208     } else {
0209       std::vector<GeometryIdentifier::Value> ids{tVolume.geometryId().volume()};
0210 
0211       for (const auto* current = &tVolume; current->motherVolume() != nullptr;
0212            current = current->motherVolume()) {
0213         ids.push_back(current->motherVolume()->geometryId().volume());
0214       }
0215 
0216       std::ranges::reverse(ids);
0217       vname = "Container";
0218       for (const auto& id : ids) {
0219         vname += "_v" + std::to_string(id);
0220       }
0221 
0222       vcConfig.outputName =
0223           std::filesystem::path(vname + std::string("_boundaries") + tag);
0224     }
0225   }
0226 
0227   auto bSurfaces = tVolume.boundarySurfaces();
0228   for (const auto& bs : bSurfaces) {
0229     drawSurface(helper, bs->surfaceRepresentation(), gctx,
0230                 Transform3::Identity(), vcConfig);
0231   }
0232   if (writeIt) {
0233     const std::filesystem::path outputName = outputDir / vcConfig.outputName;
0234     helper.write(outputName);
0235     helper.clear();
0236   }
0237 
0238   if (tVolume.confinedLayers() != nullptr) {
0239     const auto& layers = tVolume.confinedLayers()->arrayObjects();
0240     std::size_t il = 0;
0241     for (const auto& tl : layers) {
0242       if (writeIt) {
0243         lConfig.outputName = std::filesystem::path(
0244             vname + std::string("_passives_l") + std::to_string(il) + tag);
0245         sConfig.outputName = std::filesystem::path(
0246             vname + std::string("_sensitives_l") + std::to_string(il) + tag);
0247         gConfig.outputName = std::filesystem::path(
0248             vname + std::string("_grids_l") + std::to_string(il) + tag);
0249       }
0250       drawLayer(helper, *tl, gctx, lConfig, sConfig, gConfig, outputDir);
0251       ++il;
0252     }
0253   }
0254 }
0255 
0256 void Acts::GeometryView3D::drawSegmentBase(IVisualization3D& helper,
0257                                            const Vector3& start,
0258                                            const Vector3& end, int arrows,
0259                                            double arrowLength,
0260                                            double arrowWidth,
0261                                            const ViewConfig& viewConfig) {
0262   double thickness = viewConfig.lineThickness;
0263 
0264   // Draw the parameter shaft and cone
0265   auto direction = Vector3(end - start).normalized();
0266   double hlength = 0.5 * Vector3(end - start).norm();
0267 
0268   auto unitVectors = createCurvilinearUnitVectors(direction);
0269   RotationMatrix3 lrotation;
0270   lrotation.col(0) = unitVectors.first;
0271   lrotation.col(1) = unitVectors.second;
0272   lrotation.col(2) = direction;
0273 
0274   Vector3 lcenter = 0.5 * (start + end);
0275   double alength = (thickness > 0.) ? arrowLength * thickness : 2.;
0276   if (alength > hlength) {
0277     alength = hlength;
0278   }
0279 
0280   if (arrows == 2) {
0281     hlength -= alength;
0282   } else if (arrows != 0) {
0283     hlength -= 0.5 * alength;
0284     lcenter -= Vector3(arrows * 0.5 * alength * direction);
0285   }
0286 
0287   // Line - draw a line
0288   if (thickness > 0.) {
0289     auto ltransform = Transform3::Identity();
0290     ltransform.prerotate(lrotation);
0291     ltransform.pretranslate(lcenter);
0292 
0293     auto lbounds = std::make_shared<CylinderBounds>(thickness, hlength);
0294     auto line = Surface::makeShared<CylinderSurface>(ltransform, lbounds);
0295 
0296     drawSurface(helper, *line, GeometryContext::dangerouslyDefaultConstruct(),
0297                 Transform3::Identity(), viewConfig);
0298   } else {
0299     helper.line(start, end, viewConfig.color);
0300   }
0301 
0302   // Arrowheads - if configured
0303   if (arrows != 0) {
0304     double awith = thickness * arrowWidth;
0305     double alpha = std::atan2(thickness * arrowWidth, alength);
0306     auto plateBounds = std::make_shared<RadialBounds>(thickness, awith);
0307 
0308     if (arrows > 0) {
0309       auto aetransform = Transform3::Identity();
0310       aetransform.prerotate(lrotation);
0311       aetransform.pretranslate(end);
0312       // Arrow cone
0313       auto coneBounds = std::make_shared<ConeBounds>(alpha, -alength, 0.);
0314       auto cone = Surface::makeShared<ConeSurface>(aetransform, coneBounds);
0315       drawSurface(helper, *cone, GeometryContext::dangerouslyDefaultConstruct(),
0316                   Transform3::Identity(), viewConfig);
0317       // Arrow end plate
0318       auto aptransform = Transform3::Identity();
0319       aptransform.prerotate(lrotation);
0320       aptransform.pretranslate(Vector3(end - alength * direction));
0321 
0322       auto plate = Surface::makeShared<DiscSurface>(aptransform, plateBounds);
0323       drawSurface(helper, *plate,
0324                   GeometryContext::dangerouslyDefaultConstruct(),
0325                   Transform3::Identity(), viewConfig);
0326     }
0327     if (arrows < 0 || arrows == 2) {
0328       auto astransform = Transform3::Identity();
0329       astransform.prerotate(lrotation);
0330       astransform.pretranslate(start);
0331 
0332       // Arrow cone
0333       auto coneBounds = std::make_shared<ConeBounds>(alpha, 0., alength);
0334       auto cone = Surface::makeShared<ConeSurface>(astransform, coneBounds);
0335       drawSurface(helper, *cone, GeometryContext::dangerouslyDefaultConstruct(),
0336                   Transform3::Identity(), viewConfig);
0337       // Arrow end plate
0338       auto aptransform = Transform3::Identity();
0339       aptransform.prerotate(lrotation);
0340       aptransform.pretranslate(Vector3(start + alength * direction));
0341 
0342       auto plate = Surface::makeShared<DiscSurface>(aptransform, plateBounds);
0343       drawSurface(helper, *plate,
0344                   GeometryContext::dangerouslyDefaultConstruct(),
0345                   Transform3::Identity(), viewConfig);
0346     }
0347   }
0348 }
0349 
0350 void Acts::GeometryView3D::drawSegment(IVisualization3D& helper,
0351                                        const Vector3& start, const Vector3& end,
0352                                        const ViewConfig& viewConfig) {
0353   drawSegmentBase(helper, start, end, 0, 0., 0., viewConfig);
0354 }
0355 
0356 void Acts::GeometryView3D::drawArrowBackward(
0357     IVisualization3D& helper, const Vector3& start, const Vector3& end,
0358     double arrowLength, double arrowWidth, const ViewConfig& viewConfig) {
0359   drawSegmentBase(helper, start, end, -1, arrowLength, arrowWidth, viewConfig);
0360 }
0361 
0362 void Acts::GeometryView3D::drawArrowForward(
0363     IVisualization3D& helper, const Vector3& start, const Vector3& end,
0364     double arrowLength, double arrowWidth, const ViewConfig& viewConfig) {
0365   drawSegmentBase(helper, start, end, 1, arrowLength, arrowWidth, viewConfig);
0366 }
0367 
0368 void Acts::GeometryView3D::drawArrowsBoth(IVisualization3D& helper,
0369                                           const Vector3& start,
0370                                           const Vector3& end,
0371                                           double arrowLength, double arrowWidth,
0372                                           const ViewConfig& viewConfig) {
0373   drawSegmentBase(helper, start, end, 2, arrowLength, arrowWidth, viewConfig);
0374 }