VGM Version 5.5
Loading...
Searching...
No Matches
Arb8Splitter.cxx
Go to the documentation of this file.
1// -----------------------------------------------------------------------
2// The Geant4GM package of the Virtual Geometry Model
3// Copyright (C) 2007, Ivana Hrivnacova
4// All rights reserved.
5//
6// For the licensing terms see vgm/LICENSE.
7// Contact: ivana@ipno.in2p3.fr
8// -----------------------------------------------------------------------
9
11
12#include <algorithm>
13#include <cmath>
14#include <limits>
15
16namespace {
17
18struct Vector2
19{
20 double x;
21 double y;
22};
23
24//_____________________________________________________________________________
25Vector2 Edge(const std::vector<VGM::TwoVector>& vertices, int offset, int index)
26{
27 const int next = (index + 1) % 4;
28 return { vertices[offset + next].first - vertices[offset + index].first,
29 vertices[offset + next].second - vertices[offset + index].second };
30}
31
32//_____________________________________________________________________________
33double Dot(const Vector2& lhs, const Vector2& rhs)
34{
35 return lhs.x * rhs.x + lhs.y * rhs.y;
36}
37
38} // namespace
39
40//_____________________________________________________________________________
42 const std::vector<VGM::TwoVector>& vertices, Arb8Split& split)
43{
44 split = Arb8Split{};
45 if (!(halfLength > 0.) || !std::isfinite(halfLength) ||
46 vertices.size() != 8) {
48 }
49 for (const auto& vertex : vertices) {
50 if (!std::isfinite(vertex.first) || !std::isfinite(vertex.second)) {
52 }
53 }
54
55 // At fractional height t, corresponding end edges a and b interpolate as
56 // m(t)=(1-t)*a+t*b. Both new traps satisfy the 90-degree restriction when
57 // a.m(t)>=0 and m(t).b>=0. Intersect the permitted t intervals of all faces.
58 double lowerBound = 0.;
59 double upperBound = 1.;
60 bool splitNeeded = false;
61 for (int i = 0; i < 4; ++i) {
62 const Vector2 bottom = Edge(vertices, 0, i);
63 const Vector2 top = Edge(vertices, 4, i);
64 const double bottom2 = Dot(bottom, bottom);
65 const double top2 = Dot(top, top);
66
67 // G4GenericTrap treats a face with a collapsed end edge as planar.
68 if (bottom2 == 0. || top2 == 0.) continue;
69
70 const double product = Dot(bottom, top);
71 if (product >= 0.) continue;
72
73 splitNeeded = true;
74 lowerBound = std::max(lowerBound, -product / (top2 - product));
75 upperBound = std::min(upperBound, bottom2 / (bottom2 - product));
76 }
77
78 if (!splitNeeded) return Arb8SplitResult::kNoSplitNeeded;
79
80 // Avoid exactly 90 degrees: round-off in G4GenericTrap's acos() can turn a
81 // boundary value into an angle just above its limit.
82 const double margin = 64. * std::numeric_limits<double>::epsilon();
83 if (!(upperBound - lowerBound > 2. * margin)) {
85 }
86
87 double fraction = 0.5;
88 if (fraction <= lowerBound + margin || fraction >= upperBound - margin) {
89 fraction = 0.5 * (lowerBound + upperBound);
90 }
91
92 std::vector<VGM::TwoVector> middle;
93 middle.reserve(4);
94 for (int i = 0; i < 4; ++i) {
95 middle.emplace_back(vertices[i].first + fraction * (vertices[i + 4].first -
96 vertices[i].first),
97 vertices[i].second +
98 fraction * (vertices[i + 4].second - vertices[i].second));
99 }
100
101 split.fraction = fraction;
102 split.lowerHalfLength = halfLength * fraction;
103 split.lowerZOffset = halfLength * (fraction - 1.);
104 split.upperHalfLength = halfLength * (1. - fraction);
105 split.upperZOffset = halfLength * fraction;
106
107 split.lowerVertices.reserve(8);
108 split.upperVertices.reserve(8);
109 split.lowerVertices.insert(
110 split.lowerVertices.end(), vertices.begin(), vertices.begin() + 4);
111 split.lowerVertices.insert(
112 split.lowerVertices.end(), middle.begin(), middle.end());
113 split.upperVertices.insert(
114 split.upperVertices.end(), middle.begin(), middle.end());
115 split.upperVertices.insert(
116 split.upperVertices.end(), vertices.begin() + 4, vertices.end());
117
119}
Arb8SplitResult SplitArb8ForGenericTrap(double halfLength, const std::vector< VGM::TwoVector > &vertices, Arb8Split &split)
Split an Arb8 whose corresponding end edges form angles greater than 90 degrees into two pieces accep...
Parameters of two G4GenericTrap-compatible pieces obtained by cutting an Arb8 with a plane perpendicu...
std::vector< VGM::TwoVector > upperVertices
std::vector< VGM::TwoVector > lowerVertices