Skip to content

Commit

Permalink
[geom] Extended TGeoVGShape with extra solids
Browse files Browse the repository at this point in the history
Added support for tesselated, ellipsoid, hyperboloid and cut tube. Added the macro tutorials/geom/tessellatedNav.C importing and raytracing a tessellated solid.
  • Loading branch information
agheata authored and pcanal committed Feb 15, 2023
1 parent 5982340 commit 07e2f5c
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 8 deletions.
4 changes: 2 additions & 2 deletions geom/geom/inc/TGeoTessellated.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ class TGeoTessellated : public TGeoBBox {
bool IsClosedBody() const { return fClosedBody; }
bool IsDefined() const { return fDefined; }

const TGeoFacet &GetFacet(int i) { return fFacets[i]; }
const Vertex_t &GetVertex(int i) { return fVertices[i]; }
const TGeoFacet &GetFacet(int i) const { return fFacets[i]; }
const Vertex_t &GetVertex(int i) const { return fVertices[i]; }

virtual void AfterStreamer();
virtual int DistancetoPrimitive(int, int) { return 99999; }
Expand Down
62 changes: 56 additions & 6 deletions geom/vecgeom/src/TGeoVGShape.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ Bridge class for using a VecGeom solid as TGeoShape.
#include "VecGeom/volumes/UnplacedScaledShape.h"
#include "VecGeom/volumes/UnplacedGenTrap.h"
#include "VecGeom/volumes/UnplacedSExtruVolume.h"
#include "VecGeom/volumes/UnplacedTessellated.h"
#include "VecGeom/volumes/UnplacedEllipticalTube.h"
#include "VecGeom/volumes/UnplacedHype.h"
#include "VecGeom/volumes/UnplacedCutTube.h"

#include "TError.h"
#include "TGeoManager.h"
#include "TGeoMaterial.h"
Expand All @@ -54,6 +59,8 @@ Bridge class for using a VecGeom solid as TGeoShape.
#include "TGeoTorus.h"
#include "TGeoEltu.h"
#include "TGeoXtru.h"
#include "TGeoTessellated.h"
#include "TGeoHype.h"

////////////////////////////////////////////////////////////////////////////////
/// Default constructor
Expand Down Expand Up @@ -122,6 +129,7 @@ vecgeom::cxx::Transformation3D *TGeoVGShape::Convert(TGeoMatrix const *const geo
vecgeom::cxx::VUnplacedVolume *TGeoVGShape::Convert(TGeoShape const *const shape)
{
using namespace vecgeom;
using Vector3D = vecgeom::cxx::Vector3D<Precision>;
VUnplacedVolume *unplaced_volume = nullptr;

// THE BOX
Expand Down Expand Up @@ -287,20 +295,36 @@ vecgeom::cxx::VUnplacedVolume *TGeoVGShape::Convert(TGeoShape const *const shape
GeoManager::MakeInstance<UnplacedScaledShape>(referenced_shape, scale_root[0], scale_root[1], scale_root[2]);
}

// THE ELLIPTICAL TUBE AS SCALED TUBE
// THE CUT TUBE
if (shape->IsA() == TGeoCtub::Class()) {
TGeoCtub const *const p = static_cast<TGeoCtub const *>(shape);
auto low = p->GetNlow();
auto high = p->GetNhigh();
auto const bottomNormal = Vector3D{low[0], low[1], low[2]};
auto const topNormal = Vector3D{high[0], high[1], high[2]};

unplaced_volume =
GeoManager::MakeInstance<UnplacedCutTube>(p->GetRmin(), p->GetRmax(), p->GetDz(), kDegToRad * p->GetPhi1(),
kDegToRad * (p->GetPhi2() - p->GetPhi1()), bottomNormal, topNormal);
}

// THE ELLIPTICAL TUBE
if (shape->IsA() == TGeoEltu::Class()) {
TGeoEltu const *const p = static_cast<TGeoEltu const *>(shape);
// Create the corresponding unplaced tube, with:
// rmin=0, rmax=A, dz=dz, which is scaled with (1., A/B, 1.)
GenericUnplacedTube *tubeUnplaced = new GenericUnplacedTube(0, p->GetA(), p->GetDZ(), 0, kTwoPi);
unplaced_volume = new UnplacedScaledShape(tubeUnplaced, 1., p->GetB() / p->GetA(), 1.);
unplaced_volume = GeoManager::MakeInstance<UnplacedEllipticalTube>(p->GetA(), p->GetB(), p->GetDz());
}

// THE HYPERBOLOID
if (shape->IsA() == TGeoHype::Class()) {
TGeoHype const *const p = static_cast<TGeoHype const *>(shape);
unplaced_volume = GeoManager::MakeInstance<UnplacedHype>(p->GetRmin(), p->GetRmax(), kDegToRad * p->GetStIn(),
kDegToRad * p->GetStOut(), p->GetDz());
}

// THE ARB8
if (shape->IsA() == TGeoArb8::Class() || shape->IsA() == TGeoGtra::Class()) {
TGeoArb8 *p = (TGeoArb8 *)(shape);
// Create the corresponding GenTrap
std::vector<Vector3D<Precision>> vertexlist;
const double *vertices = p->GetVertices();
Precision verticesx[8], verticesy[8];
for (auto ivert = 0; ivert < 8; ++ivert) {
Expand Down Expand Up @@ -338,6 +362,32 @@ vecgeom::cxx::VUnplacedVolume *TGeoVGShape::Convert(TGeoShape const *const shape
}
}

// THE TESSELLATED
if (shape->IsA() == TGeoTessellated::Class()) {
TGeoTessellated const *const tsl = static_cast<TGeoTessellated const *>(shape);
unplaced_volume = GeoManager::MakeInstance<UnplacedTessellated>();
auto vtsl = static_cast<UnplacedTessellated *>(unplaced_volume);

for (auto i = 0; i < tsl->GetNfacets(); ++i) {
auto const &facet = tsl->GetFacet(i);
int nvert = facet.GetNvert();
auto const &v0 = facet.GetVertex(0);
auto const &v1 = facet.GetVertex(1);
auto const &v2 = facet.GetVertex(2);
if (nvert == 3) {
vtsl->AddTriangularFacet(Vector3D(v0[0], v0[1], v0[2]), Vector3D(v1[0], v1[1], v1[2]),
Vector3D(v2[0], v2[1], v2[2]));
} else if (nvert == 4) {
auto const &v3 = facet.GetVertex(3);
vtsl->AddQuadrilateralFacet(Vector3D(v0[0], v0[1], v0[2]), Vector3D(v1[0], v1[1], v1[2]),
Vector3D(v2[0], v2[1], v2[2]), Vector3D(v3[0], v3[1], v3[2]));
} else {
return nullptr; // should never happen
}
}
vtsl->Close();
}

// New volumes should be implemented here...
if (!unplaced_volume) {
printf("Unsupported shape for ROOT shape \"%s\" of type %s. "
Expand Down
5 changes: 5 additions & 0 deletions tutorials/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ else()
endif()
endif()

if (NOT ROOT_vecgeom_FOUND)
set(vecgeom_veto geom/tessellatedNav.C)
endif()

if(root7)
set(root7_veto dataframe/df013_InspectAnalysis.C
v7/browser.cxx
Expand Down Expand Up @@ -446,6 +450,7 @@ set(all_veto hsimple.C
${imt_veto}
${classic_veto}
${pythia_veto}
${vecgeom_veto}
${root7_veto}
${xrootd_veto}
${mlp_veto}
Expand Down
81 changes: 81 additions & 0 deletions tutorials/geom/tessellatedNav.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/// \file
/// \ingroup tutorial_geom
/// Macro allowing to vizualize tessellations from Wavefront's .obj format.
///
/// \image html geom_visualizeWavefrontObj.png width=500px
/// \macro_code
///
/// \author Andrei Gheata

#include <TROOT.h>
#include <TColor.h>
#include <TDatime.h>
#include <TRandom3.h>
#include <TGeoManager.h>
#include <TGeoTessellated.h>
#include <TVirtualGeoConverter.h>
#include <TView.h>

//______________________________________________________________________________
int randomColor()
{
gRandom = new TRandom3();
TDatime dt;
gRandom->SetSeed(dt.GetTime());
int ci = TColor::GetFreeColorIndex();
TColor *color = new TColor(ci, gRandom->Rndm(), gRandom->Rndm(), gRandom->Rndm());
return ci;
}

//______________________________________________________________________________
void tessellatedNav(const char *dot_obj_file = "", bool check = false)
{
// Input a file in .obj format (https://en.wikipedia.org/wiki/Wavefront_.obj_file)
// The file should have a single object inside, only vertex and faces information is used
TString name = dot_obj_file;
TString sfile = dot_obj_file;
if (sfile.IsNull()) {
sfile = gROOT->GetTutorialsDir();
sfile += "/geom/teddy.obj";
}
name.ReplaceAll(".obj", "");
gROOT->GetListOfCanvases()->Delete();
if (gGeoManager)
delete gGeoManager;
auto geom = new TGeoManager(name, "Imported from .obj file");
TGeoMaterial *mat = new TGeoMaterial("Al", 26.98, 13, 2.7);
TGeoMedium *med = new TGeoMedium("MED", 1, mat);
TGeoVolume *top = geom->MakeBox("TOP", med, 10, 10, 10);
geom->SetTopVolume(top);

auto tsl = TGeoTessellated::ImportFromObjFormat(sfile.Data(), check);
if (!tsl)
return;
tsl->ResizeCenter(5.);

TGeoVolume *vol = new TGeoVolume(name, tsl, med);
vol->SetLineColor(randomColor());
vol->SetLineWidth(2);
top->AddNode(vol, 1);
geom->CloseGeometry();

// Convert to VecGeom tessellated solid
auto converter = TVirtualGeoConverter::Instance(geom);
if (!converter) {
printf("Raytracing a tessellated shape without VecGeom support will just draw a box\n");
} else {
converter->ConvertGeometry();
}

if (gROOT->IsBatch())
return;
// Set the view
top->Draw();
TView *view = gPad->GetView();
if (!view)
return;
view->Top();

// Raytracing will call VecGeom navigation
top->Raytrace();
}

0 comments on commit 07e2f5c

Please sign in to comment.