File indexing completed on 2026-04-17 08:35:34
0001 #include <VecGeom/surfaces/BrepHelper.h>
0002 #include <VecGeom/surfaces/base/CpuTypes.h>
0003 #include <VecGeom/management/Logger.h>
0004
0005 namespace vgbrep {
0006
0007 template <typename Real_i>
0008 struct SideIteratorSlices {
0009 using VecInt_t = std::vector<int>;
0010 std::vector<const VecInt_t *> fSlices;
0011 int fNslices{0};
0012 int fNsurf{0};
0013 int fCrtSlice{0};
0014 int fCrt{0};
0015 bool fDone{true};
0016
0017 SideIteratorSlices(const Side &side, Vector3D<Real_i> const &amin, Vector3D<Real_i> const &amax,
0018 CPUsurfData<vecgeom::Precision> const &cpudata)
0019 {
0020 if (side.fDivision < 0) {
0021
0022 fNsurf = side.fNsurf;
0023 fDone = false;
0024 return;
0025 }
0026 auto const &div = cpudata.fSideDivisions[side.fDivision];
0027 int u1, u2, v1, v2;
0028 auto nslices = div.GetNslices(amin, amax, u1, u2, v1, v2);
0029 if (nslices == 0) return;
0030 fDone = false;
0031 for (auto indU = u1; indU <= u2; ++indU) {
0032 for (auto indV = v1; indV <= v2; ++indV) {
0033 auto slice = div.GetSlice(indU, indV);
0034 if (slice->size()) fSlices.push_back(slice);
0035 }
0036 }
0037 fNslices = fSlices.size();
0038 if (fNslices == 0) fDone = true;
0039 }
0040
0041 VECCORE_ATT_HOST_DEVICE
0042 VECGEOM_FORCE_INLINE
0043 bool Done() const { return fDone; }
0044
0045 VECCORE_ATT_HOST_DEVICE VECGEOM_FORCE_INLINE int operator()()
0046 {
0047 if (fNsurf > 0) return fCrt;
0048 return (*fSlices[fCrtSlice])[fCrt];
0049 }
0050
0051 VECCORE_ATT_HOST_DEVICE
0052 VECGEOM_FORCE_INLINE
0053 SideIteratorSlices &operator++()
0054 {
0055 if (fNsurf > 0) {
0056
0057 if (++fCrt > (fNsurf - 1)) fDone = true;
0058 return *this;
0059 }
0060 auto const &slice = *fSlices[fCrtSlice];
0061 fCrt = (fCrt + 1) % slice.size();
0062 if (fCrt == 0) fCrtSlice++;
0063 if (fCrtSlice == fNslices) fDone = true;
0064 return *this;
0065 }
0066 };
0067
0068 template <typename Real_t>
0069 BrepHelper<Real_t>::BrepHelper()
0070 : fSurfData(&SurfData<Real_t>::Instance()), fCPUdata(CPUsurfData<vecgeom::Precision>::Instance())
0071 {
0072 static_assert(std::is_same<CPUsurfData_t, CPUsurfData<vecgeom::Precision>>::value,
0073 "CPUsurfData_t must be CPUsurfData<vecgeom::Precision>");
0074 static_assert(std::is_same<Real_t, double>::value || std::is_same<Real_t, float>::value,
0075 "Real_t must be either double or float");
0076 }
0077
0078 template <typename Real_t>
0079 BrepHelper<Real_t> &BrepHelper<Real_t>::Instance()
0080 {
0081 static BrepHelper<Real_t> instance;
0082 return instance;
0083 }
0084
0085 template <typename Real_t>
0086 BrepHelper<Real_t>::~BrepHelper()
0087 {
0088 if (fSurfData) ClearData();
0089 }
0090
0091 template <typename Real_t>
0092 void BrepHelper<Real_t>::ClearData()
0093 {
0094
0095 fCPUdata.Clear();
0096
0097 fSurfData->Clear();
0098 fSurfData = nullptr;
0099 }
0100
0101 template <typename Real_t>
0102 void BrepHelper<Real_t>::SortSides(int common_id)
0103 {
0104
0105 auto sortFrames = [&](Side &side) {
0106 if (!side.fNsurf) return;
0107 std::sort(side.fSurfaces, side.fSurfaces + side.fNsurf,
0108 [&](int i, int j) { return fCPUdata.fFramedSurf[i] < fCPUdata.fFramedSurf[j]; });
0109 };
0110
0111
0112 auto findParentFramedSurf = [&](Side &side) {
0113 if (!side.fNsurf) return;
0114 int top_parent = side.fNsurf - 1;
0115 int num_parents = 0;
0116
0117 for (auto parent_ind = top_parent; parent_ind >= 0; --parent_ind) {
0118 auto &parent_frame = fCPUdata.fFramedSurf[side.fSurfaces[parent_ind]];
0119 if (parent_frame.fParent < 0) num_parents++;
0120
0121 auto parent_navind = parent_frame.fState;
0122
0123 for (int i = 0; i < parent_ind; ++i) {
0124 auto &child_frame = fCPUdata.fFramedSurf[side.fSurfaces[i]];
0125 auto navind = child_frame.fState;
0126 if (vecgeom::NavigationState::IsDescendentImpl(navind, parent_navind)) {
0127
0128 if (!child_frame.fEmbedded) {
0129 auto intersect_type = fCPUdata.CheckFrames(parent_frame, child_frame);
0130 child_frame.fEmbedded =
0131 (intersect_type == FrameIntersect::kEmbedding) || (intersect_type == FrameIntersect::kEqual);
0132 }
0133 child_frame.fParent = parent_ind;
0134 }
0135 }
0136 }
0137
0138
0139 for (auto parent_ind = top_parent; parent_ind >= 0; --parent_ind) {
0140 auto &parent_frame = fCPUdata.fFramedSurf[side.fSurfaces[parent_ind]];
0141
0142 auto parent_navind = parent_frame.fState;
0143 for (int i = 0; i < parent_ind; ++i) {
0144 auto &child_frame = fCPUdata.fFramedSurf[side.fSurfaces[i]];
0145 auto navind = child_frame.fState;
0146 if (vecgeom::NavigationState::IsDescendentImpl(navind, parent_navind)) {
0147
0148 if (!child_frame.fEmbedded) {
0149
0150
0151
0152
0153
0154
0155
0156 bool multi_parent = false;
0157 if (parent_ind != top_parent)
0158 multi_parent = fCPUdata.fFramedSurf[side.fSurfaces[parent_ind + 1]].fState == parent_navind;
0159 if (parent_ind != 0)
0160 multi_parent |= fCPUdata.fFramedSurf[side.fSurfaces[parent_ind - 1]].fState == parent_navind;
0161 if (multi_parent) continue;
0162 if (parent_frame.fEmbedding && child_frame.fLogicId == 0) {
0163 VECGEOM_LOG(warning) << "Non-embedded frame " << i << " having embedding parent " << parent_ind
0164 << " on CS " << common_id;
0165 if (fVerbose > 0) {
0166 PrintFramedSurface(child_frame);
0167 PrintFramedSurface(parent_frame);
0168
0169 fCPUdata.CheckFrames(parent_frame, child_frame);
0170 }
0171 }
0172 }
0173 }
0174 }
0175 }
0176 side.fNumParents = num_parents;
0177 VECGEOM_ASSERT(num_parents > 0);
0178 };
0179
0180 sortFrames(fCPUdata.fCommonSurfaces[common_id].fLeftSide);
0181 sortFrames(fCPUdata.fCommonSurfaces[common_id].fRightSide);
0182 findParentFramedSurf(fCPUdata.fCommonSurfaces[common_id].fLeftSide);
0183 findParentFramedSurf(fCPUdata.fCommonSurfaces[common_id].fRightSide);
0184 }
0185
0186 template <typename Real_t>
0187 void BrepHelper<Real_t>::ComputeDefaultStates(int common_id)
0188 {
0189 using vecgeom::NavigationState;
0190
0191 Side &left = fCPUdata.fCommonSurfaces[common_id].fLeftSide;
0192 Side &right = fCPUdata.fCommonSurfaces[common_id].fRightSide;
0193 VECGEOM_ASSERT(left.fNsurf > 0 || right.fNsurf > 0);
0194
0195 NavIndex_t default_ind = 0;
0196
0197
0198 auto getCommonState = [&](NavIndex_t const &s1, NavIndex_t const &s2) {
0199 NavIndex_t a1(s1), a2(s2);
0200
0201 while (NavigationState::GetLevelImpl(a1) > NavigationState::GetLevelImpl(a2))
0202 NavigationState::PopImpl(a1);
0203 while (NavigationState::GetLevelImpl(a2) > NavigationState::GetLevelImpl(a1))
0204 NavigationState::PopImpl(a2);
0205
0206
0207 while (a1 != a2) {
0208 NavigationState::PopImpl(a1);
0209 NavigationState::PopImpl(a2);
0210 }
0211 return a1;
0212 };
0213
0214 int minlevel = 10000;
0215 for (int isurf = 0; isurf < left.fNsurf; ++isurf) {
0216 auto navind = fCPUdata.fFramedSurf[left.fSurfaces[isurf]].fState;
0217 minlevel = std::min(minlevel, (int)NavigationState::GetLevelImpl(navind));
0218 }
0219 for (int isurf = 0; isurf < right.fNsurf; ++isurf) {
0220 auto navind = fCPUdata.fFramedSurf[right.fSurfaces[isurf]].fState;
0221 minlevel = std::min(minlevel, (int)NavigationState::GetLevelImpl(navind));
0222 }
0223
0224
0225 if (left.fNsurf > 0)
0226 default_ind = fCPUdata.fFramedSurf[left.fSurfaces[0]].fState;
0227 else if (right.fNsurf > 0)
0228 default_ind = fCPUdata.fFramedSurf[right.fSurfaces[0]].fState;
0229
0230 for (int isurf = 0; isurf < left.fNsurf; ++isurf)
0231 default_ind = getCommonState(default_ind, fCPUdata.fFramedSurf[left.fSurfaces[isurf]].fState);
0232 for (int isurf = 0; isurf < right.fNsurf; ++isurf)
0233 default_ind = getCommonState(default_ind, fCPUdata.fFramedSurf[right.fSurfaces[isurf]].fState);
0234
0235 if (NavigationState::GetLevelImpl(default_ind) == minlevel) NavigationState::PopImpl(default_ind);
0236 fCPUdata.fCommonSurfaces[common_id].fDefaultState = default_ind;
0237 }
0238
0239 template <typename Real_t>
0240 WindowMask<double> BrepHelper<Real_t>::GetPlanarFrameExtent(
0241 FramedSurface<Real_t, TransformationMP<Real_t>> const &framed_surf, TransformationMP<Real_t> const &trans)
0242 {
0243
0244 auto updateExtent = [](WindowMask<double> &e, Vector3D<double> const &pt) {
0245 e.rangeU[0] = std::min(e.rangeU[0], pt[0]);
0246 e.rangeU[1] = std::max(e.rangeU[1], pt[0]);
0247 e.rangeV[0] = std::min(e.rangeV[0], pt[1]);
0248 e.rangeV[1] = std::max(e.rangeV[1], pt[1]);
0249 };
0250
0251 WindowMask<double> ext{vecgeom::kInfLength, -vecgeom::kInfLength, vecgeom::kInfLength, -vecgeom::kInfLength};
0252 FrameType frame_type = framed_surf.fFrame.type;
0253 Vector3D<double> local;
0254
0255 WindowMask<double> extentL;
0256
0257 switch (frame_type) {
0258 case FrameType::kWindow: {
0259 auto const &maskLocal = fCPUdata.fWindowMasks[framed_surf.fFrame.id];
0260 maskLocal.GetExtent(extentL);
0261 break;
0262 }
0263 case FrameType::kRing: {
0264 auto const &maskLocal = fCPUdata.fRingMasks[framed_surf.fFrame.id];
0265 maskLocal.GetExtent(extentL);
0266 break;
0267 }
0268 case FrameType::kQuadrilateral: {
0269 WindowMask_t extLocal;
0270 auto const &quad = fCPUdata.fQuadMasks[framed_surf.fFrame.id];
0271 quad.GetExtent(extentL);
0272 break;
0273 }
0274 case FrameType::kTriangle: {
0275 TriangleMask_t extLocal;
0276 auto const &maskLocal = fCPUdata.fTriangleMasks[framed_surf.fFrame.id];
0277 maskLocal.GetExtent(extentL);
0278 break;
0279 }
0280 default:
0281 VECGEOM_VALIDATE(0, << "Not implemented");
0282 }
0283
0284
0285 local = trans.InverseTransform(Vector3D<double>{extentL.rangeU[0], extentL.rangeV[0], 0});
0286 updateExtent(ext, local);
0287 local = trans.InverseTransform(Vector3D<double>{extentL.rangeU[0], extentL.rangeV[1], 0});
0288 updateExtent(ext, local);
0289 local = trans.InverseTransform(Vector3D<double>{extentL.rangeU[1], extentL.rangeV[1], 0});
0290 updateExtent(ext, local);
0291 local = trans.InverseTransform(Vector3D<double>{extentL.rangeU[1], extentL.rangeV[0], 0});
0292 updateExtent(ext, local);
0293 return ext;
0294 }
0295
0296 template <typename Real_t>
0297 WindowMask<double> BrepHelper<Real_t>::ComputePlaneExtent(const Side &side)
0298 {
0299
0300
0301 auto updatePlaneExtent = [](WindowMask<double> &e, WindowMask<double> const &elocal) {
0302 e.rangeU[0] = std::min(e.rangeU[0], elocal.rangeU[0]);
0303 e.rangeU[1] = std::max(e.rangeU[1], elocal.rangeU[1]);
0304 e.rangeV[0] = std::min(e.rangeV[0], elocal.rangeV[0]);
0305 e.rangeV[1] = std::max(e.rangeV[1], elocal.rangeV[1]);
0306 };
0307
0308
0309 WindowMask<double> ext{vecgeom::kInfLength, -vecgeom::kInfLength, vecgeom::kInfLength, -vecgeom::kInfLength};
0310
0311
0312 for (int i = 0; i < side.fNsurf; ++i) {
0313
0314 auto &framed_surf = fCPUdata.fFramedSurf[side.fSurfaces[i]];
0315 auto extentL = GetPlanarFrameExtent(framed_surf, framed_surf.fTrans);
0316
0317 updatePlaneExtent(ext, extentL);
0318 }
0319
0320 return ext;
0321 }
0322
0323 template <typename Real_t>
0324 ZPhiMask<double> BrepHelper<Real_t>::ComputeCylinderExtent(const Side &side)
0325 {
0326 auto const &sideext = fCPUdata.GetZPhiMask(fCPUdata.fFramedSurf[side.fSurfaces[0]].fFrame.id);
0327 auto sideext_local = sideext.InverseTransform(fCPUdata.fFramedSurf[side.fSurfaces[0]].fTrans);
0328
0329
0330 for (int i = 1; i < side.fNsurf; ++i) {
0331
0332 auto &framed_surf = fCPUdata.fFramedSurf[side.fSurfaces[i]];
0333
0334 auto const &extLocal = fCPUdata.GetZPhiMask(framed_surf.fFrame.id);
0335 auto extFrame = extLocal.InverseTransform(framed_surf.fTrans);
0336
0337 bool success = sideext_local.CombineWith(extFrame);
0338 if (!success) {
0339 VECGEOM_LOG(critical) << "ComputeCylinderExtent error";
0340 }
0341 }
0342
0343 return sideext_local;
0344 }
0345
0346 template <typename Real_t>
0347 int BrepHelper<Real_t>::ComputeCylinderDivision(Side &side, ZPhiMask<double> extent_full)
0348 {
0349
0350 SideDivisionCPU divisionZ(AxisType::kZ, extent_full.rangeZ[0], extent_full.rangeZ[1], side.fNsurf);
0351 auto updateRangeZ = [](double z, double &zmin, double &zmax) {
0352 zmin = std::min(zmin, z);
0353 zmax = std::max(zmax, z);
0354 };
0355
0356 for (int i = 0; i < side.fNsurf; ++i) {
0357 auto &framed_surf = fCPUdata.fFramedSurf[side.fSurfaces[i]];
0358 VECGEOM_ASSERT(framed_surf.fFrame.type == FrameType::kZPhi);
0359
0360 Vector3D<double> local;
0361 double zmin{vecgeom::InfinityLength<Real_t>()}, zmax{-vecgeom::InfinityLength<Real_t>()};
0362 auto const &maskLocal = fCPUdata.fZPhiMasks[framed_surf.fFrame.id];
0363 local = framed_surf.fTrans.InverseTransform(Vector3D<double>{0, 0, maskLocal.rangeZ[0]});
0364 updateRangeZ(local[2], zmin, zmax);
0365 local = framed_surf.fTrans.InverseTransform(Vector3D<double>{0, 0, maskLocal.rangeZ[1]});
0366 updateRangeZ(local[2], zmin, zmax);
0367 divisionZ.AddCandidate(i, zmin, zmax);
0368 }
0369 if (divisionZ.Efficiency() > 0.01) {
0370
0371 side.fDivision = fCPUdata.fSideDivisions.size();
0372 fCPUdata.fSideDivisions.push_back(divisionZ);
0373 }
0374 return side.fDivision;
0375 }
0376
0377 template <typename Real_t>
0378 void BrepHelper<Real_t>::CountTraversals(const CommonSurface<Real_t> &surf, int &nfound, int &ntotal) const
0379 {
0380 auto count_per_side = [&](Side const &side) {
0381 ntotal += side.fNsurf;
0382 for (int i = 0; i < side.fNsurf; ++i) {
0383 auto const &frame = fCPUdata.fFramedSurf[side.fSurfaces[i]];
0384 if (frame.fTraversal > -2) nfound++;
0385 }
0386 };
0387 count_per_side(surf.fLeftSide);
0388 count_per_side(surf.fRightSide);
0389 }
0390
0391 template <typename Real_t>
0392 void BrepHelper<Real_t>::ComputeTraversalForFrame(int common_id, bool left, int iframe)
0393 {
0394 using Vector3D = Vector3D<vecgeom::Precision>;
0395 auto &surf = fCPUdata.fCommonSurfaces[common_id];
0396 Side const &side = left ? surf.fLeftSide : surf.fRightSide;
0397 auto &thisside_frame = fCPUdata.fFramedSurf[side.fSurfaces[iframe]];
0398 Side const &other_side = left ? surf.fRightSide : surf.fLeftSide;
0399 auto setTraversal = [](FramedSurface<double, TransformationMP<double>> &frame, int iframe) {
0400
0401 if (frame.fTraversal == -2) {
0402 frame.fTraversal = iframe;
0403 } else {
0404
0405 if (iframe < frame.fTraversal) frame.fTraversal = iframe;
0406 }
0407 };
0408
0409
0410
0411
0412 bool has_div = other_side.fDivision >= 0;
0413 Vector3D amin, amax;
0414 if (has_div) {
0415 if (surf.fType == SurfaceType::kPlanar) {
0416 if (fCPUdata.fSideDivisions[other_side.fDivision].fAxis == AxisType::kR) {
0417 auto const &ringMask = fCPUdata.fRingMasks[thisside_frame.fFrame.id];
0418 amin[0] = ringMask.rangeR[0];
0419 amax[0] = ringMask.rangeR[1];
0420 } else {
0421
0422 auto extentL = GetPlanarFrameExtent(thisside_frame, thisside_frame.fTrans);
0423 amin.Set(extentL.rangeU[0], extentL.rangeV[0], 0.);
0424 amax.Set(extentL.rangeU[1], extentL.rangeV[1], 0.);
0425 }
0426 } else if (surf.fType == SurfaceType::kCylindrical || surf.fType == SurfaceType::kConical) {
0427 Vector3D local;
0428 amin.Set(0., 0., vecgeom::InfinityLength<Real_t>());
0429 amax.Set(0., 0., -vecgeom::InfinityLength<Real_t>());
0430 auto const &maskLocal = fCPUdata.fZPhiMasks[thisside_frame.fFrame.id];
0431 local = thisside_frame.fTrans.InverseTransform(Vector3D{0, 0, maskLocal.rangeZ[0]});
0432 amin[2] = std::min(amin[2], local[2]);
0433 amax[2] = std::max(amax[2], local[2]);
0434 local = thisside_frame.fTrans.InverseTransform(Vector3D{0, 0, maskLocal.rangeZ[1]});
0435 amin[2] = std::min(amin[2], local[2]);
0436 amax[2] = std::max(amax[2], local[2]);
0437 }
0438 }
0439
0440 bool disjoint = true;
0441 std::set<int> candidates;
0442
0443 for (SideIteratorSlices it(other_side, amin, amax, fCPUdata); !it.Done(); ++it) {
0444 auto j = it();
0445 if (!candidates.insert(j).second) continue;
0446 auto &otherside_frame = fCPUdata.fFramedSurf[other_side.fSurfaces[j]];
0447
0448
0449 if (otherside_frame.fTraversal == -1) continue;
0450
0451
0452 auto intersect_type = fCPUdata.CheckFrames(thisside_frame, otherside_frame);
0453 if (intersect_type == FrameIntersect::kNoIntersect) continue;
0454
0455
0456 disjoint = false;
0457 if (intersect_type == FrameIntersect::kIntersect) {
0458
0459 thisside_frame.fTraversal = -3;
0460 otherside_frame.fTraversal = -3;
0461 break;
0462 }
0463 if (intersect_type == FrameIntersect::kEmbedding) {
0464
0465 if (thisside_frame.fLogicId)
0466 otherside_frame.fTraversal = -3;
0467 else
0468 setTraversal(otherside_frame, iframe);
0469
0470 thisside_frame.fTraversal = -3;
0471 break;
0472 }
0473 if (intersect_type == FrameIntersect::kEqual) {
0474
0475 if (otherside_frame.fLogicId)
0476 thisside_frame.fTraversal = -3;
0477 else
0478 setTraversal(thisside_frame, j);
0479
0480 if (thisside_frame.fLogicId)
0481 otherside_frame.fTraversal = -3;
0482 else
0483 setTraversal(otherside_frame, iframe);
0484 }
0485 if (intersect_type == FrameIntersect::kEmbedded) {
0486
0487 if (otherside_frame.fLogicId)
0488 thisside_frame.fTraversal = -3;
0489 else
0490 setTraversal(thisside_frame, j);
0491 otherside_frame.fTraversal = -3;
0492 }
0493 }
0494 if (disjoint) thisside_frame.fTraversal = -1;
0495 }
0496
0497 template <typename Real_t>
0498 void BrepHelper<Real_t>::ComputeTraversalFrames(int common_id, bool left)
0499 {
0500 auto &surf = fCPUdata.fCommonSurfaces[common_id];
0501 Side const &side = left ? surf.fLeftSide : surf.fRightSide;
0502 Side const &other_side = left ? surf.fRightSide : surf.fLeftSide;
0503 if (other_side.fNsurf == 0) {
0504
0505 for (int i = 0; i < side.fNsurf; ++i)
0506 fCPUdata.fFramedSurf[side.fSurfaces[i]].fTraversal = -1;
0507 return;
0508 }
0509
0510
0511 for (int i = 0; i < side.fNsurf; ++i) {
0512 auto &thisside_frame = fCPUdata.fFramedSurf[side.fSurfaces[i]];
0513
0514 if (thisside_frame.fTraversal == -3 || thisside_frame.fTraversal == -1) continue;
0515
0516 ComputeTraversalForFrame(common_id, left, i);
0517 }
0518 }
0519
0520 template <typename Real_t>
0521 int BrepHelper<Real_t>::ComputePlaneDivision(Side &side, WindowMask<double> extent_full)
0522 {
0523
0524 bool all_rings_id = true;
0525 double ring_max = -vecgeom::kInfLength;
0526 double ring_min = vecgeom::kInfLength;
0527 for (int i = 0; i < side.fNsurf; ++i) {
0528 auto &framed_surf = fCPUdata.fFramedSurf[side.fSurfaces[i]];
0529 FrameType frame_type = framed_surf.fFrame.type;
0530 if (frame_type == FrameType::kRing && !framed_surf.fTrans.HasTranslation()) {
0531 auto const &maskRing = fCPUdata.fRingMasks[framed_surf.fFrame.id];
0532 ring_min = std::min(maskRing.rangeR[0], ring_min);
0533 ring_max = std::max(maskRing.rangeR[1], ring_max);
0534 } else {
0535 all_rings_id = false;
0536 break;
0537 }
0538 }
0539
0540
0541 SideDivisionCPU divisionX(AxisType::kX, extent_full.rangeU[0], extent_full.rangeU[1], side.fNsurf);
0542 SideDivisionCPU divisionY(AxisType::kY, extent_full.rangeV[0], extent_full.rangeV[1], side.fNsurf);
0543 SideDivisionCPU divisionR(AxisType::kR, ring_min, ring_max, side.fNsurf);
0544 SideDivisionCPU divisionXY(AxisType::kXY, extent_full.rangeU[0], extent_full.rangeU[1], extent_full.rangeV[0],
0545 extent_full.rangeV[1], side.fNsurf);
0546
0547 for (int i = 0; i < side.fNsurf; ++i) {
0548 auto &framed_surf = fCPUdata.fFramedSurf[side.fSurfaces[i]];
0549 if (all_rings_id) {
0550 auto const &extentRing = fCPUdata.fRingMasks[framed_surf.fFrame.id];
0551 divisionR.AddCandidate(i, extentRing.rangeR[0], extentRing.rangeR[1]);
0552 }
0553 auto ext = GetPlanarFrameExtent(framed_surf, framed_surf.fTrans);
0554 divisionX.AddCandidate(i, ext.rangeU[0], ext.rangeU[1]);
0555 divisionY.AddCandidate(i, ext.rangeV[0], ext.rangeV[1]);
0556 if (side.fNsurf > 3) divisionXY.AddCandidate(i, ext.rangeU[0], ext.rangeU[1], ext.rangeV[0], ext.rangeV[1]);
0557 }
0558
0559 auto bestEfficiency = divisionX.Efficiency();
0560 SideDivisionCPU *bestDiv = &divisionX;
0561 auto efficiency = divisionY.Efficiency();
0562 if (efficiency > bestEfficiency) {
0563 bestDiv = &divisionY;
0564 bestEfficiency = efficiency;
0565 }
0566 efficiency = divisionXY.Efficiency();
0567 if (side.fNsurf >= 4 && efficiency > bestEfficiency) {
0568 bestDiv = &divisionXY;
0569 bestEfficiency = efficiency;
0570 }
0571 if (all_rings_id) {
0572 efficiency = divisionR.Efficiency();
0573 if (efficiency > bestEfficiency) {
0574 bestDiv = &divisionR;
0575 bestEfficiency = efficiency;
0576 }
0577 }
0578 if (bestEfficiency > 0.01) {
0579
0580 side.fDivision = fCPUdata.fSideDivisions.size();
0581 fCPUdata.fSideDivisions.push_back(*bestDiv);
0582 }
0583 return side.fDivision;
0584 }
0585
0586 template <typename Real_t>
0587 void BrepHelper<Real_t>::ComputeSideDivisions()
0588 {
0589
0590 auto computeSingleSideDivision = [&](SurfaceType type, Side &side) {
0591 switch (type) {
0592 case SurfaceType::kPlanar: {
0593 auto extent_plane = ComputePlaneExtent(side);
0594 return ComputePlaneDivision(side, extent_plane);
0595 }
0596 case SurfaceType::kCylindrical:
0597 case SurfaceType::kConical: {
0598 auto extent_cyl = ComputeCylinderExtent(side);
0599 return ComputeCylinderDivision(side, extent_cyl);
0600 }
0601 default:
0602 return -1;
0603 }
0604 };
0605
0606
0607 int nfound{0}, ntotal{0};
0608 int nfoundall{0}, ntotalall{0};
0609 for (size_t common_id = 1; common_id < fCPUdata.fCommonSurfaces.size(); ++common_id) {
0610 auto &surf = fCPUdata.fCommonSurfaces[common_id];
0611 if (surf.fLeftSide.fNsurf > 1) {
0612 computeSingleSideDivision(surf.fType, surf.fLeftSide);
0613 }
0614 if (fCPUdata.fCommonSurfaces[common_id].fRightSide.fNsurf > 1) {
0615 computeSingleSideDivision(surf.fType, surf.fRightSide);
0616 }
0617
0618 if (surf.IsSceneSurface()) continue;
0619 ComputeTraversalFrames(common_id, true);
0620 ComputeTraversalFrames(common_id, false);
0621 CountTraversals(surf, nfoundall, ntotalall);
0622 if (surf.fLeftSide.fNsurf > 0 && surf.fRightSide.fNsurf > 0) {
0623 CountTraversals(surf, nfound, ntotal);
0624
0625 }
0626 }
0627 VECGEOM_LOG(debug) << "traversals_all: " << nfoundall << " / " << ntotalall << " ["
0628 << 100. * static_cast<double>(nfoundall) / ntotalall << " %]";
0629
0630
0631 fSurfData->fNsideDivisions = fCPUdata.fSideDivisions.size();
0632 size_t size_slices = 0;
0633 size_t size_slice_cand = 0;
0634 for (auto const &div : fCPUdata.fSideDivisions) {
0635 size_slices += div.fNslices;
0636 size_slice_cand += div.GetNcandidates();
0637 }
0638 fSurfData->fNslices = size_slices;
0639 fSurfData->fNsliceCandidates = size_slice_cand;
0640 fSurfData->fSideDivisions = new SideDivision<Real_t>[fSurfData->fNsideDivisions];
0641 fSurfData->fSlices = new SliceCand[size_slices];
0642 fSurfData->fSliceCandidates = new int[size_slice_cand];
0643
0644 SliceCand *slices = fSurfData->fSlices;
0645 int *slice_candidates = fSurfData->fSliceCandidates;
0646 for (auto i = 0; i < fSurfData->fNsideDivisions; ++i) {
0647 fCPUdata.fSideDivisions[i].CopyTo(fSurfData->fSideDivisions[i], slices, slice_candidates);
0648 slices += fCPUdata.fSideDivisions[i].fSlices.size();
0649 slice_candidates += fCPUdata.fSideDivisions[i].GetNcandidates();
0650 }
0651 }
0652
0653 template <typename Real_t>
0654 bool BrepHelper<Real_t>::Convert()
0655 {
0656 bool success = CreateLocalSurfaces();
0657 if (!success) return false;
0658 success = CreateCommonSurfacesScenes();
0659 return success;
0660 }
0661
0662 template <typename Real_t>
0663 void BrepHelper<Real_t>::ConvertTransformations(int idsurf)
0664 {
0665 auto &surf = fCPUdata.fCommonSurfaces[idsurf];
0666
0667 surf.fTrans = fCPUdata.fFramedSurf[surf.fLeftSide.fSurfaces[0]].fTrans;
0668 TransformationMP<vecgeom::Precision> identity;
0669
0670
0671 fCPUdata.fFramedSurf[surf.fLeftSide.fSurfaces[0]].fTrans = identity;
0672
0673
0674 fCPUdata.fCommonSurfaces[idsurf].fFlipped = fCPUdata.fFramedSurf[surf.fLeftSide.fSurfaces[0]].fLogicId < 0 ? 1 : 0;
0675
0676 TransformationMP<vecgeom::Precision> tsurfinv = surf.fTrans.Inverse();
0677
0678
0679 for (int i = 1; i < surf.fLeftSide.fNsurf; ++i) {
0680 int idglob = surf.fLeftSide.fSurfaces[i];
0681 auto &framedsurf = fCPUdata.fFramedSurf[idglob];
0682 framedsurf.fTrans *= tsurfinv;
0683 framedsurf.fTrans.SetProperties();
0684 }
0685
0686
0687 for (int i = 0; i < surf.fRightSide.fNsurf; ++i) {
0688 int idglob = surf.fRightSide.fSurfaces[i];
0689 auto &framedsurf = fCPUdata.fFramedSurf[idglob];
0690 framedsurf.fTrans *= tsurfinv;
0691 framedsurf.fTrans.SetProperties();
0692 }
0693 }
0694
0695 template <typename Real_t>
0696 void BrepHelper<Real_t>::CreateCandidateLists()
0697 {
0698 constexpr char kLside = 0x01;
0699 constexpr char kRside = 0x02;
0700
0701 auto addSurfToSideStates = [&](int isurf, char iside) {
0702 auto const &surf = fCPUdata.fCommonSurfaces[isurf];
0703 Side const &side = (iside == kLside) ? surf.fLeftSide : surf.fRightSide;
0704 auto scene_id = surf.GetSceneId();
0705 for (int i = 0; i < side.fNsurf; ++i) {
0706 int idglob = side.fSurfaces[i];
0707 auto const &framedsurf = fCPUdata.fFramedSurf[idglob];
0708 vecgeom::NavigationState state(framedsurf.fState);
0709 auto state_id = state.GetId();
0710 auto surf_ind = framedsurf.fSurfIndex;
0711
0712 auto &candidatesExiting = fCPUdata.GetCandidatesExiting(scene_id, state_id);
0713 auto &frameIndExiting = fCPUdata.GetFrameIndExiting(scene_id, state_id);
0714 auto &sidesExiting = fCPUdata.GetSidesExiting(scene_id, state_id);
0715
0716 candidatesExiting[surf_ind] = isurf;
0717 frameIndExiting[surf_ind] = i;
0718
0719 sidesExiting[surf_ind] |= iside;
0720 if (fVerbose > 0) {
0721 auto msg = VECGEOM_LOG(debug);
0722 msg << " added to exiting of state on scene " << scene_id << ":";
0723 state.PrintTop();
0724 int j = 0;
0725 msg << "candExiting: ";
0726 for (auto candidate : candidatesExiting) {
0727 msg << " " << j++ << ": " << candidate;
0728 }
0729 }
0730 }
0731 };
0732
0733
0734 auto addSurfToSideParents = [&](int isurf, char iside) {
0735 auto const &surf = fCPUdata.fCommonSurfaces[isurf];
0736 Side const &side = (iside == kLside) ? surf.fLeftSide : surf.fRightSide;
0737 for (int i = 0; i < side.fNsurf; ++i) {
0738 int idglob = side.fSurfaces[i];
0739 auto &framedsurf = fCPUdata.fFramedSurf[idglob];
0740
0741 NavIndex_t parent_state = 0;
0742 framedsurf.GetParentState(parent_state);
0743 if (framedsurf.fParent < 0) {
0744 VECGEOM_ASSERT(parent_state == surf.fDefaultState);
0745 continue;
0746 }
0747
0748
0749 auto const &parent_framedsurf = fCPUdata.fFramedSurf[side.fSurfaces[framedsurf.fParent]];
0750 if (parent_framedsurf.fLogicId) framedsurf.fVirtualParent = true;
0751
0752
0753
0754
0755 if (framedsurf.fEmbedded && !framedsurf.fVirtualParent) continue;
0756
0757
0758 vecgeom::NavigationState state(parent_state);
0759 auto state_id = state.GetId();
0760 auto &candidatesEntering = fCPUdata.GetCandidatesEntering(surf.GetSceneId(), state_id);
0761 auto &frameIndEntering = fCPUdata.GetFrameIndEntering(surf.GetSceneId(), state_id);
0762 auto &sidesEntering = fCPUdata.GetSidesEntering(surf.GetSceneId(), state_id);
0763
0764 if (candidatesEntering.size() && std::abs(candidatesEntering.back()) == isurf) {
0765 candidatesEntering.back() = -isurf;
0766 sidesEntering.back() |= iside;
0767 } else {
0768 candidatesEntering.push_back(-isurf);
0769 frameIndEntering.push_back(i);
0770 sidesEntering.push_back(iside);
0771 }
0772
0773 if (fVerbose > 0) {
0774 VECGEOM_LOG(debug) << " added " << candidatesEntering.back()
0775 << " to entering of non-embedding parent state on scene " << surf.GetSceneId() << ":";
0776 vecgeom::NavigationState::PrintTopImpl(parent_state);
0777 }
0778 }
0779 };
0780
0781
0782 auto addSurfToDefaultEntering = [&](int isurf, NavIndex_t state) {
0783 auto const &surf = fCPUdata.fCommonSurfaces[std::abs(isurf)];
0784 if (fVerbose > 0) printf("===== CS %d:\n", isurf);
0785
0786 int state_id = vecgeom::NavigationState::GetIdImpl(state);
0787 auto &candidatesEntering = fCPUdata.GetCandidatesEntering(surf.GetSceneId(), state_id);
0788 auto &frameIndEntering = fCPUdata.GetFrameIndEntering(surf.GetSceneId(), state_id);
0789 auto &sidesEntering = fCPUdata.GetSidesEntering(surf.GetSceneId(), state_id);
0790
0791 char sides = 0;
0792 if (surf.fLeftSide.fNsurf) sides |= kLside;
0793 if (surf.fRightSide.fNsurf) sides |= kRside;
0794 candidatesEntering.push_back(isurf);
0795 frameIndEntering.push_back(-1);
0796 sidesEntering.push_back(sides);
0797 if (fVerbose > 0) {
0798 printf(" added %d to entering of def state on scene %d: ", candidatesEntering.back(), surf.GetSceneId());
0799 vecgeom::NavigationState::PrintTopImpl(state);
0800 }
0801 };
0802
0803
0804 for (int isurf = 1; isurf < int(fCPUdata.fCommonSurfaces.size()); ++isurf) {
0805 auto const &surf = fCPUdata.fCommonSurfaces[isurf];
0806 auto const &topSurfLeft = fCPUdata.fFramedSurf[surf.fLeftSide.GetTopSurfaceIndex()];
0807
0808
0809 if (topSurfLeft.fState != surf.fDefaultState) addSurfToDefaultEntering(isurf, surf.fDefaultState);
0810
0811 addSurfToSideParents(isurf, kLside);
0812 addSurfToSideParents(isurf, kRside);
0813
0814
0815 addSurfToSideStates(isurf, kLside);
0816 addSurfToSideStates(isurf, kRside);
0817 }
0818 }
0819
0820 template <typename Real_t>
0821 int BrepHelper<Real_t>::CreateCommonSurface(int idglob, int volId, int scene_id, int &iframe, char &iside)
0822 {
0823 constexpr char kLside = 0x01;
0824 constexpr char kRside = 0x02;
0825 bool flip{false}, flip_bool{false};
0826 auto approxEqual = [&](int idglob1, int idglob2) {
0827 flip = false;
0828 flip_bool = false;
0829 FramedSurface<Precision, TransformationMP<Precision>> const &s1 = fCPUdata.fFramedSurf[idglob1];
0830 FramedSurface<Precision, TransformationMP<Precision>> const &s2 = fCPUdata.fFramedSurf[idglob2];
0831
0832 if (s1.fSurface.type != s2.fSurface.type) return false;
0833
0834
0835 static bool warning_printed = false;
0836 if (s1.fSurface.type == SurfaceType::kArb4 || s2.fSurface.type == SurfaceType::kArb4) {
0837 if (!warning_printed) {
0838 VECGEOM_LOG(warning) << "CreateCommonSurface: case " << to_cstring(s1.fSurface.type) << " not implemented";
0839 warning_printed = true;
0840 }
0841 return false;
0842 }
0843
0844
0845 if ((s1.fLogicId == 0) || (s2.fLogicId == 0)) {
0846 flip_bool = (s1.fLogicId < 0) || (s2.fLogicId < 0);
0847 } else {
0848 flip_bool = (s1.fLogicId < 0) != (s2.fLogicId < 0);
0849 }
0850
0851
0852 vecgeom::Transformation3DMP<vecgeom::Precision> const &t1 = s1.fTrans;
0853 vecgeom::Transformation3DMP<vecgeom::Precision> const &t2 = s2.fTrans;
0854
0855
0856
0857
0858 vecgeom::Vector3D<vecgeom::Precision> const zaxis(0, 0, 1);
0859 auto z1 = t1.InverseTransformDirection(zaxis);
0860 auto z2 = t2.InverseTransformDirection(zaxis);
0861 if (!ApproxEqualVector(z1.Cross(z2), {0, 0, 0})) return false;
0862
0863
0864 vecgeom::Vector3D<vecgeom::Precision> tdiff = t1.Translation() - t2.Translation();
0865 bool same_tr = ApproxEqualVector(tdiff, {0, 0, 0});
0866 vecgeom::Vector3D<vecgeom::Precision> ldir;
0867 switch (s1.fSurface.type) {
0868 case SurfaceType::kPlanar:
0869 flip = z1.Dot(z2) < 0;
0870 if (same_tr) break;
0871
0872 tdiff.Normalize();
0873 t1.TransformDirection(tdiff, ldir);
0874 if (std::abs(ldir[2]) > vecgeom::kTolerance) return false;
0875 break;
0876 case SurfaceType::kCylindrical:
0877 if (std::abs(s1.fSurface.Radius() - s2.fSurface.Radius()) > vecgeom::kTolerance) return false;
0878
0879 flip = (s1.fSurface.IsFlipped()) ^ (s2.fSurface.IsFlipped());
0880 if (same_tr) break;
0881 tdiff.Normalize();
0882 t1.TransformDirection(tdiff, ldir);
0883
0884 if (!ApproxEqualVector(ldir, {0, 0, ldir[2]})) return false;
0885 break;
0886 case SurfaceType::kConical:
0887 if (std::abs(s1.fSurface.RadiusZ(-Abs(t1.Translation()[2])) - s2.fSurface.RadiusZ(-Abs(t2.Translation()[2]))) >
0888 vecgeom::kTolerance) {
0889 return false;
0890 }
0891 if (std::abs(s1.fSurface.fSlope - s2.fSurface.fSlope) > vecgeom::kTolerance) {
0892 return false;
0893 }
0894 flip = s1.fSurface.IsFlipped() ^ s2.fSurface.IsFlipped();
0895 if (same_tr) break;
0896 tdiff.Normalize();
0897 t1.TransformDirection(tdiff, ldir);
0898
0899 if (!ApproxEqualVector(ldir, {0, 0, ldir[2]})) return false;
0900 break;
0901 case SurfaceType::kSpherical:
0902 case SurfaceType::kTorus:
0903 case SurfaceType::kArb4:
0904 default:
0905 if (!warning_printed) {
0906 VECGEOM_LOG(warning) << "CreateCommonSurface: case " << to_cstring(s1.fSurface.type) << " not implemented";
0907 warning_printed = true;
0908 }
0909 return false;
0910 };
0911 return true;
0912 };
0913
0914 auto surfHash = [&](int idglobal, double tolerance = 100 * vecgeom::kTolerance) {
0915
0916 auto const &surf = fCPUdata.fFramedSurf[idglobal];
0917 vecgeom::Transformation3DMP<vecgeom::Precision> const &trans = surf.fTrans;
0918
0919
0920 vecgeom::Vector3D<vecgeom::Precision> normal;
0921 vecgeom::Vector3D<vecgeom::Precision> scaled_norm_vector;
0922 const vecgeom::Vector3D<vecgeom::Precision> lnorm(0, 0, 1);
0923 trans.InverseTransformDirection(lnorm, normal);
0924
0925 long hash = 0;
0926
0927 auto hash_combine = [](long seed, const long value) {
0928 return seed ^ (std::hash<long>{}(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
0929 };
0930
0931 switch (surf.fSurface.type) {
0932 case SurfaceType::kPlanar:
0933
0934 scaled_norm_vector = trans.Translation().Dot(normal) * normal;
0935 for (int i = 0; i < 3; i++) {
0936
0937 hash = hash_combine(hash, static_cast<long>(std::round(scaled_norm_vector[i] / tolerance)));
0938 }
0939 break;
0940 case SurfaceType::kCylindrical:
0941
0942 hash = hash_combine(hash, static_cast<long>(std::round(surf.fSurface.Radius() / tolerance)));
0943
0944 for (int i = 0; i < 3; i++) {
0945 hash = hash_combine(hash, static_cast<long>(std::round(normal[i] / tolerance)));
0946 }
0947 break;
0948 case SurfaceType::kConical:
0949
0950 hash = hash_combine(
0951 hash, static_cast<long>(std::round(surf.fSurface.RadiusZ(-Abs(trans.Translation()[2])) / tolerance)));
0952 hash = hash_combine(hash, static_cast<long>(std::round(surf.fSurface.fSlope / tolerance)));
0953 for (int i = 0; i < 3; i++) {
0954 hash = hash_combine(hash, static_cast<long>(std::round(normal[i] / tolerance)));
0955 }
0956 break;
0957 case SurfaceType::kSpherical:
0958 case SurfaceType::kTorus:
0959 case SurfaceType::kArb4:
0960 default:
0961 hash = 0;
0962 break;
0963 };
0964
0965 return hash;
0966 };
0967
0968 auto const &surf = fCPUdata.fFramedSurf[idglob];
0969 bool is_scene_surf = (scene_id > 0) && (surf.fState == 0);
0970 auto hash = surfHash(idglob, 1000 * vecgeom::kTolerance);
0971
0972 auto range = fCPUdata.fSurfHash[scene_id].equal_range(hash);
0973 bool found_dup_surf = false;
0974 int id = -1;
0975
0976 if (hash != 0) {
0977 for (auto it = range.first; it != range.second; ++it) {
0978 const auto &other_id = fCPUdata.fCommonSurfaces[it->second].fLeftSide.fSurfaces[0];
0979
0980 if (approxEqual(other_id, idglob)) {
0981 flip ^= flip_bool;
0982
0983
0984
0985 found_dup_surf = true;
0986 id = it->second;
0987 auto &crt_side = flip ? fCPUdata.fCommonSurfaces[id].fRightSide : fCPUdata.fCommonSurfaces[id].fLeftSide;
0988
0989
0990 NavIndex_t parent_state_index = fCPUdata.fFramedSurf[idglob].fState;
0991 vecgeom::NavigationState::PopImpl(parent_state_index);
0992 NavIndex_t default_state = fCPUdata.fCommonSurfaces[id].fDefaultState;
0993
0994
0995
0996
0997 if ((default_state != parent_state_index) || (default_state == 0 && parent_state_index == 0 &&
0998 fCPUdata.fCommonSurfaces[id].fSceneId < 0 && !is_scene_surf)) {
0999
1000 bool has_parent = false;
1001 for (auto isurf = 0; isurf < crt_side.fNsurf; ++isurf) {
1002 has_parent = fCPUdata.fFramedSurf[crt_side.fSurfaces[isurf]].fState == parent_state_index;
1003 if (has_parent) break;
1004 }
1005 if (!has_parent) {
1006 found_dup_surf = false;
1007 continue;
1008 }
1009 }
1010
1011 iframe = crt_side.AddSurface(idglob);
1012 iside = flip ? kRside : kLside;
1013 break;
1014 }
1015 }
1016 }
1017
1018 if (!found_dup_surf) {
1019
1020
1021 id = fCPUdata.fCommonSurfaces.size();
1022 fCPUdata.fCommonSurfaces.push_back({fCPUdata.fFramedSurf[idglob].fSurface.type, idglob, surf.fLogicId < 0});
1023 iside = kLside;
1024 iframe = 0;
1025 auto parent_state = fCPUdata.fFramedSurf[idglob].fState;
1026 vecgeom::NavigationState::PopImpl(parent_state);
1027 fCPUdata.fCommonSurfaces[id].fSceneId = is_scene_surf ? -scene_id : scene_id;
1028 fCPUdata.fCommonSurfaces[id].fDefaultState = parent_state;
1029
1030 fCPUdata.fSurfHash[scene_id].insert(std::make_pair(hash, id));
1031 }
1032
1033 return id;
1034 }
1035
1036 template <typename Real_t>
1037 bool BrepHelper<Real_t>::CreateCommonSurfacesScenes()
1038 {
1039 using Real_b = typename SurfData<Real_t>::Real_b;
1040 constexpr char kLside = 0x01;
1041 constexpr char kRside = 0x02;
1042 int nphysical = 0;
1043 int maxscene = -1;
1044 int numscenes = 0;
1045 vecgeom::NavigationState state;
1046 int ntot = vecgeom::GeoManager::Instance().GetRegisteredVolumesCount();
1047 std::vector<bool> visited(ntot, false);
1048 auto &numStates = fCPUdata.fSceneTouchables;
1049
1050
1051 typedef std::function<void(vecgeom::VPlacedVolume const *)> funcCountStates_t;
1052 funcCountStates_t countStatesPerScene = [&](vecgeom::VPlacedVolume const *pvol) {
1053 state.Push(pvol);
1054 const auto vol = pvol->GetLogicalVolume();
1055 auto ivol = vol->id();
1056 auto daughters = vol->GetDaughters();
1057 int nd = daughters.size();
1058 unsigned short scene_id = 0, newscene_id = 0;
1059 bool is_scene = state.GetSceneId(scene_id, newscene_id);
1060 if (scene_id > maxscene) {
1061 int ntoinsert = scene_id - maxscene + 1;
1062 numStates.insert(numStates.end(), ntoinsert, 0);
1063 maxscene = scene_id;
1064 numscenes = maxscene + 1;
1065 }
1066 numStates[scene_id]++;
1067 bool do_daughters = is_scene ? (!visited[ivol]) : true;
1068 if (do_daughters) {
1069 for (int id = 0; id < nd; ++id) {
1070 countStatesPerScene(daughters[id]);
1071 }
1072 }
1073 visited[ivol] = is_scene;
1074 state.Pop();
1075 };
1076
1077 auto allocateExitingCandidates = [&](unsigned short scene_id, int state_id, size_t nsurf) {
1078 auto &candidatesExiting = fCPUdata.GetCandidatesExiting(scene_id, state_id);
1079 auto &frameIndExiting = fCPUdata.GetFrameIndExiting(scene_id, state_id);
1080 auto &sidesExiting = fCPUdata.GetSidesExiting(scene_id, state_id);
1081 if (nsurf >= candidatesExiting.size()) {
1082 candidatesExiting.insert(candidatesExiting.end(), nsurf - candidatesExiting.size(), 0);
1083 frameIndExiting.insert(frameIndExiting.end(), nsurf - frameIndExiting.size(), 0);
1084 sidesExiting.insert(sidesExiting.end(), nsurf - sidesExiting.size(), 0);
1085 }
1086 };
1087
1088
1089 typedef std::function<void(vecgeom::VPlacedVolume const *)> func_t;
1090 func_t createCommonSurfaces = [&](vecgeom::VPlacedVolume const *pvol) {
1091
1092 state.Push(pvol);
1093 const auto vol = pvol->GetLogicalVolume();
1094 auto ivol = vol->id();
1095 auto daughters = vol->GetDaughters();
1096 int nd = daughters.size();
1097 NavIndex_t nav_ind = state.GetNavIndex();
1098 unsigned short scene_id = 0, newscene_id = 0;
1099 bool is_scene = state.GetSceneId(scene_id, newscene_id);
1100 auto state_id = state.GetId();
1101 auto &nperscene = fCPUdata.fSceneTouchables;
1102 nphysical++;
1103 nperscene[scene_id]++;
1104 TransformationMP<vecgeom::Precision> trans;
1105
1106 state.TopInSceneMatrix(trans);
1107 VolumeShellCPU const &shell = fCPUdata.fShells[ivol];
1108
1109 auto nsurf_local = shell.fSurfaces.size();
1110 allocateExitingCandidates(scene_id, state_id, nsurf_local);
1111 if (is_scene && !visited[ivol]) allocateExitingCandidates(newscene_id, 0, nsurf_local);
1112
1113 for (int lsurf_id : shell.fSurfaces) {
1114 FramedSurface<Precision, TransformationMP<Precision>> &lsurf = fCPUdata.fLocalSurfaces[lsurf_id];
1115
1116
1117 if (lsurf.fFrame.type == FrameType::kNoFrame) continue;
1118 TransformationMP<vecgeom::Precision> surftrans = lsurf.fTrans;
1119 surftrans *= trans;
1120
1121
1122 int id_surf = fCPUdata.fFramedSurf.size();
1123 fCPUdata.fFramedSurf.push_back({lsurf.fSurface, lsurf.fFrame, surftrans, nav_ind, lsurf.fNeverCheck});
1124 auto &framed_surf = fCPUdata.fFramedSurf[id_surf];
1125 framed_surf.fLogicId = lsurf.fLogicId;
1126 framed_surf.fSurfIndex = lsurf.fSurfIndex;
1127 framed_surf.fEmbedding = (lsurf.fLogicId == 0) ? lsurf.fEmbedding : false;
1128 VECGEOM_ASSERT(lsurf.fSurfIndex < nsurf_local);
1129
1130 char iside = 0;
1131 int iframe = 0;
1132 auto isurf = CreateCommonSurface(id_surf, ivol, scene_id, iframe, iside);
1133
1134 if (fVerbose > 0) {
1135 std::cout << "scene " << scene_id << ": framed surface " << id_surf << " on CS " << isurf << std::endl;
1136 state.PrintTop();
1137 std::cout << " " << surftrans << "\n";
1138 }
1139
1140 if (is_scene) {
1141
1142 if (!visited[ivol]) {
1143
1144 int id_surf_scene = fCPUdata.fFramedSurf.size();
1145
1146 fCPUdata.fFramedSurf.push_back(
1147 {lsurf.fSurface, lsurf.fFrame, lsurf.fTrans, 0 , lsurf.fNeverCheck});
1148
1149
1150 fCPUdata.fFramedSurf[id_surf_scene].fLogicId = lsurf.fLogicId;
1151 fCPUdata.fFramedSurf[id_surf_scene].fSurfIndex = lsurf.fSurfIndex;
1152 fCPUdata.fFramedSurf[id_surf_scene].fEmbedding = (lsurf.fLogicId == 0) ? lsurf.fEmbedding : false;
1153 auto isurf_scene = CreateCommonSurface(id_surf_scene, ivol, newscene_id, iframe, iside);
1154
1155
1156
1157
1158
1159
1160
1161
1162 fCPUdata.fFramedSurf[id_surf].fSceneCS = isurf_scene;
1163
1164
1165 fCPUdata.fFramedSurf[id_surf].fSceneCSind = (iside == kLside) ? id_surf_scene : -id_surf_scene;
1166 fCPUdata.fSceneShells[ivol].fSurfaces[framed_surf.fSurfIndex] = id_surf;
1167 if (fVerbose > 0) {
1168 VECGEOM_LOG(info) << "scene " << newscene_id << ": top framed surface " << id_surf_scene << " on CS "
1169 << isurf_scene;
1170 VECGEOM_LOG(info) << " linked to CS " << isurf << " surf_index=" << lsurf.fSurfIndex;
1171 }
1172 } else {
1173
1174 int id_surf_first = fCPUdata.fSceneShells[ivol].fSurfaces[framed_surf.fSurfIndex];
1175 auto &framed_surf_first = fCPUdata.fFramedSurf[id_surf_first];
1176 framed_surf.fSceneCS = framed_surf_first.fSceneCS;
1177 framed_surf.fSceneCSind = framed_surf_first.fSceneCSind;
1178 }
1179 }
1180 }
1181
1182 bool do_daughters = is_scene ? (!visited[ivol]) : true;
1183 if (do_daughters) {
1184 for (int id = 0; id < nd; ++id) {
1185 createCommonSurfaces(daughters[id]);
1186 }
1187 }
1188 visited[ivol] = is_scene;
1189 state.Pop();
1190 };
1191
1192 auto checkExitingCandidates = [&](unsigned short scene_id, int state_id, size_t nsurf) {
1193 auto &candidatesExiting = fCPUdata.GetCandidatesExiting(scene_id, state_id);
1194 int ivol = state.GetLogicalId();
1195 auto &shell = fCPUdata.fShells[ivol];
1196 for (size_t isurf = 0; isurf < nsurf; ++isurf) {
1197 auto surf = fCPUdata.fLocalSurfaces[shell.fSurfaces[isurf]];
1198 if ((surf.fFrame.type == FrameType::kNoFrame && candidatesExiting[isurf] > 0) ||
1199 (surf.fFrame.type != FrameType::kNoFrame && candidatesExiting[isurf] == 0)) {
1200 std::cout << "=== Wrong candidates for state:\n";
1201 state.Print();
1202 printf(" candExiting: ");
1203 int j = 0;
1204 for (auto candidate : candidatesExiting)
1205 printf(" %d: %d ", j++, candidate);
1206 printf("\n");
1207 return false;
1208 }
1209 }
1210 return true;
1211 };
1212
1213
1214 typedef std::function<void(vecgeom::VPlacedVolume const *)> funcValidate_t;
1215 funcValidate_t validateExitingCandidates = [&](vecgeom::VPlacedVolume const *pvol) {
1216 state.Push(pvol);
1217 const auto vol = pvol->GetLogicalVolume();
1218 auto ivol = vol->id();
1219 auto daughters = vol->GetDaughters();
1220 int nd = daughters.size();
1221 unsigned short scene_id = 0, newscene_id = 0;
1222 bool is_scene = state.GetSceneId(scene_id, newscene_id);
1223 auto state_id = state.GetId();
1224 VolumeShellCPU const &shell = fCPUdata.fShells[ivol];
1225 auto nsurf_local = shell.fSurfaces.size();
1226
1227 if (!checkExitingCandidates(scene_id, state_id, nsurf_local)) return false;
1228 if (is_scene && !visited[ivol]) {
1229 if (!checkExitingCandidates(newscene_id, 0, nsurf_local)) return false;
1230 }
1231
1232 bool do_daughters = is_scene ? (!visited[ivol]) : true;
1233 if (do_daughters) {
1234 for (int id = 0; id < nd; ++id) {
1235 validateExitingCandidates(daughters[id]);
1236 }
1237 }
1238 visited[ivol] = is_scene;
1239 state.Pop();
1240 return true;
1241 };
1242
1243
1244 fCPUdata.fCommonSurfaces.push_back({});
1245
1246 auto world = vecgeom::GeoManager::Instance().GetWorld();
1247
1248 countStatesPerScene(world);
1249
1250
1251 fCPUdata.fSceneStartIndex.insert(fCPUdata.fSceneStartIndex.end(), numscenes, 0);
1252 fCPUdata.fSurfHash.insert(fCPUdata.fSurfHash.end(), numscenes, {});
1253 int startindex = 0;
1254 for (int scene_id = 0; scene_id < numscenes; ++scene_id) {
1255
1256 int nt = ++fCPUdata.fSceneTouchables[scene_id];
1257 fCPUdata.fSceneStartIndex[scene_id] = startindex;
1258 startindex += nt;
1259 fCPUdata.fCandidatesEntering.insert(fCPUdata.fCandidatesEntering.end(), nt, {});
1260 fCPUdata.fCandidatesExiting.insert(fCPUdata.fCandidatesExiting.end(), nt, {});
1261 fCPUdata.fFrameIndEntering.insert(fCPUdata.fFrameIndEntering.end(), nt, {});
1262 fCPUdata.fFrameIndExiting.insert(fCPUdata.fFrameIndExiting.end(), nt, {});
1263 fCPUdata.fSidesEntering.insert(fCPUdata.fSidesEntering.end(), nt, {});
1264 fCPUdata.fSidesExiting.insert(fCPUdata.fSidesExiting.end(), nt, {});
1265 }
1266
1267
1268
1269
1270 InitBVHData();
1271
1272 vecgeom::ABBoxManager<Real_b>::Instance().InitABBoxesForSurfaces(fCPUdata);
1273
1274
1275 vecgeom::ABBoxManager<Real_b>::Instance().InitABBoxesForSurfaces(fCPUdata, true);
1276
1277 std::fill(visited.begin(), visited.end(), false);
1278 createCommonSurfaces(world);
1279
1280 for (size_t isurf = 1; isurf < fCPUdata.fCommonSurfaces.size(); ++isurf) {
1281
1282 ComputeDefaultStates(isurf);
1283
1284 SortSides(isurf);
1285
1286 ConvertTransformations(isurf);
1287 }
1288
1289
1290
1291 auto adjustFrameIndex = [&](int isurf, char iside, int iglob) {
1292 auto const &surf = fCPUdata.fCommonSurfaces[isurf];
1293 Side const &side = (iside == kLside) ? surf.fLeftSide : surf.fRightSide;
1294 for (int i = 0; i < side.fNsurf; ++i) {
1295 if (side.fSurfaces[i] == std::abs(iglob)) return (iglob > 0) ? i + 1 : -(i + 1);
1296 }
1297 return 0;
1298 };
1299
1300 for (size_t iframe = 0; iframe < fCPUdata.fFramedSurf.size(); ++iframe) {
1301 auto &framed_surf = fCPUdata.fFramedSurf[iframe];
1302 if (framed_surf.fSceneCS > 0) {
1303 auto iglob = framed_surf.fSceneCSind;
1304 auto index = adjustFrameIndex(framed_surf.fSceneCS, kLside, iglob);
1305 if (index == 0) index = adjustFrameIndex(framed_surf.fSceneCS, kRside, iglob);
1306 if (index != 0) framed_surf.fSceneCSind = index;
1307 }
1308 }
1309
1310
1311 CreateCandidateLists();
1312
1313
1314 std::fill(visited.begin(), visited.end(), false);
1315 state.Clear();
1316 validateExitingCandidates(world);
1317
1318
1319 ComputeSideDivisions();
1320
1321
1322 UpdateSurfData();
1323
1324
1325
1326
1327
1328
1329
1330
1331 vecgeom::ABBoxManager<Real_b>::Instance().InitABBoxesForCompleteGeometry();
1332
1333
1334 std::vector<vecgeom::LogicalVolume const *> lvols;
1335 vecgeom::GeoManager::Instance().GetAllLogicalVolumes(lvols);
1336
1337
1338 using Real_b = typename SurfData<Real_t>::Real_b;
1339 fSurfData->fBVH = new vecgeom::BVH<Real_b>[fCPUdata.fShells.size()];
1340 fSurfData->fBVHSolids =
1341 new vecgeom::BVH<Real_b>[fCPUdata.fShells.size()];
1342
1343 for (auto logical_volume : lvols) {
1344
1345 int bvh_index = fCPUdata.fShells[logical_volume->id()].fBVH;
1346 int nSolidBoxes{0};
1347 int nSurfBoxes{0};
1348 Vector3D<Real_b> *surfBoxes{nullptr};
1349 Vector3D<Real_b> *solidBoxes{nullptr};
1350 surfBoxes = vecgeom::ABBoxManager<Real_b>::Instance().GetSurfaceABBoxes(logical_volume->id(), nSurfBoxes, fCPUdata);
1351 solidBoxes = vecgeom::ABBoxManager<Real_b>::Instance().GetABBoxes(logical_volume, nSolidBoxes);
1352
1353
1354
1355 fSurfData->fBVH[bvh_index].Clear();
1356
1357
1358 bvh::InitBVH<Real_t>(logical_volume->id(), fSurfData->fBVH[bvh_index], fCPUdata, surfBoxes, nSurfBoxes);
1359
1360 if (logical_volume->GetDaughters().size() > 0) {
1361
1362
1363 bvh::InitBVH<Real_t>(logical_volume->id(), fSurfData->fBVHSolids[bvh_index], fCPUdata, solidBoxes, nSolidBoxes);
1364 }
1365 }
1366
1367
1368 if (fVerbose > 0) {
1369 for (size_t isurf = 1; isurf < fCPUdata.fCommonSurfaces.size(); ++isurf)
1370 PrintCommonSurface(isurf);
1371 }
1372
1373 if (fVerbose > 1) {
1374 PrintCandidateLists();
1375 std::cout << "Visited " << nphysical << " physical volumes, created " << fCPUdata.fCommonSurfaces.size() - 1
1376 << " common surfaces\n";
1377 }
1378
1379 return true;
1380 }
1381
1382 template <typename Real_t>
1383 bool BrepHelper<Real_t>::CreateLocalSurfaces()
1384 {
1385
1386 TransformationMP<vecgeom::Precision> identity;
1387
1388 std::vector<vecgeom::LogicalVolume *> volumes;
1389 auto n_registered_volumes = vecgeom::GeoManager::Instance().GetRegisteredVolumesCount();
1390 vecgeom::GeoManager::Instance().GetAllLogicalVolumes(volumes);
1391
1392 SetNvolumes(n_registered_volumes);
1393
1394
1395 for (auto volume : volumes) {
1396 vecgeom::VUnplacedVolume const *solid = volume->GetUnplacedVolume();
1397 bool result = conv::CreateSolidSurfaces<vecgeom::Precision>(solid, volume->id());
1398 if (!result) {
1399 VECGEOM_LOG(error) << "Could not convert volume " << volume->id() << ": " << volume->GetName();
1400 }
1401
1402 if (!fCPUdata.fShells[volume->id()].fSimplified) {
1403 auto &crtlogic = fCPUdata.fShells[volume->id()].fLogic;
1404 vgbrep::logichelper::LogicExpressionConstruct lc(crtlogic);
1405 lc.Simplify(crtlogic);
1406 vgbrep::logichelper::insert_jumps(crtlogic);
1407 fCPUdata.fShells[volume->id()].fSimplified = true;
1408 }
1409 }
1410
1411 if (fVerbose > 0) {
1412 for (auto volume : volumes) {
1413 auto const &shell = fCPUdata.fShells[volume->id()];
1414 printf("shell %d for volume %s:\n", volume->id(), volume->GetName());
1415 logichelper::print_logic(shell.fLogic);
1416 for (int lsurf_id : shell.fSurfaces) {
1417 auto const &lsurf = fCPUdata.fLocalSurfaces[lsurf_id];
1418 printf(" local surf %d (logic_id=%d): ", lsurf_id, lsurf.fLogicId);
1419 lsurf.fTrans.Print();
1420 printf("\n");
1421 }
1422 }
1423 }
1424
1425 return true;
1426 }
1427
1428 template <typename Real_t>
1429 void BrepHelper<Real_t>::DumpBVH(uint ivol)
1430 {
1431 auto lvol = vecgeom::GeoManager::Instance().GetLogicalVolume(ivol);
1432 VECGEOM_ASSERT(lvol->id() == ivol);
1433 int bvh_index = fSurfData->fShells[ivol].fBVH;
1434 auto fname = std::string(lvol->GetName()) + ".bin";
1435 bvh::DumpBVH(fSurfData->fBVH[bvh_index], fname.c_str());
1436 }
1437
1438 template <typename Real_t>
1439 bool BrepHelper<Real_t>::EqualFrames(Side const &side, int i1, int i2)
1440 {
1441 using Vector3D = vecgeom::Vector3D<vecgeom::Precision>;
1442
1443 auto const &s1 = fCPUdata.fFramedSurf[side.fSurfaces[i1]];
1444 auto const &s2 = fCPUdata.fFramedSurf[side.fSurfaces[i2]];
1445 if (s1.fFrame.type != s2.fFrame.type) return false;
1446
1447 vecgeom::Transformation3DMP<vecgeom::Precision> const &t1 = s1.fTrans;
1448 vecgeom::Transformation3DMP<vecgeom::Precision> const &t2 = s2.fTrans;
1449 Vector3D tdiff = t1.Translation() - t2.Translation();
1450
1451 if (!ApproxEqualVector(tdiff, {0, 0, 0})) return false;
1452
1453
1454 switch (s1.fFrame.type) {
1455 case FrameType::kRangeZ:
1456 break;
1457 case FrameType::kRing: {
1458 auto mask1 = fCPUdata.fRingMasks[s1.fFrame.id];
1459 auto mask2 = fCPUdata.fRingMasks[s2.fFrame.id];
1460
1461
1462 if (!ApproxEqual(mask1.rangeR[0], mask2.rangeR[0]) || !ApproxEqual(mask1.rangeR[1], mask2.rangeR[1]) ||
1463 mask1.isFullCirc != mask2.isFullCirc)
1464 return false;
1465 if (mask1.isFullCirc) return true;
1466
1467 auto phimin1 = t1.InverseTransformDirection(Vector3D{mask1.vecSPhi[0], mask1.vecSPhi[1], 0});
1468 auto phimin2 = t2.InverseTransformDirection(Vector3D{mask2.vecSPhi[0], mask2.vecSPhi[1], 0});
1469
1470 auto phimax1 = t1.InverseTransformDirection(Vector3D{mask1.vecEPhi[0], mask1.vecEPhi[1], 0});
1471 auto phimax2 = t2.InverseTransformDirection(Vector3D{mask2.vecEPhi[0], mask2.vecEPhi[1], 0});
1472
1473 if (ApproxEqualVector(phimin1, phimin2) && ApproxEqualVector(phimax1, phimax2)) return true;
1474 break;
1475 }
1476 case FrameType::kZPhi: {
1477 auto mask1 = fCPUdata.fZPhiMasks[s1.fFrame.id];
1478 auto mask2 = fCPUdata.fZPhiMasks[s2.fFrame.id];
1479
1480
1481
1482 if (!ApproxEqual(mask1.rangeZ[0], mask2.rangeZ[0]) || !ApproxEqual(mask1.rangeZ[1], mask2.rangeZ[1])) return false;
1483 if (mask1.isFullCirc) return true;
1484
1485 auto phimin1 = t1.InverseTransformDirection(Vector3D{mask1.vecSPhi[0], mask1.vecSPhi[1], 0});
1486 auto phimin2 = t2.InverseTransformDirection(Vector3D{mask2.vecSPhi[0], mask2.vecSPhi[1], 0});
1487
1488 auto phimax1 = t1.InverseTransformDirection(Vector3D{mask1.vecEPhi[0], mask1.vecEPhi[1], 0});
1489 auto phimax2 = t2.InverseTransformDirection(Vector3D{mask2.vecEPhi[0], mask2.vecEPhi[1], 0});
1490
1491 if (ApproxEqualVector(phimin1, phimin2) && ApproxEqualVector(phimax1, phimax2)) return true;
1492 break;
1493 }
1494 case FrameType::kRangeSph:
1495
1496 break;
1497 case FrameType::kWindow: {
1498 auto frameData1 = fCPUdata.fWindowMasks[s1.fFrame.id];
1499 auto frameData2 = fCPUdata.fWindowMasks[s2.fFrame.id];
1500
1501
1502 Vector3D v11 = t1.InverseTransformDirection(Vector3D{frameData1.rangeU[0], frameData1.rangeV[0], 0});
1503 Vector3D v12 = t1.InverseTransformDirection(Vector3D{frameData1.rangeU[1], frameData1.rangeV[1], 0});
1504 Vector3D v21 = t2.InverseTransformDirection(Vector3D{frameData2.rangeU[0], frameData2.rangeV[0], 0});
1505 Vector3D v22 = t2.InverseTransformDirection(Vector3D{frameData2.rangeU[1], frameData2.rangeV[1], 0});
1506
1507
1508 auto diag1 = v12 - v11;
1509 auto diag2 = v22 - v21;
1510
1511 return ApproxEqualVector(diag1.Abs(), diag2.Abs());
1512 }
1513 case FrameType::kTriangle:
1514
1515 break;
1516 case FrameType::kQuadrilateral: {
1517
1518 break;
1519 }
1520 default:
1521 break;
1522 };
1523 return false;
1524 }
1525
1526 template <typename Real_t>
1527 void BrepHelper<Real_t>::InitBVHData()
1528 {
1529 std::vector<vecgeom::LogicalVolume const *> lvols;
1530 vecgeom::GeoManager::Instance().GetAllLogicalVolumes(lvols);
1531
1532 TransformationMP<vecgeom::Precision> identity;
1533 VECGEOM_ASSERT(fCPUdata.fPVolTrans.size() == 0);
1534 fCPUdata.fPVolTrans.push_back(identity);
1535
1536 for (auto lvol : lvols) {
1537
1538 auto &rootShell = fCPUdata.fShells[lvol->id()];
1539
1540
1541 rootShell.fBVH = lvol->id();
1542
1543
1544 for (uint i = 0; i < rootShell.fSurfaces.size(); i++) {
1545 if (fCPUdata.fLocalSurfaces[rootShell.fSurfaces[i]].fFrame.type != FrameType::kNoFrame)
1546 rootShell.fExitingSurfaces.push_back(i);
1547 }
1548
1549 for (const auto &pvol : lvol->GetDaughters()) {
1550
1551 rootShell.fDaughterPvolIds.push_back(pvol->id());
1552
1553
1554 const auto &shell = fCPUdata.fShells[pvol->GetLogicalVolume()->id()];
1555
1556
1557 int vol_trans_id = fCPUdata.fPVolTrans.size();
1558 fCPUdata.fPVolTrans.push_back(vecgeom::Transformation3DMP<vecgeom::Precision>(*pvol->GetTransformation()));
1559
1560
1561 rootShell.fDaughterPvolTrans.push_back(vol_trans_id);
1562
1563
1564 for (uint i = 0; i < shell.fSurfaces.size(); i++) {
1565 if (fCPUdata.fLocalSurfaces[shell.fSurfaces[i]].fFrame.type != FrameType::kNoFrame) {
1566
1567 rootShell.fEnteringSurfaces.push_back(shell.fSurfaces[i]);
1568
1569 rootShell.fEnteringSurfacesPvol.push_back(pvol->id());
1570
1571 rootShell.fEnteringSurfacesPvolTrans.push_back(vol_trans_id);
1572 rootShell.fEnteringSurfacesLvolIds.push_back(pvol->GetLogicalVolume()->id());
1573 }
1574 }
1575 }
1576 }
1577 }
1578
1579 template <typename Real_t>
1580 void BrepHelper<Real_t>::FindConvexBooleanSurfaces()
1581 {
1582 using Real_b = typename SurfData<Real_t>::Real_b;
1583
1584 std::vector<vecgeom::LogicalVolume const *> lvols;
1585 vecgeom::GeoManager::Instance().GetAllLogicalVolumes(lvols);
1586
1587 long nsurf_bool = 0;
1588 long nsurf_bool_conv = 0;
1589
1590 for (auto lvol : lvols) {
1591
1592 auto &rootShell = fCPUdata.fShells[lvol->id()];
1593
1594
1595
1596 auto boxes = vecgeom::ABBoxManager<Real_b>::Instance().fVolToSurfaceABBoxesMap[lvol->id()];
1597
1598
1599 for (auto idsurf = 0u; idsurf < rootShell.fExitingSurfaces.size(); idsurf++) {
1600
1601 bool surf_convex = true;
1602 bool inner_surf = false;
1603
1604 auto exiting_ind = rootShell.fExitingSurfaces[idsurf];
1605 auto &localSurface =
1606 fCPUdata.fLocalSurfaces[rootShell.fSurfaces[exiting_ind]];
1607
1608
1609 if (localSurface.fLogicId == 0) continue;
1610 nsurf_bool++;
1611 if (localSurface.fLogicId < 0) continue;
1612
1613 if (localSurface.fSkipConvexity) continue;
1614 switch (localSurface.fSurface.type) {
1615 case SurfaceType::kCylindrical:
1616 case SurfaceType::kSpherical:
1617 if (localSurface.fSurface.IsFlipped()) inner_surf = true;
1618 break;
1619 case SurfaceType::kConical:
1620 if (localSurface.fSurface.IsFlipped()) inner_surf = true;
1621 break;
1622 case SurfaceType::kTorus:
1623 if (fCPUdata.fTorusData[localSurface.fSurface.id].IsFlipped()) inner_surf = true;
1624 break;
1625 default:
1626 break;
1627 }
1628
1629 auto const &surfaceTransform = localSurface.fTrans;
1630 auto const inv_surfaceTransform = surfaceTransform.Inverse();
1631
1632
1633
1634
1635 for (auto other_idsurf = 0u; other_idsurf < rootShell.fExitingSurfaces.size(); other_idsurf++) {
1636
1637 if (other_idsurf == idsurf) continue;
1638
1639 auto other_exiting_ind = rootShell.fExitingSurfaces[other_idsurf];
1640 auto const other_localSurface = fCPUdata.fLocalSurfaces[rootShell.fSurfaces[other_exiting_ind]];
1641
1642
1643
1644 switch (other_localSurface.fSurface.type) {
1645 case SurfaceType::kCylindrical:
1646 case SurfaceType::kSpherical:
1647 if ((other_localSurface.fSurface.IsFlipped()) && inner_surf) surf_convex = false;
1648 break;
1649 case SurfaceType::kConical:
1650 if (other_localSurface.fSurface.IsFlipped() && inner_surf) surf_convex = false;
1651 break;
1652 case SurfaceType::kTorus:
1653 if (fCPUdata.fTorusData[other_localSurface.fSurface.id].IsFlipped() && inner_surf) surf_convex = false;
1654 break;
1655 default:
1656 break;
1657 }
1658
1659 bool flip = localSurface.fLogicId < 0;
1660 flip ^= other_localSurface.fLogicId < 0;
1661 Real_t tol = 10000 * vecgeom::kToleranceStrict<Real_t>;
1662
1663
1664
1665
1666
1667
1668
1669
1670 auto const other_lowert = boxes[2 * other_idsurf];
1671 auto const other_uppert = boxes[2 * other_idsurf + 1];
1672 Vector3D<double> other_lower(other_lowert[0], other_lowert[1], other_lowert[2]);
1673 Vector3D<double> other_upper(other_uppert[0], other_uppert[1], other_uppert[2]);
1674
1675
1676
1677
1678 vecgeom::ABBoxManager<double>::Instance().TransformBoundingBox(other_lower, other_upper, inv_surfaceTransform);
1679
1680 Vector3D<Real_t> corner1(other_lower.x(), other_lower.y(), other_lower.z());
1681 Vector3D<Real_t> corner2(other_upper.x(), other_lower.y(), other_lower.z());
1682 Vector3D<Real_t> corner3(other_lower.x(), other_upper.y(), other_lower.z());
1683 Vector3D<Real_t> corner4(other_upper.x(), other_upper.y(), other_lower.z());
1684 Vector3D<Real_t> corner5(other_lower.x(), other_lower.y(), other_upper.z());
1685 Vector3D<Real_t> corner6(other_upper.x(), other_lower.y(), other_upper.z());
1686 Vector3D<Real_t> corner7(other_lower.x(), other_upper.y(), other_upper.z());
1687 Vector3D<Real_t> corner8(other_upper.x(), other_upper.y(), other_upper.z());
1688
1689 bool inside_c1 = localSurface.fSurface.Inside(corner1, fCPUdata, flip, tol);
1690 bool inside_c2 = localSurface.fSurface.Inside(corner2, fCPUdata, flip, tol);
1691 bool inside_c3 = localSurface.fSurface.Inside(corner3, fCPUdata, flip, tol);
1692 bool inside_c4 = localSurface.fSurface.Inside(corner4, fCPUdata, flip, tol);
1693 bool inside_c5 = localSurface.fSurface.Inside(corner5, fCPUdata, flip, tol);
1694 bool inside_c6 = localSurface.fSurface.Inside(corner6, fCPUdata, flip, tol);
1695 bool inside_c7 = localSurface.fSurface.Inside(corner7, fCPUdata, flip, tol);
1696 bool inside_c8 = localSurface.fSurface.Inside(corner8, fCPUdata, flip, tol);
1697
1698
1699
1700
1701 surf_convex &=
1702 inside_c1 && inside_c2 && inside_c3 && inside_c4 && inside_c5 && inside_c6 && inside_c7 && inside_c8;
1703 }
1704 if (surf_convex) {
1705
1706 localSurface.fLogicId = 0;
1707 nsurf_bool_conv++;
1708 } else {
1709
1710 }
1711 }
1712 }
1713 if (fVerbose > 0)
1714 printf("\n Boolean Surface Convexity Check:\n convex boolean surfaces: %li total number of boolean surfaces %li "
1715 "ratio: %f\n",
1716 nsurf_bool_conv, nsurf_bool, double(nsurf_bool_conv) / nsurf_bool);
1717 }
1718
1719 template <typename Real_t>
1720 void BrepHelper<Real_t>::PrintCandidates(vecgeom::NavigationState const &state)
1721 {
1722 printf("\nCandidate surfaces per state: ");
1723 state.Print();
1724 unsigned short scene_id = 0, newscene_id = 0;
1725 bool is_scene = state.GetSceneId(scene_id, newscene_id);
1726 printf("is_scene=%d scene_id=%d newscene_id=%d\n", int(is_scene), scene_id, newscene_id);
1727 auto &cand = fSurfData->GetCandidates(scene_id, state.GetId());
1728 auto &cand_newscene = fSurfData->GetCandidates(newscene_id, 0);
1729 int ncand = is_scene ? cand.fNExiting + cand_newscene.fNcand - cand_newscene.fNExiting : cand.fNcand;
1730 printf(" %d candidates: exiting={", ncand);
1731 for (int i = 0; i < cand.fNExiting; ++i)
1732 printf("%d (side %d, ind %d) ", cand.fCandidates[i], int(cand.fSides[i]), cand.fFrameInd[i]);
1733 printf("} entering={");
1734 if (is_scene) {
1735
1736 for (int i = cand_newscene.fNExiting; i < cand_newscene.fNcand; ++i)
1737 printf("%d (side %d, ind %d) ", cand_newscene.fCandidates[i], int(cand_newscene.fSides[i]),
1738 cand_newscene.fFrameInd[i]);
1739 } else {
1740 for (int i = cand.fNExiting; i < cand.fNcand; ++i)
1741 printf("%d (side %d, ind %d) ", cand.fCandidates[i], int(cand.fSides[i]), cand.fFrameInd[i]);
1742 }
1743 printf("}\n");
1744 }
1745
1746 template <typename Real_t>
1747 void BrepHelper<Real_t>::PrintCandidateLists()
1748 {
1749 vecgeom::NavigationState state;
1750
1751
1752
1753 typedef std::function<void(vecgeom::VPlacedVolume const *)> func_t;
1754 func_t printCandidates = [&](vecgeom::VPlacedVolume const *pvol) {
1755 state.Push(pvol);
1756 const auto vol = pvol->GetLogicalVolume();
1757 auto daughters = vol->GetDaughters();
1758 int nd = daughters.size();
1759 PrintCandidates(state);
1760
1761
1762 for (int id = 0; id < nd; ++id) {
1763 printCandidates(daughters[id]);
1764 }
1765 state.Pop();
1766 };
1767
1768 PrintCandidates(state);
1769 printCandidates(vecgeom::GeoManager::Instance().GetWorld());
1770 }
1771
1772 template <typename Real_t>
1773 template <typename Real_i, typename Transformation_t>
1774 void BrepHelper<Real_t>::PrintFramedSurface(FramedSurface<Real_i, Transformation_t> const &surf)
1775 {
1776
1777 std::stringstream framedata;
1778 framedata << "FS: " << to_cstring(surf.fFrame.type);
1779 switch (surf.fFrame.type) {
1780 case FrameType::kRing: {
1781 auto const &data = fCPUdata.fRingMasks[surf.fFrame.id];
1782 framedata << " { rangeR{" << data.rangeR[0] << ", " << data.rangeR[1] << "}, isFullCirc{"
1783 << (data.isFullCirc ? "true" : "false") << "}, vecSPhi{" << data.vecSPhi << "}, vecEPhi{" << data.vecEPhi
1784 << "}}";
1785 } break;
1786 case FrameType::kZPhi: {
1787 auto const &data = fCPUdata.fZPhiMasks[surf.fFrame.id];
1788 framedata << " { rangeZ{" << data.rangeZ[0] << ", " << data.rangeZ[1] << "}, alpha{"
1789 << vecCore::math::ACos(1. / data.invcalf) * vecgeom::kRadToDeg << "}, vecSPhi{" << data.vecSPhi
1790 << "}, vecEPhi{" << data.vecEPhi << "}, isFullCirc{" << (data.isFullCirc ? "true" : "false") << "}}";
1791
1792 } break;
1793 case FrameType::kWindow: {
1794 auto const &data = fCPUdata.fWindowMasks[surf.fFrame.id];
1795 framedata << " { rangeU{" << data.rangeU[0] << ", " << data.rangeU[1] << "}, rangeV{" << data.rangeV[0] << ", "
1796 << data.rangeV[1] << "}}";
1797 } break;
1798
1799 case FrameType::kTriangle: {
1800 auto const &data = fCPUdata.fTriangleMasks[surf.fFrame.id];
1801 framedata << " { p{ 0:{" << data.p_[0] << "}, 1:{" << data.p_[1] << "}, 2:{" << data.p_[2] << "}, n0:{"
1802 << data.n_[0] << "}, n1:{" << data.n_[1] << "}, n2:{" << data.n_[2] << "}}";
1803 } break;
1804 case FrameType::kQuadrilateral: {
1805 auto const &data = fCPUdata.fQuadMasks[surf.fFrame.id];
1806 framedata << " { p{ 0:{" << data.p_[0] << "}, 1:{" << data.p_[1] << "}, 2:{" << data.p_[2] << "}, 3:{" << data.p_[3]
1807 << "}, n0:{" << data.n_[0] << "}, n1:{" << data.n_[1] << "}, n2:{" << data.n_[2] << "}, n3:{"
1808 << data.n_[3] << "}}";
1809 } break;
1810 case FrameType::kNoFrame:
1811 case FrameType::kRangeZ:
1812
1813
1814 case FrameType::kRangeSph:
1815
1816
1817 break;
1818 default:
1819
1820 framedata << " { no such frame type }";
1821 };
1822
1823 framedata << " fTrans{" << surf.fTrans << "} fParent{" << surf.fParent << "} fTraversal{" << surf.fTraversal
1824 << "} fLogicId{" << surf.fLogicId << "} fNeverCheck{" << surf.fNeverCheck << "} ";
1825 if (surf.fSceneCS) framedata << "fSceneCS{" << surf.fSceneCS << "} fSceneCSind{" << surf.fSceneCSind << "} ";
1826 framedata << "fEmbedding{" << to_cstring(surf.fEmbedding) << "} ";
1827 framedata << "fEmbedded{" << to_cstring(surf.fEmbedded) << "} ";
1828 framedata << "fVirtualParent{" << to_cstring(surf.fVirtualParent) << "} ";
1829 if (surf.fFrame.type != FrameType::kNoFrame) framedata << "fSurfIndex{" << surf.fSurfIndex << "} ";
1830 std::cout << framedata.str() << "\n fState: ";
1831 surf.PrintState();
1832 }
1833
1834 template <typename Real_t>
1835 void BrepHelper<Real_t>::PrintCommonSurface(int common_id)
1836 {
1837 if (common_id >= fSurfData->fNcommonSurf) {
1838 VECGEOM_LOG(error) << "You are trying to print a non-existent common surface " << common_id;
1839 return;
1840 }
1841 auto round0 = [](Real_t x) { return (std::abs(x) < vecgeom::kToleranceStrict<Real_t>) ? Real_t(0) : x; };
1842 vecgeom::Vector3D<Real_t> normal;
1843 const vecgeom::Vector3D<Real_t> lnorm(0, 0, 1);
1844 auto const &surf = fSurfData->fCommonSurfaces[common_id];
1845 surf.fTrans.InverseTransformDirection(lnorm, normal);
1846 vecgeom::NavigationState default_state(surf.fDefaultState);
1847 int scene_id = surf.GetSceneId();
1848 printf("\n== common surface %d: type: %s, scene %d, default state: ", common_id, to_cstring(surf.fType), scene_id);
1849 default_state.Print();
1850 printf(" transformation: ");
1851 surf.fTrans.Print();
1852 switch (surf.fType) {
1853 case SurfaceType::kPlanar: {
1854 printf("\n \x1B[34mleft:\x1B[0m %d surfaces, num_parents=%d, normal: (%g, %g, "
1855 "%g)\n",
1856 surf.fLeftSide.fNsurf, surf.fLeftSide.fNumParents, round0(normal[0]), round0(normal[1]), round0(normal[2]));
1857 break;
1858 }
1859 case SurfaceType::kCylindrical: {
1860 printf("\n \x1B[34mleft\x1B[0m: %d surfaces, num_parents=%d, {radius{%g}}\n", surf.fLeftSide.fNsurf,
1861 surf.fLeftSide.fNumParents, fSurfData->fFramedSurf[surf.fLeftSide.fSurfaces[0]].fSurface.fRadius);
1862 break;
1863 }
1864 case SurfaceType::kConical: {
1865 printf("\n \x1B[34mleft\x1B[0m: %d surfaces, num_parents=%d, {radius{%g}, slope{%g}}\n", surf.fLeftSide.fNsurf,
1866 surf.fLeftSide.fNumParents, fSurfData->fFramedSurf[surf.fLeftSide.fSurfaces[0]].fSurface.fRadius,
1867 fSurfData->fFramedSurf[surf.fLeftSide.fSurfaces[0]].fSurface.fSlope);
1868 break;
1869 }
1870 case SurfaceType::kElliptical:
1871 case SurfaceType::kSpherical:
1872 case SurfaceType::kTorus:
1873 case SurfaceType::kArb4:
1874 default:
1875 VECGEOM_LOG(error) << "Surface type " << to_cstring(surf.fType) << " not implemented";
1876 }
1877 for (int i = 0; i < surf.fLeftSide.fNsurf; ++i) {
1878 int idglob = surf.fLeftSide.fSurfaces[i];
1879 auto const &placed = fSurfData->fFramedSurf[idglob];
1880 printf("%d: iframe=%d ", i, idglob);
1881 PrintFramedSurface(placed);
1882 }
1883 if (surf.fRightSide.fNsurf > 0) {
1884 switch (surf.fType) {
1885 case SurfaceType::kPlanar: {
1886 printf(" \x1B[31mright:\x1B[0m %d surfaces, num_parents=%d, normal: (%g, "
1887 "%g, %g)\n",
1888 surf.fRightSide.fNsurf, surf.fRightSide.fNumParents, round0(-normal[0]), round0(-normal[1]),
1889 round0(-normal[2]));
1890 break;
1891 }
1892 case SurfaceType::kCylindrical: {
1893 printf(" \x1B[31mright:\x1B[0m %d surfaces, num_parents=%d}\n", surf.fRightSide.fNsurf,
1894 surf.fRightSide.fNumParents);
1895 break;
1896 }
1897 case SurfaceType::kConical: {
1898 printf("\n \x1B[31mright\x1B[0m: %d surfaces, num_parents=%d\n", surf.fRightSide.fNsurf,
1899 surf.fRightSide.fNumParents);
1900 break;
1901 }
1902 case SurfaceType::kElliptical:
1903 case SurfaceType::kSpherical:
1904 case SurfaceType::kTorus:
1905 case SurfaceType::kArb4:
1906 default:
1907 VECGEOM_LOG(error) << "Surface type " << to_cstring(surf.fType) << " not implemented";
1908 }
1909 } else {
1910 printf(" \x1B[31mright:\x1B[0m 0 surfaces\n");
1911 }
1912
1913 for (int i = 0; i < surf.fRightSide.fNsurf; ++i) {
1914 int idglob = surf.fRightSide.fSurfaces[i];
1915 auto const &placed = fSurfData->fFramedSurf[idglob];
1916 printf("%d: iframe=%d ", i, idglob);
1917 PrintFramedSurface(placed);
1918 }
1919 }
1920
1921 template <typename Real_t>
1922 void BrepHelper<Real_t>::PrintSurfData()
1923 {
1924 constexpr int megabyte = 1024 * 1024;
1925 float total = 0, size = 0;
1926 auto msg = VECGEOM_LOG(info);
1927 size_t ndivX{0}, ndivY{0}, ndivZ{0}, ndivR{0}, ndivXY{0};
1928 for (auto const &div : fCPUdata.fSideDivisions) {
1929 ndivX += div.fAxis == AxisType::kX;
1930 ndivY += div.fAxis == AxisType::kY;
1931 ndivZ += div.fAxis == AxisType::kZ;
1932 ndivR += div.fAxis == AxisType::kR;
1933 ndivXY += div.fAxis == AxisType::kXY;
1934 }
1935
1936 msg << "___________________________________________________________________________________\n";
1937 msg << " Surface model info: " << vecgeom::GeoManager::Instance().GetTotalNodeCount() + 1 << " touchables, "
1938 << fSurfData->fNscenes << " scenes\n";
1939 size = float(fSurfData->fNshells * sizeof(VolumeShell) + fSurfData->fNlocalSurf * sizeof(int)) / megabyte;
1940 total += size;
1941 msg << " volume shells = " << fSurfData->fNshells << " [" << size << " MB]\n";
1942 size =
1943 float(fSurfData->fNEnteringSurfaces * 4 * sizeof(int) + fSurfData->fNEnteringSurfaces * sizeof(int)) / megabyte;
1944 total += size;
1945 msg << " Entering surface list = " << fSurfData->fNEnteringSurfaces << " [" << size << " MB]\n";
1946 size = float(fSurfData->fNExitingSurfaces * 4 * sizeof(int) + fSurfData->fNExitingSurfaces * sizeof(int)) / megabyte;
1947 total += size;
1948 msg << " Exiting surface list = " << fSurfData->fNExitingSurfaces << " [" << size << " MB]\n";
1949 size = float(fSurfData->fNvolTrans * sizeof(Transformation)) / megabyte;
1950 total += size;
1951 msg << " volume transformations = " << fSurfData->fNvolTrans << " [" << size << " MB]\n";
1952 size = float(fSurfData->fNlocalSurf * sizeof(FramedSurface<Real_t, TransformationMP<Real_t>>)) / megabyte;
1953 total += size;
1954 msg << " local surfaces = " << fSurfData->fNlocalSurf << " [" << size << " MB]\n";
1955 size = float(fSurfData->fNglobalSurf * sizeof(FramedSurface<Real_t, TransformationMP<Real_t>>)) / megabyte;
1956 total += size;
1957 msg << " global surfaces = " << fSurfData->fNglobalSurf << " [" << size << " MB]\n";
1958 size = float(fSurfData->fNcommonSurf * sizeof(CommonSurface<Real_t>) + fSurfData->fNsides * sizeof(int)) / megabyte;
1959 total += size;
1960 msg << " common surfaces = " << fSurfData->fNcommonSurf << " [" << size << " MB]\n";
1961 size = float(fSurfData->fNsideDivisions * sizeof(SideDivision_t) + fSurfData->fNslices * sizeof(SliceCand) +
1962 fSurfData->fNsliceCandidates * sizeof(int)) /
1963 megabyte;
1964 total += size;
1965 msg << " side divisions = " << fSurfData->fNsideDivisions << " [" << size << " MB]\n";
1966 msg << " planar { X=" << ndivX << " Y=" << ndivY << " kR=" << ndivR << " XY=" << ndivXY
1967 << " } cylindrical { Z=" << ndivZ << " }\n";
1968 size = float(fSurfData->fSizeCandList * sizeof(int)) / megabyte;
1969 total += size;
1970 msg << " candidates = " << fSurfData->fSizeCandList << " [" << size << " MB]\n";
1971 size = float(fSurfData->fNwindows * sizeof(WindowMask_t)) / megabyte;
1972 total += size;
1973 msg << " window masks = " << fSurfData->fNwindows << " [" << size << " MB]\n";
1974 size = float(fSurfData->fNrings * sizeof(RingMask_t)) / megabyte;
1975 total += size;
1976 msg << " ring masks = " << fSurfData->fNrings << " [" << size << " MB]\n";
1977 size = float(fSurfData->fNzphis * sizeof(ZPhiMask_t)) / megabyte;
1978 total += size;
1979 msg << " Z/phi masks = " << fSurfData->fNzphis << " [" << size << " MB]\n";
1980 size = float(fSurfData->fNtriangs * sizeof(TriangleMask_t)) / megabyte;
1981 total += size;
1982 msg << " triangle masks = " << fSurfData->fNtriangs << " [" << size << " MB]\n";
1983 size = float(fSurfData->fNquads * sizeof(QuadMask_t)) / megabyte;
1984 total += size;
1985 msg << " quad masks = " << fSurfData->fNquads << " [" << size << " MB]\n";
1986 size = float(fSurfData->fNshells * sizeof(int)) / megabyte;
1987
1988 for (int i = 0; i < fSurfData->fNshells; i++) {
1989 size += float(fSurfData->fBVH[fSurfData->fShells[i].fBVH].GetAllocatedSize()) / megabyte;
1990 }
1991 total += size;
1992 msg << " BVHs = " << fSurfData->fNshells << " [" << size << " MB]\n";
1993
1994 msg << " Total: " << total << "[MB]\n";
1995 msg << "___________________________________________________________________________________\n";
1996 }
1997
1998 template <typename Real_t>
1999 void BrepHelper<Real_t>::SetNvolumes(int nvolumes)
2000 {
2001 if (fCPUdata.fShells.size() > 0) {
2002 VECGEOM_LOG(warning) << "BrepHelper::SetNvolumes already called for this instance";
2003 return;
2004 }
2005 fCPUdata.fShells.resize(nvolumes);
2006 fCPUdata.fSceneShells.resize(nvolumes);
2007 }
2008
2009 template <typename Real_t>
2010 void BrepHelper<Real_t>::UpdateMaskData()
2011 {
2012 fSurfData->fNwindows = fCPUdata.fWindowMasks.size();
2013 delete[] fSurfData->fWindowMasks;
2014 fSurfData->fWindowMasks = new WindowMask_t[fCPUdata.fWindowMasks.size()];
2015 for (size_t i = 0; i < fCPUdata.fWindowMasks.size(); ++i)
2016 fSurfData->fWindowMasks[i] = fCPUdata.fWindowMasks[i];
2017
2018 fSurfData->fNrings = fCPUdata.fRingMasks.size();
2019 delete[] fSurfData->fRingMasks;
2020 fSurfData->fRingMasks = new RingMask_t[fCPUdata.fRingMasks.size()];
2021 for (size_t i = 0; i < fCPUdata.fRingMasks.size(); ++i)
2022 fSurfData->fRingMasks[i] = fCPUdata.fRingMasks[i];
2023
2024 fSurfData->fNzphis = fCPUdata.fZPhiMasks.size();
2025 delete[] fSurfData->fZPhiMasks;
2026 fSurfData->fZPhiMasks = new ZPhiMask_t[fCPUdata.fZPhiMasks.size()];
2027 for (size_t i = 0; i < fCPUdata.fZPhiMasks.size(); ++i)
2028 fSurfData->fZPhiMasks[i] = fCPUdata.fZPhiMasks[i];
2029
2030 fSurfData->fNquads = fCPUdata.fQuadMasks.size();
2031 delete[] fSurfData->fQuadMasks;
2032 fSurfData->fQuadMasks = new QuadMask_t[fCPUdata.fQuadMasks.size()];
2033 for (size_t i = 0; i < fCPUdata.fQuadMasks.size(); ++i)
2034 fSurfData->fQuadMasks[i] = fCPUdata.fQuadMasks[i];
2035
2036 fSurfData->fNtriangs = fCPUdata.fTriangleMasks.size();
2037 fSurfData->fTriangleMasks = new TriangleMask_t[fCPUdata.fTriangleMasks.size()];
2038 for (size_t i = 0; i < fCPUdata.fTriangleMasks.size(); ++i)
2039 fSurfData->fTriangleMasks[i] = fCPUdata.fTriangleMasks[i];
2040 }
2041
2042 template <typename Real_t>
2043 void BrepHelper<Real_t>::UpdateSurfData()
2044 {
2045
2046
2047
2048 fSurfData->fNvolTrans = fCPUdata.fPVolTrans.size();
2049 fSurfData->fPVolTrans = new TransformationMP<Real_t>[fCPUdata.fPVolTrans.size()];
2050 for (size_t i = 0; i < fCPUdata.fPVolTrans.size(); ++i)
2051 fSurfData->fPVolTrans[i] = fCPUdata.fPVolTrans[i];
2052
2053
2054 auto numLocalSurf = fCPUdata.fLocalSurfaces.size();
2055 fSurfData->fNlocalSurf = numLocalSurf;
2056 fSurfData->fLocalSurf = new FramedSurface<Real_t, TransformationMP<Real_t>>[numLocalSurf];
2057 for (size_t i = 0; i < numLocalSurf; ++i)
2058 fSurfData->fLocalSurf[i] = fCPUdata.fLocalSurfaces[i];
2059
2060
2061 auto numGlobalSurf = fCPUdata.fFramedSurf.size();
2062 fSurfData->fNglobalSurf = numGlobalSurf;
2063 fSurfData->fFramedSurf = new FramedSurface<Real_t, vecgeom::Transformation2DMP<Real_t>>[numGlobalSurf];
2064 for (size_t i = 0; i < numGlobalSurf; ++i)
2065 fSurfData->fFramedSurf[i] = FramedSurface<Real_t, vecgeom::Transformation2DMP<Real_t>>(fCPUdata.fFramedSurf[i]);
2066
2067
2068 fSurfData->fNellip = fCPUdata.fEllipData.size();
2069 fSurfData->fEllipData = new EllipData_t[fCPUdata.fEllipData.size()];
2070 for (size_t i = 0; i < fCPUdata.fEllipData.size(); ++i)
2071 fSurfData->fEllipData[i] = fCPUdata.fEllipData[i];
2072
2073 fSurfData->fNtorus = fCPUdata.fTorusData.size();
2074 fSurfData->fTorusData = new TorusData_t[fCPUdata.fTorusData.size()];
2075 for (size_t i = 0; i < fCPUdata.fTorusData.size(); ++i)
2076 fSurfData->fTorusData[i] = fCPUdata.fTorusData[i];
2077
2078 fSurfData->fNarb4 = fCPUdata.fArb4Data.size();
2079 fSurfData->fArb4Data = new Arb4Data_t[fCPUdata.fArb4Data.size()];
2080 for (size_t i = 0; i < fCPUdata.fArb4Data.size(); ++i)
2081 fSurfData->fArb4Data[i] = fCPUdata.fArb4Data[i];
2082
2083
2084 UpdateMaskData();
2085
2086
2087 size_t size_sides = 0;
2088 for (auto const &surf : fCPUdata.fCommonSurfaces)
2089 size_sides += surf.fLeftSide.fNsurf + surf.fRightSide.fNsurf;
2090 fSurfData->fNsides = size_sides;
2091 fSurfData->fSides = new int[size_sides];
2092 int *current_side = fSurfData->fSides;
2093 fSurfData->fNcommonSurf = fCPUdata.fCommonSurfaces.size();
2094 fSurfData->fCommonSurfaces = new CommonSurface<Real_t>[fSurfData->fNcommonSurf];
2095 for (size_t i = 0; i < fCPUdata.fCommonSurfaces.size(); ++i) {
2096
2097 fSurfData->fCommonSurfaces[i] = fCPUdata.fCommonSurfaces[i];
2098
2099 for (auto isurf = 0; isurf < fCPUdata.fCommonSurfaces[i].fLeftSide.fNsurf; ++isurf)
2100 current_side[isurf] = fCPUdata.fCommonSurfaces[i].fLeftSide.fSurfaces[isurf];
2101
2102 fSurfData->fCommonSurfaces[i].fLeftSide.fSurfaces = current_side;
2103 current_side += fCPUdata.fCommonSurfaces[i].fLeftSide.fNsurf;
2104
2105 for (auto isurf = 0; isurf < fCPUdata.fCommonSurfaces[i].fRightSide.fNsurf; ++isurf)
2106 current_side[isurf] = fCPUdata.fCommonSurfaces[i].fRightSide.fSurfaces[isurf];
2107
2108 fSurfData->fCommonSurfaces[i].fRightSide.fSurfaces = current_side;
2109 current_side += fCPUdata.fCommonSurfaces[i].fRightSide.fNsurf;
2110
2111 fSurfData->fCommonSurfaces[i].fLeftSide.fNumParents = fCPUdata.fCommonSurfaces[i].fLeftSide.fNumParents;
2112 fSurfData->fCommonSurfaces[i].fRightSide.fNumParents = fCPUdata.fCommonSurfaces[i].fRightSide.fNumParents;
2113 }
2114
2115
2116 auto nscenes = fCPUdata.fSceneStartIndex.size();
2117 fSurfData->fNscenes = nscenes;
2118
2119 fSurfData->fSceneStartIndex = new int[nscenes];
2120 fSurfData->fSceneTouchables = new int[nscenes];
2121 for (size_t scene_id = 0; scene_id < nscenes; ++scene_id) {
2122 fSurfData->fSceneStartIndex[scene_id] = fCPUdata.fSceneStartIndex[scene_id];
2123 fSurfData->fSceneTouchables[scene_id] = fCPUdata.fSceneTouchables[scene_id];
2124 }
2125
2126
2127
2128 size_t num_states = fCPUdata.fCandidatesEntering.size();
2129 fSurfData->fNStates = num_states;
2130
2131 auto size_candidates = 0;
2132 for (auto const &list : fCPUdata.fCandidatesExiting) {
2133 size_candidates += 2 * list.size() + list.size() * sizeof(char) / sizeof(int) + 1;
2134 }
2135 for (auto const &list : fCPUdata.fCandidatesEntering) {
2136 size_candidates += 2 * list.size() + list.size() * sizeof(char) / sizeof(int) + 1;
2137 }
2138
2139 size_candidates += num_states;
2140
2141
2142 fSurfData->fSizeCandList = size_candidates;
2143 fSurfData->fCandList = new int[size_candidates];
2144 int *current_candidates = fSurfData->fCandList;
2145
2146 fSurfData->fCandidates = new Candidates[num_states];
2147
2148 for (size_t i = 0; i < num_states; ++i) {
2149
2150
2151
2152
2153 size_t offset = 0;
2154
2155
2156 auto ncandExiting = fCPUdata.fCandidatesExiting[i].size();
2157 for (size_t icand = 0; icand < ncandExiting; icand++) {
2158 current_candidates[icand] = (fCPUdata.fCandidatesExiting[i])[icand];
2159 }
2160
2161 offset += ncandExiting;
2162
2163
2164 auto ncandEntering = fCPUdata.fCandidatesEntering[i].size();
2165 for (size_t icand = 0; icand < ncandEntering; icand++) {
2166 current_candidates[icand + offset] = (fCPUdata.fCandidatesEntering[i])[icand];
2167 }
2168
2169 offset += ncandEntering;
2170
2171
2172 for (size_t icand = 0; icand < ncandExiting; icand++) {
2173 current_candidates[icand + offset] = (fCPUdata.fFrameIndExiting[i])[icand];
2174 }
2175
2176 offset += ncandExiting;
2177
2178
2179 for (size_t icand = 0; icand < ncandEntering; icand++) {
2180 current_candidates[icand + offset] = (fCPUdata.fFrameIndEntering[i])[icand];
2181 }
2182
2183 offset += ncandEntering;
2184
2185
2186 char *current_sides = reinterpret_cast<char *>(current_candidates + offset);
2187 for (size_t icand = 0; icand < ncandExiting; icand++) {
2188 current_sides[icand] = (fCPUdata.fSidesExiting[i])[icand];
2189 }
2190
2191
2192 current_sides += ncandExiting;
2193 for (size_t icand = 0; icand < ncandEntering; icand++) {
2194 current_sides[icand] = (fCPUdata.fSidesEntering[i])[icand];
2195 }
2196
2197
2198 auto ncand = ncandEntering + ncandExiting;
2199 int add_one = ((ncand * sizeof(char)) % sizeof(int)) > 0 ? 1 : 0;
2200 offset += ncand * sizeof(char) / sizeof(int) + add_one;
2201
2202
2203 fSurfData->fCandidates[i].fNcand = ncand;
2204 fSurfData->fCandidates[i].fNExiting = ncandExiting;
2205
2206 fSurfData->fCandidates[i].fCandidates = current_candidates;
2207
2208 fSurfData->fCandidates[i].fFrameInd = current_candidates + ncand;
2209
2210 fSurfData->fCandidates[i].fSides = reinterpret_cast<char *>(current_candidates + 2 * ncand);
2211
2212 current_candidates += offset;
2213 }
2214
2215
2216 auto numShells = fCPUdata.fShells.size();
2217 fSurfData->fNshells = numShells;
2218 fSurfData->fShells = new VolumeShell[numShells];
2219
2220 fSurfData->fSurfShellList = new int[numLocalSurf];
2221 int *current_surf = fSurfData->fSurfShellList;
2222
2223 size_t sizeLogic = 0;
2224 for (size_t i = 0; i < numShells; ++i) {
2225 sizeLogic += fCPUdata.fShells[i].fLogic.size();
2226 }
2227 fSurfData->fLogicList = new logic_int[sizeLogic];
2228 fSurfData->fNlogic = sizeLogic;
2229 logic_int *current_logic = fSurfData->fLogicList;
2230
2231
2232 for (const auto &shell : fCPUdata.fShells) {
2233 fSurfData->fNExitingSurfaces += shell.fExitingSurfaces.size();
2234 fSurfData->fNEnteringSurfaces += shell.fEnteringSurfaces.size();
2235 }
2236 fSurfData->fNPlacedVolumes = vecgeom::GeoManager::Instance().GetPlacedVolumesCount();
2237
2238 fSurfData->fShellExitingSurfaceList = new int[fSurfData->fNExitingSurfaces];
2239 fSurfData->fShellEnteringSurfaceList = new int[fSurfData->fNEnteringSurfaces];
2240 fSurfData->fShellEnteringSurfacePvolList = new int[fSurfData->fNEnteringSurfaces];
2241 fSurfData->fShellEnteringSurfacePvolTransList = new int[fSurfData->fNEnteringSurfaces];
2242 fSurfData->fShellEnteringSurfaceLvolIdList = new int[fSurfData->fNEnteringSurfaces];
2243 fSurfData->fShellDaughterPvolIdList = new int[fSurfData->fNPlacedVolumes];
2244 fSurfData->fShellDaughterPvolTransList = new int[fSurfData->fNPlacedVolumes];
2245
2246 int *currentExitingSurface = fSurfData->fShellExitingSurfaceList;
2247 int *currentEnteringSurface = fSurfData->fShellEnteringSurfaceList;
2248 int *currentEnteringSurfacePvol = fSurfData->fShellEnteringSurfacePvolList;
2249 int *currentShellEnteringSurfacePvolTrans = fSurfData->fShellEnteringSurfacePvolTransList;
2250 int *currentShellEnteringSurfaceLvolId = fSurfData->fShellEnteringSurfaceLvolIdList;
2251 int *currentShellDaughterPvolId = fSurfData->fShellDaughterPvolIdList;
2252 int *currentShellDaughterPvolTrans = fSurfData->fShellDaughterPvolTransList;
2253
2254 for (size_t i = 0; i < numShells; ++i) {
2255 auto const &surfaces = fCPUdata.fShells[i].fSurfaces;
2256 auto nsurf = surfaces.size();
2257 fSurfData->fShells[i].fNsurf = nsurf;
2258 for (size_t isurf = 0; isurf < nsurf; isurf++)
2259 current_surf[isurf] = surfaces[isurf];
2260 fSurfData->fShells[i].fSurfaces = current_surf;
2261 current_surf += nsurf;
2262 auto nlogic = fCPUdata.fShells[i].fLogic.size();
2263 fSurfData->fShells[i].fLogic.size_ = nlogic;
2264 fSurfData->fShells[i].fLogic.data_ = current_logic;
2265 int iitem = 0;
2266 for (auto item : fCPUdata.fShells[i].fLogic)
2267 fSurfData->fShells[i].fLogic.data_[iitem++] = item;
2268 current_logic += nlogic;
2269
2270 auto const &exitingSurfaces = fCPUdata.fShells[i].fExitingSurfaces;
2271 auto const &enteringSurfaces = fCPUdata.fShells[i].fEnteringSurfaces;
2272 auto const &enteringSurfacesPvol = fCPUdata.fShells[i].fEnteringSurfacesPvol;
2273 auto const &enteringSurfacesPvolTrans = fCPUdata.fShells[i].fEnteringSurfacesPvolTrans;
2274 auto const &enteringSurfacesLvolIds = fCPUdata.fShells[i].fEnteringSurfacesLvolIds;
2275 auto const &daughterPvolIds = fCPUdata.fShells[i].fDaughterPvolIds;
2276 auto const &daughterPvolTrans = fCPUdata.fShells[i].fDaughterPvolTrans;
2277 auto nExitingSurf = exitingSurfaces.size();
2278 auto nEnteringSurf = enteringSurfaces.size();
2279 auto nDaughterPvol = daughterPvolIds.size();
2280
2281 fSurfData->fShells[i].fNExitingSurfaces = nExitingSurf;
2282 fSurfData->fShells[i].fNEnteringSurfaces = nEnteringSurf;
2283 fSurfData->fShells[i].fNDaughterPvols = nDaughterPvol;
2284
2285 for (size_t isurf = 0; isurf < nExitingSurf; isurf++)
2286 currentExitingSurface[isurf] = exitingSurfaces[isurf];
2287 for (size_t isurf = 0; isurf < nEnteringSurf; isurf++) {
2288 currentEnteringSurface[isurf] = enteringSurfaces[isurf];
2289 currentEnteringSurfacePvol[isurf] = enteringSurfacesPvol[isurf];
2290 currentShellEnteringSurfacePvolTrans[isurf] = enteringSurfacesPvolTrans[isurf];
2291 currentShellEnteringSurfaceLvolId[isurf] = enteringSurfacesLvolIds[isurf];
2292 }
2293
2294 for (size_t ivol = 0; ivol < nDaughterPvol; ivol++) {
2295 currentShellDaughterPvolId[ivol] = daughterPvolIds[ivol];
2296 currentShellDaughterPvolTrans[ivol] = daughterPvolTrans[ivol];
2297 }
2298
2299
2300 fSurfData->fShells[i].fExitingSurfaces = currentExitingSurface;
2301 fSurfData->fShells[i].fEnteringSurfaces = currentEnteringSurface;
2302 fSurfData->fShells[i].fEnteringSurfacesPvol = currentEnteringSurfacePvol;
2303 fSurfData->fShells[i].fEnteringSurfacesPvolTrans = currentShellEnteringSurfacePvolTrans;
2304 fSurfData->fShells[i].fEnteringSurfacesLvolIds = currentShellEnteringSurfaceLvolId;
2305 fSurfData->fShells[i].fDaughterPvolIds = currentShellDaughterPvolId;
2306 fSurfData->fShells[i].fDaughterPvolTrans = currentShellDaughterPvolTrans;
2307
2308 currentExitingSurface += nExitingSurf;
2309 currentEnteringSurface += nEnteringSurf;
2310 currentEnteringSurfacePvol += nEnteringSurf;
2311 currentShellEnteringSurfacePvolTrans += nEnteringSurf;
2312 currentShellEnteringSurfaceLvolId += nEnteringSurf;
2313 currentShellDaughterPvolId += nDaughterPvol;
2314 currentShellDaughterPvolTrans += nDaughterPvol;
2315
2316 fSurfData->fShells[i].fBVH = fCPUdata.fShells[i].fBVH;
2317 }
2318 }
2319
2320
2321 template class BrepHelper<double>;
2322 template class BrepHelper<float>;
2323
2324 }