CMS 3D CMS Logo

DDCutTubsFromPoints.cc
Go to the documentation of this file.
1 // File: DDCutTubsFromPoints.cc
3 // Description: Create a ring of CutTubs segments from points on the rim.
5 
14 #include <CLHEP/Units/GlobalPhysicalConstants.h>
15 #include <CLHEP/Units/SystemOfUnits.h>
16 
17 #include <cmath>
18 #include <map>
19 #include <string>
20 #include <vector>
21 
22 // This algorithm creates a ring made of CutTubs segments from the phi,z points
23 // of the rings "corners".
24 // The algorithm only defines and places two copies of a single Solid with the given name.
25 class DDCutTubsFromPoints : public DDAlgorithm {
26 public:
27  //Constructor and Destructor
29  ~DDCutTubsFromPoints() override;
30 
31  void initialize(const DDNumericArguments& nArgs,
32  const DDVectorArguments& vArgs,
33  const DDMapArguments& mArgs,
34  const DDStringArguments& sArgs,
35  const DDStringVectorArguments& vsArgs) override;
36 
37  void execute(DDCompactView& cpv) override;
38 
39 private:
40  struct Section {
41  double phi; // phi position of this edge
42  double z_l; // -Z end (cuttubs l plane)
43  double z_t; // +Z end (cuttubs t plane)
44  // radius is implicitly r_min
45  };
46 
47  double r_min;
48  double r_max;
49  double z_pos;
51 
52  // a segment is produced between each two consecutive sections that have a
53  // non-zero phi distance. Sections with zero phi distance can be used to
54  // create sharp jumps.
55  std::vector<Section> sections;
56  // this solid will be defined.
58 };
59 
61  LogDebug("TrackerGeom") << "DDCutTubsFromPoints info: Creating an instance";
62 }
63 
65 
67  const DDVectorArguments& vArgs,
68  const DDMapArguments&,
69  const DDStringArguments& sArgs,
70  const DDStringVectorArguments&) {
71  r_min = nArgs["rMin"];
72  r_max = nArgs["rMax"];
73  z_pos = nArgs["zPos"];
74  material = DDMaterial(sArgs["Material"]);
75 
76  auto phis_name = DDName(sArgs["Phi"]);
77  auto z_ls_name = DDName(sArgs["z_l"]);
78  auto z_ts_name = DDName(sArgs["z_t"]);
79  DDVector phis(phis_name);
80  DDVector z_ls(z_ls_name);
81  DDVector z_ts(z_ts_name);
82 
83  assert(phis.size() == z_ls.size());
84  assert(phis.size() == z_ts.size());
85 
86  for (unsigned i = 0; i < phis.size(); i++) {
87  Section s = {phis[i], z_ls[i], z_ts[i]};
88  sections.emplace_back(s);
89  }
90  assert(!sections.empty());
91 
92  solidOutput = DDName(sArgs["SolidName"]);
93 
94  std::string idNameSpace = DDCurrentNamespace::ns();
95  DDName parentName = parent().name();
96  LogDebug("TrackerGeom") << "DDCutTubsFromPoints debug: Parent " << parentName << "\tSolid " << solidOutput
97  << " NameSpace " << idNameSpace << "\tnumber of sections " << sections.size();
98 }
99 
100 static double square(double x) { return x * x; }
101 
103  // radius for plane calculations
104  // We use r_max here, since P3 later has a Z that is always more inside
105  // than the extreme points. This means the cutting planes have outwards
106  // slopes in r-Z, and the corner at r_max could stick out of the bounding
107  // volume otherwise.
108  double r = r_max;
109 
110  // min and max z for the placement in the end
111  double min_z = 1e9;
112  double max_z = -1e9;
113 
114  // counter of actually produced segments (excluding skipped ones)
115  int segment = 0;
116 
117  // the segments and their corresponding offset (absolute, as in the input)
118  std::vector<DDSolid> segments;
119  std::vector<double> offsets;
120 
121  Section s1 = sections[0];
122  for (Section s2 : sections) {
123  if (s1.phi != s2.phi) {
124  segment++;
125  // produce segment s1-s2.
126  DDName segname(solidOutput.name() + "_seg_" + std::to_string(segment), solidOutput.ns());
127 
128  double phi1 = s1.phi;
129  double phi2 = s2.phi;
130 
131  // track the min/max to properly place&align later
132  if (s2.z_l < min_z)
133  min_z = s2.z_l;
134  if (s2.z_t > max_z)
135  max_z = s2.z_t;
136 
137  double P1_z_l = s1.z_l;
138  double P1_z_t = s1.z_t;
139  double P2_z_l = s2.z_l;
140  double P2_z_t = s2.z_t;
141 
142  double P1_x_t = cos(phi1) * r;
143  double P1_x_l = cos(phi1) * r;
144  double P1_y_t = sin(phi1) * r;
145  double P1_y_l = sin(phi1) * r;
146 
147  double P2_x_t = cos(phi2) * r;
148  double P2_x_l = cos(phi2) * r;
149  double P2_y_t = sin(phi2) * r;
150  double P2_y_l = sin(phi2) * r;
151 
152  // each cutting plane is defined by P1-3. P1-2 are corners of the
153  // segment, P3 is at r=0 with the "average" z to get a nice cut.
154  double P3_z_l = (P1_z_l + P2_z_l) / 2;
155  double P3_z_t = (P1_z_t + P2_z_t) / 2;
156 
157  // we only have one dz to position both planes. The anchor is implicitly
158  // between the P3's, we have to use an offset later to make the segments
159  // line up correctly.
160  double dz = (P3_z_t - P3_z_l) / 2;
161  double offset = (P3_z_t + P3_z_l) / 2;
162 
163  // the plane is defined by P1-P3 and P2-P3; since P3 is at r=0 we
164  // only need the z.
165  double D1_z_l = P1_z_l - P3_z_l;
166  double D2_z_l = P2_z_l - P3_z_l;
167 
168  // the normal is then the cross product...
169  double n_x_l = (P1_y_l * D2_z_l) - (D1_z_l * P2_y_l);
170  double n_y_l = (D1_z_l * P2_x_l) - (P1_x_l * D2_z_l);
171  double n_z_l = (P1_x_l * P2_y_l) - (P1_y_l * P2_x_l);
172 
173  // ... normalized.
174  // flip the sign here (but not for t) since root wants it like that.
175  double norm = -sqrt(square(n_x_l) + square(n_y_l) + square(n_z_l));
176  n_x_l /= norm;
177  n_y_l /= norm;
178  n_z_l /= norm;
179 
180  // same game for the t side.
181  double D1_z_t = P1_z_t - P3_z_t;
182  double D2_z_t = P2_z_t - P3_z_t;
183 
184  double n_x_t = (P1_y_t * D2_z_t) - (D1_z_t * P2_y_t);
185  double n_y_t = (D1_z_t * P2_x_t) - (P1_x_t * D2_z_t);
186  double n_z_t = (P1_x_t * P2_y_t) - (P1_y_t * P2_x_t);
187 
188  norm = sqrt(square(n_x_t) + square(n_y_t) + square(n_z_t));
189  n_x_t /= norm;
190  n_y_t /= norm;
191  n_z_t /= norm;
192 
193  // the cuttubs wants a delta phi
194  double dphi = phi2 - phi1;
195 
196  DDSolid seg =
197  DDSolidFactory::cuttubs(segname, dz, r_min, r_max, phi1, dphi, n_x_l, n_y_l, n_z_l, n_x_t, n_y_t, n_z_t);
198  segments.emplace_back(seg);
199  offsets.emplace_back(offset);
200  }
201  s1 = s2;
202  }
203 
204  assert(segments.size() >= 2); // less would be special cases
205 
206  DDSolid solid = segments[0];
207  // placment happens relative to the first member of the union
208  double shift = offsets[0];
209 
210  for (unsigned i = 1; i < segments.size() - 1; i++) {
211  // each sub-union needs a name. Well.
212  DDName unionname(solidOutput.name() + "_uni_" + std::to_string(i + 1), solidOutput.ns());
214  unionname, solid, segments[i], DDTranslation(0, 0, offsets[i] - shift), DDRotation());
215  }
216 
218  solid,
219  segments[segments.size() - 1],
220  DDTranslation(0, 0, offsets[segments.size() - 1] - shift),
221  DDRotation());
222 
223  // remove the common offset from the input, to get sth. aligned at z=0.
224  double offset = -shift + (min_z + (max_z - min_z) / 2);
225 
227 
228  // This is not as generic as the name promises, but it is hard to make a
229  // solid w/o placing it.
230  DDRotation rot180("pixfwdCommon:Z180");
231  cpv.position(logical, parent(), 1, DDTranslation(0, 0, z_pos - offset), DDRotation());
232  cpv.position(logical, parent(), 2, DDTranslation(0, 0, z_pos - offset), rot180);
233 }
234 
235 DEFINE_EDM_PLUGIN(DDAlgorithmFactory, DDCutTubsFromPoints, "track:DDCutTubsFromPoints");
void position(const DDLogicalPart &self, const DDLogicalPart &parent, const std::string &copyno, const DDTranslation &trans, const DDRotation &rot, const DDDivision *div=nullptr)
size_t size() const
the size of the array of values
Definition: DDVector.h:36
DDMaterial is used to define and access material information.
Definition: DDMaterial.h:45
std::vector< Section > sections
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
DDName is used to identify DDD entities uniquely.
Definition: DDName.h:17
static std::string & ns()
assert(be >=bs)
Compact representation of the geometrical detector hierarchy.
Definition: DDCompactView.h:81
A DDSolid represents the shape of a part.
Definition: DDSolid.h:39
static std::string to_string(const XMLCh *ch)
Represents a uniquely identifyable rotation matrix.
Definition: DDTransform.h:57
void initialize(const DDNumericArguments &nArgs, const DDVectorArguments &vArgs, const DDMapArguments &mArgs, const DDStringArguments &sArgs, const DDStringVectorArguments &vsArgs) override
static DDSolid cuttubs(const DDName &name, double zhalf, double rIn, double rOut, double startPhi, double deltaPhi, double lx, double ly, double lz, double tx, double ty, double tz)
Definition: DDSolid.cc:672
const std::string & name() const
Returns the name.
Definition: DDName.cc:41
T sqrt(T t)
Definition: SSEVec.h:23
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
A DDLogicalPart aggregates information concerning material, solid and sensitveness ...
Definition: DDLogicalPart.h:93
a named constant corresponding to the DDL-XML tag <Constant> and <ConstantsVector> ...
Definition: DDVector.h:18
static double square(double x)
static unsigned int const shift
float x
#define DEFINE_EDM_PLUGIN(factory, type, name)
static DDSolid unionSolid(const DDName &name, const DDSolid &a, const DDSolid &b, const DDTranslation &t, const DDRotation &r)
Definition: DDSolid.cc:594
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > DDTranslation
Definition: DDTranslation.h:7
void execute(DDCompactView &cpv) override
#define LogDebug(id)
const std::string & ns() const
Returns the namespace.
Definition: DDName.cc:52