Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-12 09:02:30

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->associatedDetectorElement() != nullptr
0062                              ? sensitiveConfig
0063                              : passiveConfig;
0064     drawSurface(helper, *sf, gctx, transform, vConfig);
0065     auto sfExtent = sf->polyhedronRepresentation(gctx, 1).extent();
0066     arrayExtent.extend(sfExtent);
0067   }
0068 
0069   if (!sensitiveConfig.outputName.empty()) {
0070     helper.write(outputDir / sensitiveConfig.outputName);
0071     helper.clear();
0072   }
0073 
0074   double thickness = gridConfig.lineThickness;
0075   // Draw the grid itself
0076   auto binning = surfaceArray.binningValues();
0077   auto axes = surfaceArray.getAxes();
0078   if (!binning.empty() && binning.size() == 2 && axes.size() == 2) {
0079     // Cylinder surface array
0080     if (binning[0] == AxisDirection::AxisPhi &&
0081         binning[1] == AxisDirection::AxisZ) {
0082       double R = arrayExtent.medium(AxisDirection::AxisR) + gridConfig.offset;
0083       auto phiValues = axes[0]->getBinEdges();
0084       auto zValues = axes[1]->getBinEdges();
0085       ViewConfig gridRadConfig = gridConfig;
0086       // Longitudinal lines
0087       for (auto phi : phiValues) {
0088         double cphi = std::cos(phi);
0089         double sphi = std::sin(phi);
0090         Vector3 p1(R * cphi, R * sphi, axes[1]->getMin());
0091         Vector3 p0(R * cphi, R * sphi, axes[1]->getMax());
0092         drawSegment(helper, transform * p0, transform * p1, gridConfig);
0093       }
0094       CylinderVolumeBounds cvb(R - 0.5 * thickness, R + 0.5 * thickness,
0095                                0.5 * thickness);
0096       auto cvbOrientedSurfaces = cvb.orientedSurfaces();
0097       for (auto z : zValues) {
0098         for (const auto& cvbSf : cvbOrientedSurfaces) {
0099           drawSurface(helper, *cvbSf.surface, gctx,
0100                       Translation3(0., 0., z) * transform, gridRadConfig);
0101         }
0102       }
0103 
0104     } else if (binning[0] == AxisDirection::AxisR &&
0105                binning[1] == AxisDirection::AxisPhi) {
0106       double z = arrayExtent.medium(AxisDirection::AxisZ) + gridConfig.offset;
0107       auto rValues = axes[0]->getBinEdges();
0108       auto phiValues = axes[1]->getBinEdges();
0109       ViewConfig gridRadConfig = gridConfig;
0110       gridRadConfig.quarterSegments = phiValues.size();
0111       for (auto r : rValues) {
0112         CylinderVolumeBounds cvb(r - 0.5 * thickness, r + 0.5 * thickness,
0113                                  0.5 * thickness);
0114         auto cvbOrientedSurfaces = cvb.orientedSurfaces();
0115         for (const auto& cvbSf : cvbOrientedSurfaces) {
0116           drawSurface(helper, *cvbSf.surface, gctx,
0117                       Translation3(0., 0., z) * transform, gridRadConfig);
0118         }
0119       }
0120       double rMin = axes[0]->getMin();
0121       double rMax = axes[0]->getMax();
0122       for (auto phi : phiValues) {
0123         double cphi = std::cos(phi);
0124         double sphi = std::sin(phi);
0125         Vector3 p1(rMax * cphi, rMax * sphi, z);
0126         Vector3 p0(rMin * cphi, rMin * sphi, z);
0127         drawSegment(helper, transform * p0, transform * p1, gridConfig);
0128       }
0129     }
0130   }
0131 
0132   if (!gridConfig.outputName.empty()) {
0133     helper.write(outputDir / gridConfig.outputName);
0134     helper.clear();
0135   }
0136 }
0137 
0138 void Acts::GeometryView3D::drawVolume(IVisualization3D& helper,
0139                                       const Volume& volume,
0140                                       const GeometryContext& gctx,
0141                                       const Transform3& /*transform*/,
0142                                       const ViewConfig& viewConfig) {
0143   volume.visualize(helper, gctx, viewConfig);
0144 }
0145 
0146 void Acts::GeometryView3D::drawLayer(
0147     IVisualization3D& helper, const Layer& layer, const GeometryContext& gctx,
0148     const ViewConfig& layerConfig, const ViewConfig& sensitiveConfig,
0149     const ViewConfig& gridConfig, const std::filesystem::path& outputDir) {
0150   if (layerConfig.visible) {
0151     auto layerVolume = layer.representingVolume();
0152     if (layerVolume != nullptr) {
0153       drawVolume(helper, *layerVolume, gctx, Transform3::Identity(),
0154                  layerConfig);
0155     } else {
0156       const auto& layerSurface = layer.surfaceRepresentation();
0157       drawSurface(helper, layerSurface, gctx, Transform3::Identity(),
0158                   layerConfig);
0159     }
0160     if (!layerConfig.outputName.empty()) {
0161       helper.write(outputDir / layerConfig.outputName);
0162       helper.clear();
0163     }
0164   }
0165 
0166   if (sensitiveConfig.visible || gridConfig.visible) {
0167     auto surfaceArray = layer.surfaceArray();
0168     if (surfaceArray != nullptr) {
0169       drawSurfaceArray(helper, *surfaceArray, gctx, Transform3::Identity(),
0170                        sensitiveConfig, layerConfig, gridConfig, outputDir);
0171     }
0172   }
0173 }
0174 
0175 void Acts::GeometryView3D::drawTrackingVolume(
0176     IVisualization3D& helper, const TrackingVolume& tVolume,
0177     const GeometryContext& gctx, const ViewConfig& containerView,
0178     const ViewConfig& volumeView, const ViewConfig& layerView,
0179     const ViewConfig& sensitiveView, const ViewConfig& gridView, bool writeIt,
0180     const std::string& tag, const std::filesystem::path& outputDir) {
0181   if (tVolume.confinedVolumes() != nullptr) {
0182     const auto& subVolumes = tVolume.confinedVolumes()->arrayObjects();
0183     for (const auto& tv : subVolumes) {
0184       drawTrackingVolume(helper, *tv, gctx, containerView, volumeView,
0185                          layerView, sensitiveView, gridView, writeIt, tag,
0186                          outputDir);
0187     }
0188   }
0189 
0190   ViewConfig cConfig = containerView;
0191   ViewConfig vConfig = volumeView;
0192   ViewConfig lConfig = layerView;
0193   ViewConfig sConfig = sensitiveView;
0194   ViewConfig gConfig = gridView;
0195   gConfig.quarterSegments = 8;
0196 
0197   ViewConfig vcConfig = cConfig;
0198   std::string vname = tVolume.volumeName();
0199   if (writeIt) {
0200     std::vector<std::string> repChar = {"::" /*, "|", " ", "{", "}"*/};
0201     for (const auto& rchar : repChar) {
0202       while (vname.find(rchar) != std::string::npos) {
0203         vname.replace(vname.find(rchar), rchar.size(), std::string("_"));
0204       }
0205     }
0206     if (tVolume.confinedVolumes() == nullptr) {
0207       vcConfig = vConfig;
0208       vcConfig.outputName =
0209           std::filesystem::path(vname + std::string("_boundaries") + tag);
0210     } else {
0211       std::vector<GeometryIdentifier::Value> ids{tVolume.geometryId().volume()};
0212 
0213       for (const auto* current = &tVolume; current->motherVolume() != nullptr;
0214            current = current->motherVolume()) {
0215         ids.push_back(current->motherVolume()->geometryId().volume());
0216       }
0217 
0218       std::ranges::reverse(ids);
0219       vname = "Container";
0220       for (const auto& id : ids) {
0221         vname += "_v" + std::to_string(id);
0222       }
0223 
0224       vcConfig.outputName =
0225           std::filesystem::path(vname + std::string("_boundaries") + tag);
0226     }
0227   }
0228 
0229   auto bSurfaces = tVolume.boundarySurfaces();
0230   for (const auto& bs : bSurfaces) {
0231     drawSurface(helper, bs->surfaceRepresentation(), gctx,
0232                 Transform3::Identity(), vcConfig);
0233   }
0234   if (writeIt) {
0235     const std::filesystem::path outputName = outputDir / vcConfig.outputName;
0236     helper.write(outputName);
0237     helper.clear();
0238   }
0239 
0240   if (tVolume.confinedLayers() != nullptr) {
0241     const auto& layers = tVolume.confinedLayers()->arrayObjects();
0242     std::size_t il = 0;
0243     for (const auto& tl : layers) {
0244       if (writeIt) {
0245         lConfig.outputName = std::filesystem::path(
0246             vname + std::string("_passives_l") + std::to_string(il) + tag);
0247         sConfig.outputName = std::filesystem::path(
0248             vname + std::string("_sensitives_l") + std::to_string(il) + tag);
0249         gConfig.outputName = std::filesystem::path(
0250             vname + std::string("_grids_l") + std::to_string(il) + tag);
0251       }
0252       drawLayer(helper, *tl, gctx, lConfig, sConfig, gConfig, outputDir);
0253       ++il;
0254     }
0255   }
0256 }
0257 
0258 void Acts::GeometryView3D::drawSegmentBase(IVisualization3D& helper,
0259                                            const Vector3& start,
0260                                            const Vector3& end, int arrows,
0261                                            double arrowLength,
0262                                            double arrowWidth,
0263                                            const ViewConfig& viewConfig) {
0264   double thickness = viewConfig.lineThickness;
0265 
0266   // Draw the parameter shaft and cone
0267   auto direction = Vector3(end - start).normalized();
0268   double hlength = 0.5 * Vector3(end - start).norm();
0269 
0270   auto unitVectors = createCurvilinearUnitVectors(direction);
0271   RotationMatrix3 lrotation;
0272   lrotation.col(0) = unitVectors.first;
0273   lrotation.col(1) = unitVectors.second;
0274   lrotation.col(2) = direction;
0275 
0276   Vector3 lcenter = 0.5 * (start + end);
0277   double alength = (thickness > 0.) ? arrowLength * thickness : 2.;
0278   if (alength > hlength) {
0279     alength = hlength;
0280   }
0281 
0282   if (arrows == 2) {
0283     hlength -= alength;
0284   } else if (arrows != 0) {
0285     hlength -= 0.5 * alength;
0286     lcenter -= Vector3(arrows * 0.5 * alength * direction);
0287   }
0288 
0289   // Line - draw a line
0290   if (thickness > 0.) {
0291     auto ltransform = Transform3::Identity();
0292     ltransform.prerotate(lrotation);
0293     ltransform.pretranslate(lcenter);
0294 
0295     auto lbounds = std::make_shared<CylinderBounds>(thickness, hlength);
0296     auto line = Surface::makeShared<CylinderSurface>(ltransform, lbounds);
0297 
0298     drawSurface(helper, *line, GeometryContext(), Transform3::Identity(),
0299                 viewConfig);
0300   } else {
0301     helper.line(start, end, viewConfig.color);
0302   }
0303 
0304   // Arrowheads - if configured
0305   if (arrows != 0) {
0306     double awith = thickness * arrowWidth;
0307     double alpha = std::atan2(thickness * arrowWidth, alength);
0308     auto plateBounds = std::make_shared<RadialBounds>(thickness, awith);
0309 
0310     if (arrows > 0) {
0311       auto aetransform = Transform3::Identity();
0312       aetransform.prerotate(lrotation);
0313       aetransform.pretranslate(end);
0314       // Arrow cone
0315       auto coneBounds = std::make_shared<ConeBounds>(alpha, -alength, 0.);
0316       auto cone = Surface::makeShared<ConeSurface>(aetransform, coneBounds);
0317       drawSurface(helper, *cone, GeometryContext(), Transform3::Identity(),
0318                   viewConfig);
0319       // Arrow end plate
0320       auto aptransform = Transform3::Identity();
0321       aptransform.prerotate(lrotation);
0322       aptransform.pretranslate(Vector3(end - alength * direction));
0323 
0324       auto plate = Surface::makeShared<DiscSurface>(aptransform, plateBounds);
0325       drawSurface(helper, *plate, GeometryContext(), Transform3::Identity(),
0326                   viewConfig);
0327     }
0328     if (arrows < 0 || arrows == 2) {
0329       auto astransform = Transform3::Identity();
0330       astransform.prerotate(lrotation);
0331       astransform.pretranslate(start);
0332 
0333       // Arrow cone
0334       auto coneBounds = std::make_shared<ConeBounds>(alpha, 0., alength);
0335       auto cone = Surface::makeShared<ConeSurface>(astransform, coneBounds);
0336       drawSurface(helper, *cone, GeometryContext(), Transform3::Identity(),
0337                   viewConfig);
0338       // Arrow end plate
0339       auto aptransform = Transform3::Identity();
0340       aptransform.prerotate(lrotation);
0341       aptransform.pretranslate(Vector3(start + alength * direction));
0342 
0343       auto plate = Surface::makeShared<DiscSurface>(aptransform, plateBounds);
0344       drawSurface(helper, *plate, GeometryContext(), Transform3::Identity(),
0345                   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 }