EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GeometryView3D.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GeometryView3D.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
12 #include "Acts/Geometry/Layer.hpp"
24 
26  const Polyhedron& polyhedron,
27  const ViewConfig& ViewConfig) {
28  if (ViewConfig.visible) {
29  if (not ViewConfig.triangulate) {
30  helper.faces(polyhedron.vertices, polyhedron.faces, ViewConfig.color);
31  } else {
32  helper.faces(polyhedron.vertices, polyhedron.triangularMesh,
33  ViewConfig.color);
34  }
35  }
36 }
37 
39  const Surface& surface,
40  const GeometryContext& gctx,
41  const Transform3D& transform,
42  const ViewConfig& ViewConfig) {
43  Polyhedron surfaceHedron =
44  surface.polyhedronRepresentation(gctx, ViewConfig.nSegments);
45  if (not transform.isApprox(Transform3D::Identity())) {
46  surfaceHedron.move(transform);
47  }
48  drawPolyhedron(helper, surfaceHedron, ViewConfig);
49 }
50 
52  const SurfaceArray& surfaceArray,
53  const GeometryContext& gctx,
54  const Transform3D& transform,
55  const ViewConfig& sensitiveConfig,
56  const ViewConfig& passiveConfig,
57  const ViewConfig& gridConfig) {
58  // Draw all the surfaces
59  Extent arrayExtent;
60  for (const auto& sf : surfaceArray.surfaces()) {
61  ViewConfig vConfig = sf->associatedDetectorElement() != nullptr
62  ? sensitiveConfig
63  : passiveConfig;
64  drawSurface(helper, *sf, gctx, transform, vConfig);
65  auto sfExtent = sf->polyhedronRepresentation(gctx, 1).extent();
66  arrayExtent.extend(sfExtent);
67  }
68 
69  if (not sensitiveConfig.outputName.empty()) {
70  helper.write(sensitiveConfig.outputName);
71  helper.clear();
72  }
73 
74  double thickness = gridConfig.lineThickness;
75  // Draw the grid itself
76  auto binning = surfaceArray.binningValues();
77  auto axes = surfaceArray.getAxes();
78  if (not binning.empty() and binning.size() == 2 and axes.size() == 2) {
79  // Cylinder surface array
80  if (binning[0] == binPhi and binning[1] == binZ) {
81  double R = arrayExtent.medium(binR) + gridConfig.offset;
82  auto phiValues = axes[0]->getBinEdges();
83  auto zValues = axes[1]->getBinEdges();
84  ViewConfig gridRadConfig = gridConfig;
85  gridRadConfig.nSegments = phiValues.size();
86  // Longitudinal lines
87  for (auto phi : phiValues) {
88  double cphi = std::cos(phi);
89  double sphi = std::sin(phi);
90  Vector3D p1(R * cphi, R * sphi, axes[1]->getMin());
91  Vector3D p0(R * cphi, R * sphi, axes[1]->getMax());
92  drawSegment(helper, transform * p0, transform * p1, gridConfig);
93  }
94  CylinderVolumeBounds cvb(R - 0.5 * thickness, R + 0.5 * thickness,
95  0.5 * thickness);
96  auto cvbOrientedSurfaces = cvb.orientedSurfaces();
97  for (auto z : zValues) {
98  for (auto cvbSf : cvbOrientedSurfaces) {
99  drawSurface(helper, *cvbSf.first, gctx,
100  Translation3D(0., 0., z) * transform, gridRadConfig);
101  }
102  }
103 
104  } else if (binning[0] == binR and binning[1] == binPhi) {
105  double z = arrayExtent.medium(binZ) + gridConfig.offset;
106  auto rValues = axes[0]->getBinEdges();
107  auto phiValues = axes[1]->getBinEdges();
108  ViewConfig gridRadConfig = gridConfig;
109  gridRadConfig.nSegments = phiValues.size();
110  for (auto r : rValues) {
111  CylinderVolumeBounds cvb(r - 0.5 * thickness, r + 0.5 * thickness,
112  0.5 * thickness);
113  auto cvbOrientedSurfaces = cvb.orientedSurfaces();
114  for (auto cvbSf : cvbOrientedSurfaces) {
115  drawSurface(helper, *cvbSf.first, gctx,
116  Translation3D(0., 0., z) * transform, gridRadConfig);
117  }
118  }
119  double rMin = axes[0]->getMin();
120  double rMax = axes[0]->getMax();
121  for (auto phi : phiValues) {
122  double cphi = std::cos(phi);
123  double sphi = std::sin(phi);
124  Vector3D p1(rMax * cphi, rMax * sphi, z);
125  Vector3D p0(rMin * cphi, rMin * sphi, z);
126  drawSegment(helper, transform * p0, transform * p1, gridConfig);
127  }
128  }
129  }
130 
131  if (not gridConfig.outputName.empty()) {
132  helper.write(gridConfig.outputName);
133  helper.clear();
134  }
135 }
136 
138  const AbstractVolume& volume,
139  const GeometryContext& gctx,
140  const Transform3D& transform,
141  const ViewConfig& viewConfig) {
142  auto bSurfaces = volume.boundarySurfaces();
143  for (const auto& bs : bSurfaces) {
144  drawSurface(helper, bs->surfaceRepresentation(), gctx, transform,
145  viewConfig);
146  }
147 }
148 
150  const Layer& layer,
151  const GeometryContext& gctx,
152  const ViewConfig& layerConfig,
153  const ViewConfig& sensitiveConfig,
154  const ViewConfig& gridConfig) {
155  if (layerConfig.visible) {
156  auto layerVolume = layer.representingVolume();
157  if (layerVolume != nullptr) {
158  drawVolume(helper, *layerVolume, gctx, Transform3D::Identity(),
159  layerConfig);
160  } else {
161  const auto& layerSurface = layer.surfaceRepresentation();
162  drawSurface(helper, layerSurface, gctx, Transform3D::Identity(),
163  layerConfig);
164  }
165  if (not layerConfig.outputName.empty()) {
166  helper.write(layerConfig.outputName);
167  helper.clear();
168  }
169  }
170 
171  if (sensitiveConfig.visible or gridConfig.visible) {
172  auto surfaceArray = layer.surfaceArray();
173  if (surfaceArray != nullptr) {
174  drawSurfaceArray(helper, *surfaceArray, gctx, Transform3D::Identity(),
175  sensitiveConfig, layerConfig, gridConfig);
176  }
177  }
178 }
179 
181  IVisualization3D& helper, const TrackingVolume& tVolume,
182  const GeometryContext& gctx, const ViewConfig& containerView,
183  const ViewConfig& volumeView, const ViewConfig& layerView,
184  const ViewConfig& sensitiveView, const ViewConfig& gridView, bool writeIt,
185  const std::string& tag) {
186  if (tVolume.confinedVolumes() != nullptr) {
187  const auto& subVolumes = tVolume.confinedVolumes()->arrayObjects();
188  for (const auto& tv : subVolumes) {
189  drawTrackingVolume(helper, *tv, gctx, containerView, volumeView,
190  layerView, sensitiveView, gridView, writeIt, tag);
191  }
192  }
193 
194  ViewConfig cConfig = containerView;
195  ViewConfig vConfig = volumeView;
196  ViewConfig lConfig = layerView;
197  ViewConfig sConfig = sensitiveView;
198  ViewConfig gConfig = gridView;
199  gConfig.nSegments = 8;
200 
201  ViewConfig vcConfig = cConfig;
202  std::string vname = tVolume.volumeName();
203  if (writeIt) {
204  std::vector<std::string> repChar = {":", "|", " ", "{", "}"};
205  for (auto rchar : repChar) {
206  while (vname.find(rchar) != std::string::npos) {
207  vname.replace(vname.find(rchar), rchar.size(), std::string("_"));
208  }
209  }
210  if (tVolume.confinedVolumes() == nullptr) {
211  vcConfig = vConfig;
212  vcConfig.outputName = vname + std::string("_boundaries") + tag;
213  } else {
214  vcConfig.outputName =
215  std::string("Container-") + vname + std::string("_boundaries") + tag;
216  }
217  }
218 
219  auto bSurfaces = tVolume.boundarySurfaces();
220  for (const auto& bs : bSurfaces) {
221  drawSurface(helper, bs->surfaceRepresentation(), gctx,
222  Transform3D::Identity(), vcConfig);
223  }
224  if (writeIt) {
225  helper.write(vcConfig.outputName);
226  helper.clear();
227  }
228 
229  if (tVolume.confinedLayers() != nullptr) {
230  const auto& layers = tVolume.confinedLayers()->arrayObjects();
231  size_t il = 0;
232  for (const auto& tl : layers) {
233  if (writeIt) {
234  lConfig.outputName =
235  vname + std::string("_passives_l") + std::to_string(il) + tag;
236  sConfig.outputName =
237  vname + std::string("_sensitives_l") + std::to_string(il) + tag;
238  gConfig.outputName =
239  vname + std::string("_grids_l") + std::to_string(il) + tag;
240  }
241  drawLayer(helper, *tl, gctx, lConfig, sConfig, gConfig);
242  ++il;
243  }
244  }
245 }
246 
248  const Vector3D& start,
249  const Vector3D& end, int arrows,
250  double arrowLength,
251  double arrowWidth,
252  const ViewConfig& viewConfig) {
253  double thickness = viewConfig.lineThickness;
254 
255  // Draw the parameter shaft and cone
256  auto direction = Vector3D(end - start).normalized();
257  double hlength = 0.5 * Vector3D(end - start).norm();
258 
259  auto unitVectors = makeCurvilinearUnitVectors(direction);
260  RotationMatrix3D lrotation;
261  lrotation.col(0) = unitVectors.first;
262  lrotation.col(1) = unitVectors.second;
263  lrotation.col(2) = direction;
264 
265  Vector3D lcenter = 0.5 * (start + end);
266  double alength = (thickness > 0.) ? arrowLength * thickness : 2.;
267  if (alength > hlength) {
268  alength = hlength;
269  }
270 
271  if (arrows == 2) {
272  hlength -= alength;
273  } else if (arrows != 0) {
274  hlength -= 0.5 * alength;
275  lcenter -= Vector3D(arrows * 0.5 * alength * direction);
276  }
277 
278  // Line - draw a line
279  if (thickness > 0.) {
280  auto ltransform = Transform3D::Identity();
281  ltransform.prerotate(lrotation);
282  ltransform.pretranslate(lcenter);
283 
284  auto lbounds = std::make_shared<CylinderBounds>(thickness, hlength);
285  auto line = Surface::makeShared<CylinderSurface>(ltransform, lbounds);
286 
287  drawSurface(helper, *line, GeometryContext(), Transform3D::Identity(),
288  viewConfig);
289  } else {
290  helper.line(start, end, viewConfig.color);
291  }
292 
293  // Arrowheads - if configured
294  if (arrows != 0) {
295  double awith = thickness * arrowWidth;
296  double alpha = atan2(thickness * arrowWidth, alength);
297  auto plateBounds = std::make_shared<RadialBounds>(thickness, awith);
298 
299  if (arrows > 0) {
300  auto aetransform = Transform3D::Identity();
301  aetransform.prerotate(lrotation);
302  aetransform.pretranslate(end);
303  // Arrow cone
304  auto coneBounds = std::make_shared<ConeBounds>(alpha, -alength, 0.);
305  auto cone = Surface::makeShared<ConeSurface>(aetransform, coneBounds);
306  drawSurface(helper, *cone, GeometryContext(), Transform3D::Identity(),
307  viewConfig);
308  // Arrow end plate
309  auto aptransform = Transform3D::Identity();
310  aptransform.prerotate(lrotation);
311  aptransform.pretranslate(Vector3D(end - alength * direction));
312 
313  auto plate = Surface::makeShared<DiscSurface>(aptransform, plateBounds);
314  drawSurface(helper, *plate, GeometryContext(), Transform3D::Identity(),
315  viewConfig);
316  }
317  if (arrows < 0 or arrows == 2) {
318  auto astransform = Transform3D::Identity();
319  astransform.prerotate(lrotation);
320  astransform.pretranslate(start);
321 
322  // Arrow cone
323  auto coneBounds = std::make_shared<ConeBounds>(alpha, 0., alength);
324  auto cone = Surface::makeShared<ConeSurface>(astransform, coneBounds);
325  drawSurface(helper, *cone, GeometryContext(), Transform3D::Identity(),
326  viewConfig);
327  // Arrow end plate
328  auto aptransform = Transform3D::Identity();
329  aptransform.prerotate(lrotation);
330  aptransform.pretranslate(Vector3D(start + alength * direction));
331 
332  auto plate = Surface::makeShared<DiscSurface>(aptransform, plateBounds);
333  drawSurface(helper, *plate, GeometryContext(), Transform3D::Identity(),
334  viewConfig);
335  }
336  }
337 }
338 
340  const Vector3D& start,
341  const Vector3D& end,
342  const ViewConfig& viewConfig) {
343  drawSegmentBase(helper, start, end, 0, 0., 0., viewConfig);
344 }
345 
347  IVisualization3D& helper, const Vector3D& start, const Vector3D& end,
348  double arrowLength, double arrowWidth, const ViewConfig& viewConfig) {
349  drawSegmentBase(helper, start, end, -1, arrowLength, arrowWidth, viewConfig);
350 }
351 
353  IVisualization3D& helper, const Vector3D& start, const Vector3D& end,
354  double arrowLength, double arrowWidth, const ViewConfig& viewConfig) {
355  drawSegmentBase(helper, start, end, 1, arrowLength, arrowWidth, viewConfig);
356 }
357 
359  const Vector3D& start,
360  const Vector3D& end,
361  double arrowLength, double arrowWidth,
362  const ViewConfig& viewConfig) {
363  drawSegmentBase(helper, start, end, 2, arrowLength, arrowWidth, viewConfig);
364 }