167 lines
5.1 KiB
C++
167 lines
5.1 KiB
C++
/*//////////////////////////////////////////////////////////////////////////////
|
|
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
|
|
All rights reserved
|
|
|
|
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
|
|
|
|
------------------------------------------------------------------
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 3.0 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library.
|
|
|
|
//////////////////////////////////////////////////////////////////////////////*/
|
|
|
|
#include "vtkGeantSolid.h"
|
|
|
|
#include <vtkActor.h>
|
|
#include <vtkPolyData.h>
|
|
#include <vtkPoints.h>
|
|
#include <vtkCellArray.h>
|
|
#include <vtkPolyDataMapper.h>
|
|
#include <vtkProperty.h>
|
|
#include <vtkSmartPointer.h>
|
|
#include <vtkTransform.h>
|
|
#include <vtkMatrix4x4.h>
|
|
|
|
#include <Geant4/G4VSolid.hh>
|
|
#include <Geant4/G4Polyhedron.hh>
|
|
#include <Geant4/G4VPhysicalVolume.hh>
|
|
|
|
namespace uLib {
|
|
namespace Vtk {
|
|
|
|
GeantSolid::GeantSolid(Content *content)
|
|
: m_SolidActor(vtkActor::New()), m_Content(content) {
|
|
this->InstallPipe();
|
|
}
|
|
|
|
GeantSolid::~GeantSolid() {
|
|
m_SolidActor->Delete();
|
|
}
|
|
|
|
vtkPolyData *GeantSolid::GetPolyData() const {
|
|
if (!m_SolidActor || !m_SolidActor->GetMapper())
|
|
return NULL;
|
|
return vtkPolyData::SafeDownCast(m_SolidActor->GetMapper()->GetInput());
|
|
}
|
|
|
|
void GeantSolid::Update() {
|
|
this->UpdateGeometry();
|
|
this->UpdateTransform();
|
|
}
|
|
|
|
void GeantSolid::UpdateGeometry() {
|
|
if (!m_Content)
|
|
return;
|
|
|
|
G4VSolid *g4solid = m_Content->GetG4Solid();
|
|
if (!g4solid)
|
|
return;
|
|
|
|
// Get the polyhedron tessellation from Geant4
|
|
G4Polyhedron *polyhedron = g4solid->GetPolyhedron();
|
|
if (!polyhedron)
|
|
return;
|
|
|
|
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
|
|
vtkSmartPointer<vtkCellArray> polys = vtkSmartPointer<vtkCellArray>::New();
|
|
|
|
// Extract vertices
|
|
int nVertices = polyhedron->GetNoVertices();
|
|
for (int i = 1; i <= nVertices; ++i) {
|
|
G4Point3D vtx = polyhedron->GetVertex(i);
|
|
|
|
points->InsertNextPoint(vtx.x(), vtx.y(), vtx.z());
|
|
}
|
|
|
|
// Extract facets (polygons)
|
|
int nFacets = polyhedron->GetNoFacets();
|
|
for (int f = 1; f <= nFacets; ++f) {
|
|
G4int nEdges;
|
|
G4int iVertex[4]; // G4Polyhedron facets have at most 4 vertices
|
|
// GetNextFacet returns edges; for quads nEdges=4, for triangles nEdges=3
|
|
polyhedron->GetFacet(f, nEdges, iVertex);
|
|
|
|
vtkIdType ids[4];
|
|
for (int e = 0; e < nEdges; ++e) {
|
|
// G4Polyhedron vertices are 1-indexed; VTK expects 0-indexed
|
|
ids[e] = static_cast<vtkIdType>(std::abs(iVertex[e]) - 1);
|
|
}
|
|
polys->InsertNextCell(nEdges, ids);
|
|
}
|
|
|
|
vtkPolyData *polyData = GetPolyData();
|
|
if (polyData) {
|
|
polyData->SetPoints(points);
|
|
polyData->SetPolys(polys);
|
|
polyData->Modified();
|
|
}
|
|
}
|
|
|
|
void GeantSolid::UpdateTransform() {
|
|
if (!m_Content || !m_SolidActor)
|
|
return;
|
|
|
|
// Apply the Geant4 transform (position/rotation) if placed
|
|
if (m_Content->GetPhysical()) {
|
|
auto *phys = m_Content->GetPhysical();
|
|
G4ThreeVector pos = phys->GetTranslation();
|
|
const G4RotationMatrix *rot = phys->GetRotation();
|
|
|
|
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
|
|
transform->Identity();
|
|
transform->Translate(pos.x(), pos.y(), pos.z());
|
|
|
|
if (rot) {
|
|
// G4RotationMatrix stores the inverse of the rotation for placement
|
|
G4RotationMatrix invRot = rot->inverse();
|
|
double elements[16] = {
|
|
invRot.xx(), invRot.xy(), invRot.xz(), 0,
|
|
invRot.yx(), invRot.yy(), invRot.yz(), 0,
|
|
invRot.zx(), invRot.zy(), invRot.zz(), 0,
|
|
0, 0, 0, 1
|
|
};
|
|
vtkSmartPointer<vtkMatrix4x4> mat = vtkSmartPointer<vtkMatrix4x4>::New();
|
|
mat->DeepCopy(elements);
|
|
transform->Concatenate(mat);
|
|
}
|
|
|
|
m_SolidActor->SetUserTransform(transform);
|
|
}
|
|
}
|
|
|
|
void GeantSolid::InstallPipe() {
|
|
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper =
|
|
vtkSmartPointer<vtkPolyDataMapper>::New();
|
|
mapper->SetInputData(polyData);
|
|
|
|
m_SolidActor->SetMapper(mapper);
|
|
|
|
// Default look: semi-transparent blue surface
|
|
m_SolidActor->GetProperty()->SetColor(0.4, 0.6, 0.9);
|
|
m_SolidActor->GetProperty()->SetOpacity(0.3);
|
|
m_SolidActor->GetProperty()->SetAmbient(0.5);
|
|
m_SolidActor->GetProperty()->SetDiffuse(0.6);
|
|
m_SolidActor->GetProperty()->SetSpecular(0.2);
|
|
m_SolidActor->GetProperty()->SetEdgeVisibility(1);
|
|
m_SolidActor->GetProperty()->SetEdgeColor(0.2, 0.3, 0.5);
|
|
|
|
this->SetProp(m_SolidActor);
|
|
}
|
|
|
|
} // namespace Vtk
|
|
} // namespace uLib
|