File indexing completed on 2025-08-06 08:11:40
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Geometry/DiscLayer.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/Geometry/GeometryHierarchyMap.hpp"
0014 #include "Acts/Geometry/Layer.hpp"
0015 #include "Acts/Geometry/LayerCreator.hpp"
0016 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
0017 #include "Acts/Plugins/ActSVG/LayerSvgConverter.hpp"
0018 #include "Acts/Plugins/ActSVG/SvgUtils.hpp"
0019 #include "Acts/Surfaces/DiscSurface.hpp"
0020 #include "Acts/Surfaces/PlaneSurface.hpp"
0021 #include "Acts/Surfaces/RadialBounds.hpp"
0022 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0023 #include "Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0024
0025 #include <fstream>
0026 #include <memory>
0027 #include <vector>
0028
0029 BOOST_AUTO_TEST_SUITE(ActSvg)
0030
0031 namespace {
0032
0033 Acts::GeometryContext tgContext;
0034
0035 std::shared_ptr<const Acts::LayerCreator> lCreator(nullptr);
0036
0037 void setupTools() {
0038 if (lCreator == nullptr) {
0039 Acts::LayerCreator::Config lCreatorCfg;
0040 lCreatorCfg.surfaceArrayCreator =
0041 std::make_shared<const Acts::SurfaceArrayCreator>();
0042 lCreator = std::make_shared<const Acts::LayerCreator>(lCreatorCfg);
0043 }
0044 }
0045
0046 std::shared_ptr<Acts::Layer> generateDiscLayer(Acts::ActsScalar rInner,
0047 Acts::ActsScalar rOuter,
0048 unsigned int nSegments,
0049 unsigned int nRings,
0050 bool useTrapezoids = false) {
0051
0052 setupTools();
0053 std::vector<std::shared_ptr<const Acts::Surface>> moduleSurfaces;
0054 Acts::ActsScalar phiStep = 2 * M_PI / nSegments;
0055 Acts::ActsScalar rStep = (rOuter - rInner) / nRings;
0056
0057 moduleSurfaces.reserve(nSegments * nRings);
0058
0059 if (!useTrapezoids) {
0060 for (unsigned int ir = 0; ir < nRings; ++ir) {
0061 std::shared_ptr<const Acts::RadialBounds> rBounds = nullptr;
0062 rBounds = std::make_shared<Acts::RadialBounds>(
0063 rInner + ir * rStep - 0.025 * rInner,
0064 rInner + (ir + 1u) * rStep + 0.025 * rInner, 0.55 * phiStep, 0.);
0065 for (unsigned int is = 0; is < nSegments; ++is) {
0066
0067 auto placement = Acts::Transform3::Identity();
0068 if ((is % 2) != 0u) {
0069 placement.pretranslate(Acts::Vector3{0., 0., 2.});
0070 }
0071 placement.rotate(
0072 Eigen::AngleAxisd(is * phiStep, Acts::Vector3(0, 0, 1)));
0073 auto dModule =
0074 Acts::Surface::makeShared<Acts::DiscSurface>(placement, rBounds);
0075 moduleSurfaces.push_back(dModule);
0076 }
0077 }
0078 } else {
0079 for (unsigned int ir = 0; ir < nRings; ++ir) {
0080
0081 Acts::ActsScalar radius = rInner + (ir + 0.5) * rStep;
0082 Acts::ActsScalar yHalf = rStep * 0.5125;
0083
0084 Acts::ActsScalar xHalfMin =
0085 1.15 * (rInner + ir * rStep) * M_PI / nSegments;
0086 Acts::ActsScalar xHalfMax =
0087 1.15 * (rInner + (ir + 1) * rStep) * M_PI / nSegments;
0088
0089 std::shared_ptr<const Acts::TrapezoidBounds> tBounds =
0090 std::make_shared<const Acts::TrapezoidBounds>(xHalfMin, xHalfMax,
0091 yHalf);
0092 for (unsigned int is = 0; is < nSegments; ++is) {
0093
0094 Acts::ActsScalar cphi = -M_PI + is * phiStep;
0095 Acts::Vector3 center(radius * std::cos(cphi), radius * std::sin(cphi),
0096 (is % 2) * 2 + (ir % 2) * 5);
0097
0098 Acts::Vector3 localY(std::cos(cphi), std::sin(cphi), 0.);
0099 Acts::Vector3 localZ(0., 0., 1.);
0100 Acts::Vector3 localX = localY.cross(localZ);
0101 Acts::RotationMatrix3 rotation;
0102 rotation.col(0) = localX;
0103 rotation.col(1) = localY;
0104 rotation.col(2) = localZ;
0105 Acts::Transform3 placement(Acts::Translation3(center) * rotation);
0106
0107 auto dModule =
0108 Acts::Surface::makeShared<Acts::PlaneSurface>(placement, tBounds);
0109 moduleSurfaces.push_back(dModule);
0110 }
0111 }
0112 }
0113
0114 return lCreator->discLayer(tgContext, moduleSurfaces, nRings, nSegments);
0115 }
0116
0117 }
0118
0119 BOOST_AUTO_TEST_CASE(DiscLayerRadialSvg) {
0120
0121 Acts::Svg::Style discLayerStyle;
0122 discLayerStyle.fillColor = {51, 153, 255};
0123 discLayerStyle.fillOpacity = 0.75;
0124 discLayerStyle.highlightColor = {255, 153, 51};
0125 discLayerStyle.highlights = {"mouseover", "mouseout"};
0126 discLayerStyle.strokeColor = {25, 25, 25};
0127 discLayerStyle.strokeWidth = 0.5;
0128 discLayerStyle.nSegments = 72u;
0129
0130 Acts::GeometryIdentifier geoID{0};
0131
0132
0133 auto discLayer = generateDiscLayer(100, 250, 32u, 4u);
0134
0135 Acts::Svg::LayerConverter::Options lOptions;
0136 lOptions.name = "disc_layer_sectors";
0137 lOptions.surfaceStyles =
0138 Acts::GeometryHierarchyMap<Acts::Svg::Style>({{geoID, discLayerStyle}});
0139
0140
0141 auto discLayerSheets =
0142 Acts::Svg::LayerConverter::convert(tgContext, *discLayer, lOptions);
0143
0144 for (const auto& s : discLayerSheets) {
0145 Acts::Svg::toFile({s}, s._id + ".svg");
0146 }
0147 }
0148
0149 BOOST_AUTO_TEST_CASE(DiscLayerTrapezoidSvg) {
0150
0151 Acts::Svg::Style discLayerStyle;
0152 discLayerStyle.fillColor = {51, 153, 255};
0153 discLayerStyle.fillOpacity = 0.75;
0154 discLayerStyle.highlightColor = {255, 153, 51};
0155 discLayerStyle.highlights = {"mouseover", "mouseout"};
0156 discLayerStyle.strokeColor = {25, 25, 25};
0157 discLayerStyle.strokeWidth = 0.5;
0158 discLayerStyle.nSegments = 72u;
0159
0160 Acts::GeometryIdentifier geoID{0};
0161
0162
0163 auto discLayer = generateDiscLayer(100, 250, 32u, 4u, true);
0164
0165 Acts::Svg::LayerConverter::Options lOptions;
0166 lOptions.name = "disc_layer_trapezoid";
0167 lOptions.surfaceStyles =
0168 Acts::GeometryHierarchyMap<Acts::Svg::Style>({{geoID, discLayerStyle}});
0169
0170
0171 auto discLayerSheets =
0172 Acts::Svg::LayerConverter::convert(tgContext, *discLayer, lOptions);
0173
0174 for (const auto& s : discLayerSheets) {
0175 Acts::Svg::toFile({s}, s._id + ".svg");
0176 }
0177 }
0178
0179 BOOST_AUTO_TEST_CASE(CylinderLayerSvg) {
0180
0181 Acts::Svg::Style cylinderLayerStyle;
0182 cylinderLayerStyle.fillColor = {51, 153, 255};
0183 cylinderLayerStyle.fillOpacity = 0.75;
0184 cylinderLayerStyle.highlightColor = {255, 153, 51};
0185 cylinderLayerStyle.highlights = {"mouseover", "mouseout"};
0186 cylinderLayerStyle.strokeColor = {25, 25, 25};
0187 cylinderLayerStyle.strokeWidth = 0.5;
0188 cylinderLayerStyle.nSegments = 72u;
0189
0190 Acts::GeometryIdentifier geoID{0};
0191
0192 Acts::Test::CylindricalTrackingGeometry cGeometry(tgContext);
0193 auto tGeometry = cGeometry();
0194 auto pixelVolume =
0195 tGeometry->lowestTrackingVolume(tgContext, Acts::Vector3(50., 0., 0.));
0196 if (pixelVolume != nullptr && pixelVolume->confinedLayers() != nullptr) {
0197 auto layers = pixelVolume->confinedLayers()->arrayObjects();
0198 std::size_t il = 0;
0199 for (const auto& layer : layers) {
0200 if (layer->surfaceArray() != nullptr) {
0201 Acts::Svg::LayerConverter::Options lOptions;
0202 lOptions.name = "cylinder_layer_" + std::to_string(il++);
0203 lOptions.surfaceStyles = Acts::GeometryHierarchyMap<Acts::Svg::Style>(
0204 {{geoID, cylinderLayerStyle}});
0205
0206
0207 auto layerSheets =
0208 Acts::Svg::LayerConverter::convert(tgContext, *layer, lOptions);
0209 for (const auto& s : layerSheets) {
0210 Acts::Svg::toFile({s}, s._id + ".svg");
0211 }
0212 }
0213 }
0214 }
0215 }
0216
0217 BOOST_AUTO_TEST_CASE(PlaeyLayerSvg) {}
0218
0219 BOOST_AUTO_TEST_SUITE_END()