Project
Loading...
Searching...
No Matches
TGeoGeometryUtils.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
15
17#include <TGeoShape.h>
18#include <TGeoTessellated.h>
19#include <TGeoBBox.h>
20#include <TGeoMatrix.h>
21#include <TBuffer3D.h>
22#include <TString.h>
23#include <cmath>
24#include <vector>
25
26namespace o2
27{
28namespace base
29{
30
31namespace
32{
33// some helpers to interpret TGeo TBuffer3D output
34// and convert it to surface triangles (reengineered from TGeo code)
35
36std::vector<int> BuildVertexLoop(const TBuffer3D& buf,
37 const std::vector<int>& segs)
38{
39 // adjacency list
40 std::unordered_map<int, std::vector<int>> adj;
41
42 for (int s : segs) {
43 int a = buf.fSegs[3 * s + 1];
44 int b = buf.fSegs[3 * s + 2];
45 adj[a].push_back(b);
46 adj[b].push_back(a);
47 }
48
49 // start from any vertex
50 int start = adj.begin()->first;
51 int prev = -1;
52 int curr = start;
53
54 std::vector<int> loop;
55
56 while (true) {
57 loop.push_back(curr);
58
59 const auto& nbrs = adj[curr];
60 int next = -1;
61
62 for (int n : nbrs) {
63 if (n != prev) {
64 next = n;
65 break;
66 }
67 }
68
69 if (next == -1 || next == start) {
70 break;
71 }
72
73 prev = curr;
74 curr = next;
75 }
76 return loop;
77}
78
79std::vector<std::vector<int>> ExtractPolygons(const TBuffer3D& buf)
80{
81 std::vector<std::vector<int>> polys;
82 Int_t idx = 0;
83
84 for (Int_t ip = 0; ip < buf.NbPols(); ++ip) {
85
86 idx++; // color
87 Int_t nseg = buf.fPols[idx++];
88
89 std::vector<int> segs(nseg);
90 for (Int_t i = 0; i < nseg; ++i) {
91 segs[i] = buf.fPols[idx++];
92 }
93
94 auto verts = BuildVertexLoop(buf, segs);
95 if (verts.size() >= 3) {
96 polys.push_back(std::move(verts));
97 }
98 }
99
100 return polys;
101}
102
103std::vector<std::array<int, 3>>
104 Triangulate(const std::vector<std::vector<int>>& polys)
105{
106 std::vector<std::array<int, 3>> tris;
107 for (const auto& poly : polys) {
108 int nv = poly.size();
109 if (nv < 3) {
110 continue;
111 }
112
113 int v0 = poly[0];
114 for (int i = 1; i < nv - 1; ++i) {
115 tris.push_back({{v0, poly[i], poly[i + 1]}});
116 }
117 }
118 return tris;
119}
120
121TGeoTessellated* MakeTessellated(const TBuffer3D& buf)
122{
123 auto polys = ExtractPolygons(buf);
124 auto tris = Triangulate(polys);
125 int i = 0;
126 auto* tess = new TGeoTessellated("tess");
127 const Double_t* p = buf.fPnts;
128 for (auto& t : tris) {
129 tess->AddFacet(
130 TGeoTessellated::Vertex_t{p[3 * t[0]], p[3 * t[0] + 1], p[3 * t[0] + 2]},
131 TGeoTessellated::Vertex_t{p[3 * t[1]], p[3 * t[1] + 1], p[3 * t[1] + 2]},
132 TGeoTessellated::Vertex_t{p[3 * t[2]], p[3 * t[2] + 1], p[3 * t[2] + 2]});
133 }
134 tess->CloseShape();
135 return tess;
136}
137} // end anonymous namespace
138
141TGeoTessellated* TGeoGeometryUtils::TGeoShapeToTGeoTessellated(TGeoShape const* shape)
142{
143 auto& buf = shape->GetBuffer3D(TBuffer3D::kRawSizes | TBuffer3D::kRaw | TBuffer3D::kCore, false);
144 auto tes = MakeTessellated(buf);
145 return tes;
146}
147
149void TGeoGeometryUtils::makeHalfSpaceBox(const char* name, const double p[3], const double n[3], double reach)
150{
151 // TGeoHalfSpace contains the points x with (p - x) . n >= 0, and normalizes n itself.
152 double nn[3] = {n[0], n[1], n[2]};
153 const double norm = std::sqrt(nn[0] * nn[0] + nn[1] * nn[1] + nn[2] * nn[2]);
154 for (auto& c : nn) {
155 c /= norm;
156 }
157
158 // an orthonormal triad (u, v, nn); the seed is chosen to stay away from nn
159 double a[3] = {1., 0., 0.};
160 if (std::abs(nn[0]) > 0.9) {
161 a[0] = 0.;
162 a[1] = 1.;
163 }
164 double u[3] = {a[1] * nn[2] - a[2] * nn[1], a[2] * nn[0] - a[0] * nn[2], a[0] * nn[1] - a[1] * nn[0]};
165 const double unorm = std::sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
166 for (auto& c : u) {
167 c /= unorm;
168 }
169 const double v[3] = {nn[1] * u[2] - nn[2] * u[1], nn[2] * u[0] - nn[0] * u[2], nn[0] * u[1] - nn[1] * u[0]};
170
171 // rotation taking the local z axis onto nn (TGeoRotation stores the matrix row-wise,
172 // so the images of the local axes are its columns)
173 const double m[9] = {u[0], v[0], nn[0], u[1], v[1], nn[1], u[2], v[2], nn[2]};
174 auto* rot = new TGeoRotation(TString::Format("%s_rot", name));
175 rot->SetMatrix(m);
176
177 // centre the cube one half-size behind the plane, so its +z face lies on the plane
178 auto* tr = new TGeoCombiTrans(TString::Format("%s_tr", name), p[0] - reach * nn[0], p[1] - reach * nn[1],
179 p[2] - reach * nn[2], rot);
180 tr->RegisterYourself();
181
182 new TGeoBBox(name, reach, reach, reach);
183}
184
185} // namespace base
186} // namespace o2
int32_t i
uint32_t c
Definition RawData.h:2
Collection of utility functions for TGeo.
static TGeoTessellated * TGeoShapeToTGeoTessellated(TGeoShape const *)
< Transform any (primitive) TGeoShape to a tessellated representation
static void makeHalfSpaceBox(const char *name, const double p[3], const double n[3], double reach)
GLdouble n
Definition glcorearb.h:1982
const GLfloat * m
Definition glcorearb.h:4066
const GLdouble * v
Definition glcorearb.h:832
GLuint const GLchar * name
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLfloat v0
Definition glcorearb.h:811
GLuint start
Definition glcorearb.h:469
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...