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