Import Geant4 11.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2021-12-10 14:46:44 +01:00
committed by Ben Morgan
parent 6399a014b6
commit 80e2389dd8
3932 changed files with 202519 additions and 246221 deletions
+68
View File
@@ -0,0 +1,68 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
//
// John Allison 5th April 2001
// A template for a simplest possible graphics driver.
//?? Lines or sections marked like this require specialisation for your driver.
#include "G4Vtk.hh"
#include "G4VtkSceneHandler.hh"
#include "G4VtkViewer.hh"
#include "G4VtkMessenger.hh"
G4Vtk::G4Vtk(): G4VGraphicsSystem("VtkNative","VTKN","Vtk with native windowing",
G4VGraphicsSystem::noFunctionality)
{
G4VtkMessenger::GetInstance();
}
G4Vtk::~G4Vtk() {}
G4VSceneHandler* G4Vtk::CreateSceneHandler(const G4String& name) {
G4VSceneHandler* pScene = new G4VtkSceneHandler(*this, name);
return pScene;
}
G4VViewer* G4Vtk::CreateViewer(G4VSceneHandler& scene,
const G4String& name) {
G4VViewer* pView = new G4VtkViewer((G4VtkSceneHandler&) scene, name);
if (pView) {
if (pView->GetViewId() < 0) {
G4cerr << "G4Vtk::CreateViewer: ERROR flagged by negative"
" view id in G4VtkViewer creation."
"\n Destroying view and returning null pointer."
<< G4endl;
delete pView;
pView = 0;
}
}
else {
G4cerr << "G4Vtk::CreateViewer: ERROR: null pointer on new G4VtkViewer." << G4endl;
}
return pView;
}
@@ -0,0 +1,131 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
#include "G4VtkMessenger.hh"
#include "G4VtkViewer.hh"
#include "G4UIdirectory.hh"
#include "G4UIcmdWithABool.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UIcommand.hh"
#include "G4Tokenizer.hh"
#include "G4VisManager.hh"
#include "vtkObject.h"
G4VtkMessenger* G4VtkMessenger::fpInstance = nullptr;
G4VtkMessenger* G4VtkMessenger::GetInstance()
{
if (!fpInstance) fpInstance = new G4VtkMessenger;
return fpInstance;
}
G4VtkMessenger::G4VtkMessenger() {
G4bool omitable;
fpDirectory = new G4UIdirectory("/vis/vtk/");
fpDirectory->SetGuidance("G4VtkViewer commands.");
// Export command
fpCommandExport = new G4UIcommand("/vis/vtk/export", this);
fpCommandExport->SetGuidance ("Export a screenshot or OBJ file of current Vtk viewer");
// File type for export
auto parameterExport = new G4UIparameter ("name", 's', omitable = true);
fpCommandExport->SetGuidance ("File type (jpg,tiff,eps,ps,obj,vrml)");
fpCommandExport->SetParameter(parameterExport);
// File name for export
parameterExport = new G4UIparameter ("name", 's', omitable = true);
fpCommandExport->SetGuidance ("File name");
fpCommandExport->SetParameter(parameterExport);
// Vtk warnings output
fpCommandWarnings = new G4UIcmdWithABool("/vis/vtk/warnings", this);
fpCommandExport->SetGuidance ("Enable (True) or disable (False) VTK warnings");
}
G4VtkMessenger::~G4VtkMessenger()
{
delete fpDirectory;
delete fpCommandExport;
delete fpCommandWarnings;
}
G4String G4VtkMessenger::GetCurrentValue(G4UIcommand * /*command*/) {
return G4String();
}
void G4VtkMessenger::SetNewValue(G4UIcommand *command, G4String newValue)
{
G4VisManager* pVisManager = G4VisManager::GetInstance();
G4VViewer* pViewer = pVisManager->GetCurrentViewer();
if (!pViewer) {
G4cout << "G4VtkMessenger::SetNewValue: No current viewer.\n"
<< "\"/vis/open\", or similar, to get one."
<< G4endl;
return;
}
auto* pVtkViewer = dynamic_cast<G4VtkViewer*>(pViewer);
if (!pVtkViewer) {
G4cout << "G4OpenGLViewerMessenger::SetNewValue: Current viewer is not of type VTK. \n"
<< "(It is \""
<< pViewer->GetName()
<< "\".)\n"
<< "Use \"/vis/viewer/select\" or \"/vis/open\"."
<< G4endl;
return;
}
if (command == fpCommandExport)
{
G4String format, name;
std::istringstream iss(newValue);
iss >> format >> name;
if(format == "jpg" || format == "tiff" ||
format == "png" || format == "bmp" ||
format == "pnm" || format == "ps")
pVtkViewer->ExportScreenShot(name, format);
else if(format == "obj")
pVtkViewer->ExportOBJScene(name);
else if(format == "vrml")
pVtkViewer->ExportVRMLScene(name);
else if(format == "vtp")
pVtkViewer->ExportVTPScene(name);
else
G4cout << "Unknown /vis/vtk/export file format" << G4endl;
}
else if (command == fpCommandWarnings)
{
vtkObject::GlobalWarningDisplayOff();
}
}
+90
View File
@@ -0,0 +1,90 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
#include "G4VtkQt.hh"
#include "G4VtkQtSceneHandler.hh"
#include "G4VtkQtViewer.hh"
#include "G4UIQt.hh"
#include "G4UImanager.hh"
#include "G4UIbatch.hh"
G4VtkQt::G4VtkQt(): G4VGraphicsSystem("VtkQt","VTKQt","VTK with Qt",
G4VGraphicsSystem::noFunctionality)
{}
G4VtkQt::~G4VtkQt() {}
G4VSceneHandler* G4VtkQt::CreateSceneHandler(const G4String& name) {
G4VSceneHandler* pScene = new G4VtkQtSceneHandler(*this, name);
return pScene;
}
G4VViewer* G4VtkQt::CreateViewer(G4VSceneHandler& scene,
const G4String& name) {
G4VViewer* pView = new G4VtkQtViewer((G4VtkQtSceneHandler&) scene, name);
if (pView) {
if (pView->GetViewId() < 0) {
G4cerr << "G4VtkQt::CreateViewer: ERROR flagged by negative"
" view id in G4VtkViewer creation."
"\n Destroying view and returning null pointer."
<< G4endl;
delete pView;
pView = nullptr;
}
}
else {
G4cerr << "G4Vtk::CreateViewer: ERROR: null pointer on new G4VtkViewer." << G4endl;
}
return pView;
}
G4bool G4VtkQt::IsUISessionCompatible () const
{
G4bool isCompatible = false;
G4UImanager* ui = G4UImanager::GetUIpointer();
G4UIsession* session = ui->GetSession();
// If session is a batch session, it may be:
// a) this is a batch job (the user has not instantiated any UI session);
// b) we are currently processing a UI command, in which case the UI
// manager creates a temporary batch session and to find out if there is
// a genuine UI session that the user has instantiated we must drill
// down through previous sessions to a possible non-batch session.
while (G4UIbatch* batch = dynamic_cast<G4UIbatch*>(session)) {
session = batch->GetPreviousSession();
}
// Qt windows are only appropriate in a Qt session.
if (session) {
// If non-zero, this is the originating non-batch session
// The user has instantiated a UI session...
if (dynamic_cast<G4UIQt*>(session)) {
// ...and it's a G4UIQt session, which is OK.
isCompatible = true;
}
}
return isCompatible;
}
@@ -0,0 +1,53 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
#include "G4VtkQtSceneHandler.hh"
#include "G4PhysicalVolumeModel.hh"
#include "G4LogicalVolumeModel.hh"
#include "G4VPhysicalVolume.hh"
#include "G4LogicalVolume.hh"
#include "G4Polyline.hh"
#include "G4Text.hh"
#include "G4Circle.hh"
#include "G4Square.hh"
#include "G4Polyhedron.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"
#include "G4Material.hh"
#include "G4Box.hh"
G4int G4VtkQtSceneHandler::fSceneIdCount = 0;
// Counter for XXX scene handlers.
G4VtkQtSceneHandler::G4VtkQtSceneHandler(G4VGraphicsSystem& system,
const G4String& name) :
G4VtkSceneHandler(system, name)
{}
G4VtkQtSceneHandler::~G4VtkQtSceneHandler() {}
@@ -0,0 +1,88 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
#include "G4VSceneHandler.hh"
#include "G4VtkQtViewer.hh"
#include "G4VtkQtSceneHandler.hh"
#include "G4UImanager.hh"
#include "G4UIQt.hh"
#include "G4Qt.hh"
#include <array>
#include "vtkVersion.h"
#include "vtkNew.h"
#include "vtkNamedColors.h"
#include "vtkCylinderSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkCamera.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkGenericOpenGLRenderWindow.h"
G4VtkQtViewer::G4VtkQtViewer (G4VSceneHandler& sceneHandler, const G4String& name) :
G4VtkViewer(sceneHandler, name) {
}
G4VtkQtViewer::~G4VtkQtViewer() {}
void G4VtkQtViewer::Initialise()
{
CreateMainWindow(this, QString(GetName()));
// Specific GL render window and interactor for Qt
_renderWindow = vtkGenericOpenGLRenderWindow::New();
renderWindowInteractor = vtkRenderWindowInteractor::New();
_renderWindow->AddRenderer(renderer);
#if VTK_MAJOR_VERSION == 8
this->SetRenderWindow(_renderWindow);
#else
this->setRenderWindow(_renderWindow);
#endif
// Set callback to match VTK parameters to Geant4
geant4Callback->SetGeant4ViewParameters(&fVP);
renderer->AddObserver(vtkCommand::EndEvent, geant4Callback);
}
void G4VtkQtViewer::CreateMainWindow(QVTKOpenGLNativeWidget *vtkWidget,
const QString& name) {
// G4Qt* interactorManager = G4Qt::getInstance ();
G4UImanager* UI = G4UImanager::GetUIpointer();
fUiQt = static_cast<G4UIQt*> (UI->GetG4UIWindow());
fUiQt->AddTabWidget((QWidget*)vtkWidget,name);
}
void G4VtkQtViewer::FinishView()
{
G4VtkViewer::FinishView();
// force a widget repaint as there should already
// be a rendered buffer when visualiser starts up
// paintGL();
// repaint();
}
@@ -0,0 +1,876 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
//
// John Allison 5th April 2001
// A template for a simplest possible graphics driver.
//?? Lines or sections marked like this require specialisation for your driver.
#include "G4VtkSceneHandler.hh"
#include "G4PhysicalVolumeModel.hh"
#include "G4LogicalVolumeModel.hh"
#include "G4VPhysicalVolume.hh"
#include "G4LogicalVolume.hh"
#include "G4Polyline.hh"
#include "G4Text.hh"
#include "G4Circle.hh"
#include "G4Square.hh"
#include "G4Polyhedron.hh"
#include "G4Mesh.hh"
#include "G4PseudoScene.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"
#include "G4Material.hh"
#include "G4Box.hh"
#include <stdlib.h>
namespace std
{
inline void hash_combine(std::size_t) {}
template <typename T, typename... Rest>
inline void hash_combine(std::size_t &seed, const T &v, Rest... rest) {
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
std::hash_combine(seed, rest...);
}
template<> struct hash<G4VisAttributes> {
std::size_t operator()(const G4VisAttributes &va) const {
using std::size_t;
using std::hash;
std::size_t h = 0;
std::hash_combine(h,va.IsVisible());
std::hash_combine(h,va.IsDaughtersInvisible());
std::hash_combine(h,va.GetColour().GetRed());
std::hash_combine(h,va.GetColour().GetGreen());
std::hash_combine(h,va.GetColour().GetBlue());
std::hash_combine(h,va.GetColour().GetAlpha());
std::hash_combine(h,static_cast<int>(va.GetLineStyle()));
return h;
}
};
template<> struct hash<G4Polyhedron> {
std::size_t operator()(const G4Polyhedron &ph) const {
using std::size_t;
using std::hash;
G4bool notLastFace;
G4Point3D vertex[4];
G4int edgeFlag[4];
G4Normal3D normals[4];
G4int nEdges;
std::size_t h = 0;
do {
notLastFace = ph.GetNextFacet(nEdges, vertex, edgeFlag, normals);
for (int i = 0; i < nEdges; i++) {
std::size_t hx = std::hash<double>()(vertex[i].x());
std::size_t hy = std::hash<double>()(vertex[i].y());
std::size_t hz = std::hash<double>()(vertex[i].z());
std::hash_combine(h,hx);
std::hash_combine(h,hy);
std::hash_combine(h,hz);
}
} while (notLastFace);
return h;
}
};
}
G4int G4VtkSceneHandler::fSceneIdCount = 0;
// Counter for XXX scene handlers.
G4VtkSceneHandler::G4VtkSceneHandler(G4VGraphicsSystem& system,
const G4String& name) :
G4VSceneHandler(system, fSceneIdCount++, name)
{}
#ifdef G4VTKDEBUG
void G4VtkSceneHandler::PrintThings() {
G4cout << " with transformation " << fObjectTransformation.xx() << G4endl;
if (fpModel) {
G4cout << " from " << fpModel->GetCurrentDescription()
<< " (tag " << fpModel->GetCurrentTag()
<< ')';
}
else {
G4cout << "(not from a model)";
}
G4PhysicalVolumeModel* pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (pPVModel) {
G4cout << "\n current physical volume: " << pPVModel->GetCurrentPV()->GetName()
<< "\n current logical volume : " << pPVModel->GetCurrentLV()->GetName() // There might be a problem with the LV pointer if this is a G4LogicalVolumeModel
<< "\n current depth of geometry tree: " << pPVModel->GetCurrentDepth();
}
G4cout << G4endl;
}
#endif
void G4VtkSceneHandler::AddPrimitive(const G4Polyline& polyline) {
G4VSceneHandler::MarkerSizeType sizeType;
// GetMarkerSize(text,sizeType);
if(fProcessing2D) {sizeType = screen;}
else {sizeType = world;}
// Get vis attributes - pick up defaults if none.
const G4VisAttributes* pVA = fpViewer -> GetApplicableVisAttributes(polyline.GetVisAttributes());
G4Color colour = pVA->GetColour();
G4double opacity = colour.GetAlpha();
G4double lineWidth = pVA->GetLineWidth();
#ifdef G4VTKDEBUG
G4cout << "=================================" << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyline& polyline) called> vis hash: " << sizeType << " " << std::hash<G4VisAttributes>{}(*pVA) << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyline& polyline) called> sizeType: " << sizeType << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyline& polyline) called> isVisible: " << pVA->IsVisible() << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyline& polyline) called> isDaughtersInvisible: " << pVA->IsDaughtersInvisible() << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyline& polyline) called> colour: " << colour.GetRed() << " " << colour.GetGreen() << " " << colour.GetBlue() << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyline& polyline) called> alpha: " << colour.GetAlpha() << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyline& polyline) called> lineWidth: " << lineWidth << G4endl;
#endif
if(sizeType == world) {
std::size_t hash = std::hash<G4VisAttributes>{}(*pVA);
if (polylineVisAttributesMap.find(hash) == polylineVisAttributesMap.end()) {
polylineVisAttributesMap.insert(std::pair<std::size_t, const G4VisAttributes *>(hash, pVA));
vtkSmartPointer <vtkPoints> data = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer <vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer <vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer <vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer <vtkActor> actor = vtkSmartPointer<vtkActor>::New();
polyData->SetPoints(data);
polyData->SetLines(lines);
mapper->SetInputData(polyData);
actor->SetMapper(mapper);
// Setup actor and mapper
actor->GetProperty()->SetLineWidth(lineWidth);
actor->GetProperty()->SetColor(colour.GetRed(), colour.GetGreen(),
colour.GetBlue());
actor->GetProperty()->SetOpacity(opacity);
actor->SetVisibility(1);
// actor->GetProperty()->BackfaceCullingOn();
// actor->GetProperty()->FrontfaceCullingOn();
auto pVtkViewer = dynamic_cast<G4VtkViewer*>(fpViewer);
pVtkViewer->renderer->AddActor(actor);
polylineDataMap.insert(
std::pair<std::size_t, vtkSmartPointer<vtkPoints>>(hash, data));
polylineLineMap.insert(
std::pair<std::size_t, vtkSmartPointer<vtkCellArray>>(hash, lines));
polylinePolyDataMap.insert(
std::pair<std::size_t, vtkSmartPointer<vtkPolyData>>(hash, polyData));
polylinePolyDataMapperMap.insert(
std::pair<std::size_t, vtkSmartPointer<vtkPolyDataMapper>>(hash,
mapper));
polylinePolyDataActorMap.insert(
std::pair<std::size_t, vtkSmartPointer<vtkActor>>(hash, actor));
}
// Data data
const size_t nLines = polyline.size();
for (size_t i = 0; i < nLines; ++i) {
auto id = polylineDataMap[hash]->InsertNextPoint(polyline[i].x(),
polyline[i].y(),
polyline[i].z());
if (i < nLines - 1) {
vtkSmartPointer <vtkLine> line = vtkSmartPointer<vtkLine>::New();
line->GetPointIds()->SetId(0, id);
line->GetPointIds()->SetId(1, id + 1);
polylineLineMap[hash]->InsertNextCell(line);
}
}
}
else if (sizeType == screen ) {
}
}
void G4VtkSceneHandler::AddPrimitive(const G4Text& text) {
G4VSceneHandler::MarkerSizeType sizeType;
if(fProcessing2D) {sizeType = screen;}
else {sizeType = world;}
const G4VisAttributes* pVA = fpViewer -> GetApplicableVisAttributes(text.GetVisAttributes());
G4Color colour = pVA->GetColour();
G4double opacity = colour.GetAlpha();
// G4Text::Layout layout = text.GetLayout();
// G4double xOffset = text.GetXOffset();
// G4double yOffset = text.GetYOffset();
double x = text.GetPosition().x();
double y = text.GetPosition().y();
double z = text.GetPosition().z();
#ifdef G4VTKDEBUG
G4cout << "=================================" << G4endl;
G4cout << "G4VtkSeneHandler::AddPrimitive(const G4Text& text) called> text: " << text.GetText() << " sizeType:" << sizeType << " " << fProcessing2D << G4endl;
G4cout << "G4VtkSeneHandler::AddPrimitive(const G4Text& text) called> colour: " << colour.GetRed() << " " << colour.GetBlue() << " " << colour.GetGreen() << G4endl;
G4cout << "G4VtkSeneHandler::AddPrimitive(const G4Text& text) called> alpha: " << colour.GetAlpha() << G4endl;
G4cout << "G4VtkSeneHandler::AddPrimitive(const G4Text& text) called> position: " << x << " " << y << " " << z << G4endl;
#endif
switch (sizeType) {
default:
case (screen): {
vtkSmartPointer <vtkTextActor> actor = vtkSmartPointer<vtkTextActor>::New();
actor->SetInput(text.GetText().c_str());
actor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
// actor->SetTextScaleModeToViewport();
actor->SetPosition((x+1.)/2.0, (y+1.)/2.);
actor->GetTextProperty()->SetFontSize(text.GetScreenSize());
actor->GetTextProperty()->SetColor(colour.GetRed(), colour.GetBlue(), colour.GetGreen());
actor->GetTextProperty()->SetOpacity(opacity);
auto *pVtkViewer = dynamic_cast<G4VtkViewer *>(fpViewer);
pVtkViewer->renderer->AddActor(actor);
break;
}
case world: {
vtkSmartPointer <vtkBillboardTextActor3D> actor = vtkSmartPointer<vtkBillboardTextActor3D>::New();
actor->SetInput(text.GetText().c_str());
actor->SetPosition(x, y, z);
actor->GetTextProperty()->SetFontSize(text.GetScreenSize());
actor->GetTextProperty()->SetColor(colour.GetRed(), colour.GetBlue(), colour.GetGreen());
actor->GetTextProperty()->SetOpacity(opacity);
auto *pVtkViewer = dynamic_cast<G4VtkViewer*>(fpViewer);
pVtkViewer->renderer->AddActor(actor);
break;
}
}
}
void G4VtkSceneHandler::AddPrimitive(const G4Circle& circle) {
MarkerSizeType sizeType;
G4double size= GetMarkerSize(circle, sizeType);
if(fProcessing2D) {sizeType = screen;}
else {sizeType = world;}
// Get vis attributes - pick up defaults if none.
const G4VisAttributes *pVA = fpViewer->GetApplicableVisAttributes(circle.GetVisAttributes());
G4Color colour = pVA->GetColour();
G4double opacity = colour.GetAlpha();
// G4bool isVisible = pVA->IsVisible();
#ifdef G4VTKDEBUG
G4cout << "=================================" << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Circle& circle) called> " << " radius:" << size << " sizeType:" << sizeType << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Circle& circle) called> colour: " << colour.GetRed() << " " << colour.GetBlue() << " " << colour.GetGreen() << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Circle& circle) called> alpha: " << colour.GetAlpha() << G4endl;
#endif
if (sizeType == world) {
std::size_t hash = std::hash<G4VisAttributes>{}(*pVA);
if (circleVisAttributesMap.find(hash) == circleVisAttributesMap.end()) {
circleVisAttributesMap.insert(std::pair<std::size_t, const G4VisAttributes *>(hash, pVA));
vtkSmartPointer<vtkPoints> data = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkVertexGlyphFilter> filter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
polyData->SetPoints(data);
filter->SetInputData(polyData);
mapper->SetInputConnection(filter->GetOutputPort());
actor->SetMapper(mapper);
// Setup actor and mapper
actor->GetProperty()->SetColor(colour.GetRed(), colour.GetGreen(), colour.GetBlue());
actor->GetProperty()->SetOpacity(opacity);
actor->SetVisibility(1);
actor->GetProperty()->SetRenderPointsAsSpheres(true);
actor->GetProperty()->SetPointSize(size*5);
auto *pVtkViewer = dynamic_cast<G4VtkViewer *>(fpViewer);
pVtkViewer->renderer->AddActor(actor);
circleDataMap.insert(std::pair<std::size_t,vtkSmartPointer<vtkPoints>>(hash, data));
circlePolyDataMap.insert(std::pair<std::size_t, vtkSmartPointer < vtkPolyData>>(hash, polyData));
circleFilterMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkVertexGlyphFilter>>(hash, filter));
circlePolyDataMapperMap.insert(std::pair<std::size_t, vtkSmartPointer < vtkPolyDataMapper>>(hash, mapper));
circlePolyDataActorMap.insert(std::pair<std::size_t, vtkSmartPointer < vtkActor>>(hash, actor));
}
// Data data point
const CLHEP::HepRotation rot = fObjectTransformation.getRotation();
G4Point3D posPrime = rot*circle.GetPosition();
circleDataMap[hash]->InsertNextPoint(fObjectTransformation.dx() + posPrime.x(),
fObjectTransformation.dy() + posPrime.y(),
fObjectTransformation.dz() + posPrime.z());
}
else if (sizeType == screen) {
}
}
void G4VtkSceneHandler::AddPrimitive(const G4Square& square) {
MarkerSizeType sizeType;
G4double size = GetMarkerSize (square, sizeType);
// Get vis attributes - pick up defaults if none.
const G4VisAttributes* pVA = fpViewer -> GetApplicableVisAttributes(square.GetVisAttributes());
G4Color colour = pVA->GetColour();
G4double opacity = colour.GetAlpha();
// G4bool isVisible = pVA->IsVisible();
// Draw in world coordinates.
vtkSmartPointer<vtkRegularPolygonSource> polygonSource = vtkSmartPointer<vtkRegularPolygonSource>::New();
polygonSource->SetNumberOfSides(4);
polygonSource->SetRadius(size);
#ifdef G4VTKDEBUG
G4cout << "=================================" << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Square& square) called" << G4endl;
G4cout << square.GetPosition().x() << " " << square.GetPosition().y() << " " << square.GetPosition().z() << G4endl;
//PrintThings();
#endif
if (sizeType == world) {
std::size_t hash = std::hash<G4VisAttributes>{}(*pVA);
if (squareVisAttributesMap.find(hash) == squareVisAttributesMap.end()) {
squareVisAttributesMap.insert(std::pair<std::size_t, const G4VisAttributes *>(hash, pVA));
vtkSmartPointer<vtkPoints> data = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkVertexGlyphFilter> filter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
polyData->SetPoints(data);
filter->SetInputData(polyData);
mapper->SetInputConnection(filter->GetOutputPort());
actor->SetMapper(mapper);
// Setup actor and mapper
actor->GetProperty()->SetColor(colour.GetRed(), colour.GetGreen(), colour.GetBlue());
actor->GetProperty()->SetOpacity(opacity);
actor->SetVisibility(1);
actor->GetProperty()->SetPointSize(size*5);
auto *pVtkViewer = dynamic_cast<G4VtkViewer *>(fpViewer);
pVtkViewer->renderer->AddActor(actor);
squareDataMap.insert(std::pair<std::size_t,vtkSmartPointer<vtkPoints>>(hash, data));
squarePolyDataMap.insert(std::pair<std::size_t, vtkSmartPointer < vtkPolyData>>(hash, polyData));
squareFilterMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkVertexGlyphFilter>>(hash, filter));
squarePolyDataMapperMap.insert(std::pair<std::size_t, vtkSmartPointer < vtkPolyDataMapper>>(hash, mapper));
squarePolyDataActorMap.insert(std::pair<std::size_t, vtkSmartPointer < vtkActor>>(hash, actor));
}
// Data data point
const CLHEP::HepRotation rot = fObjectTransformation.getRotation();
G4Point3D posPrime = rot*square.GetPosition();
squareDataMap[hash]->InsertNextPoint(fObjectTransformation.dx() + posPrime.x(),
fObjectTransformation.dy() + posPrime.y(),
fObjectTransformation.dz() + posPrime.z());
}
else if (sizeType == screen) {
}
}
void G4VtkSceneHandler::AddPrimitive(const G4Polyhedron& polyhedron) {
AddPrimitiveTensorGlyph(polyhedron);
}
void G4VtkSceneHandler::AddPrimitiveTensorGlyph(const G4Polyhedron& polyhedron) {
// only have a single polydata object for each LV but bake in the PV
// transformation so clippers and cutters can be implemented
//Get colour, etc..
if (polyhedron.GetNoFacets() == 0) {return;}
// Get vis attributes - pick up defaults if none.
const G4VisAttributes *pVA = fpViewer->GetApplicableVisAttributes(polyhedron.GetVisAttributes());
G4Color colour = pVA->GetColour();
// G4bool isVisible = pVA->IsVisible();
// G4double lineWidth = pVA->GetLineWidth();
// G4VisAttributes::LineStyle lineStyle = pVA->GetLineStyle();
// G4double lineWidthScale = drawing_style.GetGlobalLineWidthScale();
// Get view parameters that the user can force through the vis attributes, thereby over-riding the current view parameter.
G4ViewParameters::DrawingStyle drawing_style = GetDrawingStyle(pVA);
//G4bool isAuxEdgeVisible = GetAuxEdgeVisible (pVA);
#ifdef G4VTKDEBUG
G4cout << "=================================" << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyhedron& polyhedron) called> " << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyhedron& polyhedron) called> colour:" << colour.GetRed() << " " << colour.GetBlue() << " " << colour.GetGreen() << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyhedron& polyhedron) called> alpha:" << colour.GetAlpha() << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyhedron& polyhedron) called> lineWidth:" << lineWidth << G4endl;
G4cout << "G4VtkSceneHandler::AddPrimitive(const G4Polyhedron& polyhedron) called> lineStyle:" << lineStyle << G4endl;
#endif
//std::size_t vhash = std::hash<G4VisAttributes>{}(*pVA);
std::size_t vhash = 0;
std::hash_combine(vhash,static_cast<int>(drawing_style));
std::size_t phash = std::hash<G4Polyhedron>{}(polyhedron);
std::size_t hash = 0;
std::hash_combine(hash, phash);
std::hash_combine(hash, vhash);
if (polyhedronPolyDataMap.find(hash) == polyhedronPolyDataMap.end()) {
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> polys = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
G4bool notLastFace;
int iVert = 0;
do {
G4Point3D vertex[4];
G4int edgeFlag[4];
G4Normal3D normals[4];
G4int nEdges;
notLastFace = polyhedron.GetNextFacet(nEdges, vertex, edgeFlag, normals);
vtkSmartPointer<vtkIdList> poly = vtkSmartPointer<vtkIdList>::New();
// loop over vertices
for (int i = 0; i < nEdges; i++) {
points->InsertNextPoint(vertex[i].x(), vertex[i].y(), vertex[i].z());
poly->InsertNextId(iVert);
iVert++;
}
polys->InsertNextCell(poly);
} while (notLastFace);
polydata->SetPoints(points);
polydata->SetPolys(polys);
polyhedronDataMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkPoints>>(hash, points));
polyhedronPolyMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkCellArray>>(hash, polys));
polyhedronPolyDataMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkPolyData>>(hash, polydata));
polyhedronPolyDataCountMap.insert(std::pair<std::size_t, std::size_t>(hash, 0));
vtkSmartPointer<vtkPoints> instancePosition = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkDoubleArray> instanceRotation = vtkSmartPointer<vtkDoubleArray>::New();
vtkSmartPointer<vtkDoubleArray> instanceColors = vtkSmartPointer<vtkDoubleArray>::New();
vtkSmartPointer<vtkPolyDataMapper> instanceMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> instanceActor = vtkSmartPointer<vtkActor>::New();
instanceColors->SetName("colors");
instanceColors->SetNumberOfComponents(4);
instanceRotation->SetNumberOfComponents(9);
vtkSmartPointer<vtkPolyData> instancePolyData = vtkSmartPointer<vtkPolyData>::New();
instancePolyData->SetPoints(instancePosition);
instancePolyData->GetPointData()->SetTensors(instanceRotation);
instancePolyData->GetPointData()->SetVectors(instanceColors);
instancePolyData->GetPointData()->SetScalars(instanceColors);
vtkSmartPointer<vtkCleanPolyData> filterClean = vtkSmartPointer<vtkCleanPolyData>::New();
filterClean->PointMergingOn();
filterClean->AddInputData(polydata);
vtkSmartPointer<vtkTriangleFilter> filterTriangle = vtkSmartPointer<vtkTriangleFilter>::New();
filterTriangle->SetInputConnection(filterClean->GetOutputPort());
vtkSmartPointer<vtkPolyDataNormals> filterNormals = vtkSmartPointer<vtkPolyDataNormals>::New();
filterNormals->SetFeatureAngle(45);
filterNormals->SetInputConnection(filterTriangle->GetOutputPort());
vtkSmartPointer<vtkFeatureEdges> filterEdge = vtkSmartPointer<vtkFeatureEdges>::New();
filterEdge->SetFeatureEdges(1);
filterEdge->SetManifoldEdges(0);
filterEdge->SetBoundaryEdges(0);
filterEdge->SetFeatureAngle(45); // TODO need to have a function and command to set this
filterEdge->SetInputConnection(filterTriangle->GetOutputPort());
vtkSmartPointer<vtkTensorGlyphColor> tensorGlyph = vtkSmartPointer<vtkTensorGlyphColor>::New();
tensorGlyph->SetInputData(instancePolyData);
tensorGlyph->SetSourceConnection(filterNormals->GetOutputPort());
tensorGlyph->ColorGlyphsOn();
tensorGlyph->ScalingOff();
tensorGlyph->ThreeGlyphsOff();
tensorGlyph->ExtractEigenvaluesOff();
tensorGlyph->SetColorModeToScalars();
tensorGlyph->Update();
instanceMapper->SetInputData(tensorGlyph->GetOutput());
instanceMapper->SetColorModeToDirectScalars();
instanceActor->SetMapper(instanceMapper);
// instanceActor->GetProperty()->SetLineWidth(10);
instanceActor->SetVisibility(1);
if(drawing_style == G4ViewParameters::hsr) {
}
if(drawing_style == G4ViewParameters::hlr) {
}
if(drawing_style == G4ViewParameters::wireframe) {
instanceActor->GetProperty()->SetRepresentationToWireframe();
}
auto *pVtkViewer = dynamic_cast<G4VtkViewer *>(fpViewer);
pVtkViewer->renderer->AddActor(instanceActor);
instancePositionMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkPoints>>(hash, instancePosition));
instanceRotationMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkDoubleArray>>(hash, instanceRotation));
instanceColoursMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkDoubleArray>>(hash, instanceColors));
instancePolyDataMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkPolyData>>(hash,instancePolyData));
instanceActorMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkActor>>(hash, instanceActor));
instanceTensorGlyphMap.insert(std::pair<std::size_t, vtkSmartPointer<vtkTensorGlyphColor>>(hash, tensorGlyph));
}
polyhedronPolyDataCountMap[hash]++;
double red = colour.GetRed();
double green = colour.GetGreen();
double blue = colour.GetBlue();
double alpha = colour.GetAlpha();
instanceColoursMap[hash]->InsertNextTuple4(red, green, blue, alpha);
instancePositionMap[hash]->InsertNextPoint(fObjectTransformation.dx(),
fObjectTransformation.dy(),
fObjectTransformation.dz());
G4Transform3D fInvObjTrans = fObjectTransformation.inverse();
instanceRotationMap[hash]->InsertNextTuple9(fInvObjTrans.xx(), fInvObjTrans.xy(),fInvObjTrans.xz(),
fInvObjTrans.yx(), fInvObjTrans.yy(),fInvObjTrans.yz(),
fInvObjTrans.zx(), fInvObjTrans.zy(),fInvObjTrans.zz());
}
void G4VtkSceneHandler::AddPrimitiveBakedTransform(const G4Polyhedron& polyhedron)
{
// only have a single polydata object for each LV but bake in the PV
// transformation so clippers and cutters can be implemented
AddPrimitiveTensorGlyph(polyhedron);
}
void G4VtkSceneHandler::Modified() {
for (auto it = polylineDataMap.begin(); it != polylineDataMap.end(); it++)
{
it->second->Modified();
}
for (auto it = polylineLineMap.begin(); it != polylineLineMap.end(); it++)
{
it->second->Modified();
}
for (auto it = circleDataMap.begin(); it != circleDataMap.end(); it++)
{
it->second->Modified();
}
for (auto it = squareDataMap.begin(); it != squareDataMap.end(); it++)
{
it->second->Modified();
}
for(auto it = instancePositionMap.begin(); it != instancePositionMap.end(); it++)
{
it->second->Modified();
}
for(auto it = instanceRotationMap.begin(); it != instanceRotationMap.end(); it++)
{
it->second->Modified();
}
for(auto it = instanceColoursMap.begin(); it != instanceColoursMap.end(); it++)
{
it->second->Modified();
}
for(auto it = instancePolyDataMap.begin(); it != instancePolyDataMap.end(); it++)
{
it->second->Modified();
}
for(auto it = instanceActorMap.begin(); it != instanceActorMap.end(); it++)
{
it->second->Modified();
}
for(auto it = instanceTensorGlyphMap.begin(); it != instanceTensorGlyphMap.end(); it++)
{
it->second->Update();
}
#ifdef G4VTKDEBUG
G4cout << "G4VtkSceneHandler::Modified() polyline styles: " << polylineVisAttributesMap.size() << G4endl;
for (auto it = polylineLineMap.begin(); it != polylineLineMap.end(); it++)
{
G4cout << "G4VtkSceneHandler::Modified() polyline segments: "
<< it->second->GetNumberOfCells() << G4endl;
}
G4cout << "G4VtkSceneHandler::Modified() circle styles: " << circleVisAttributesMap.size() << G4endl;
for (auto it = circleDataMap.begin(); it != circleDataMap.end(); it++)
{
G4cout << "G4VtkSceneHandler::Modified() circles: "
<< it->second->GetNumberOfPoints() << G4endl;
}
G4cout << "G4VtkSceneHandler::Modified() square styles: " << squareVisAttributesMap.size() << G4endl;
for (auto it = squareDataMap.begin(); it != squareDataMap.end(); it++)
{
G4cout << "G4VtkSceneHanler::Modified() squares: "
<< it->second->GetNumberOfPoints() << G4endl;
}
G4cout << "G4VtkSceneHandler::Modified() unique polyhedra: " << polyhedronDataMap.size() << G4endl;
int nPlacements = 0;
int nCells = 0;
for (auto it = polyhedronPolyDataMap.begin(); it != polyhedronPolyDataMap.end(); it++) {
G4cout << "G4VtkSceneHandler::Modified() polyhedronPolyData: " << it->second->GetPoints()->GetNumberOfPoints() << " " << it->second->GetPolys()->GetNumberOfCells() << " " << polyhedronPolyDataCountMap[it->first] <<G4endl;
nCells += it->second->GetPolys()->GetNumberOfCells()*polyhedronPolyDataCountMap[it->first];
nPlacements += polyhedronPolyDataCountMap[it->first];
}
G4cout << "G4VtkSceneHandler::Modified() polyhedronPolyData: " << nPlacements << " " << nCells << G4endl;
#endif
}
void G4VtkSceneHandler::Clear() {
polylineVisAttributesMap.clear();
polylineDataMap.clear();
polylineLineMap.clear();
polylinePolyDataMap.clear();
polylinePolyDataMapperMap.clear();
polylinePolyDataActorMap.clear();
for (auto& v : polylineDataMap)
{v.second->Reset();}
for (auto& v : polylineLineMap)
{v.second->Reset();}
circleVisAttributesMap.clear();
circleDataMap.clear();
circlePolyDataMap.clear();
circleFilterMap.clear();
circlePolyDataMapperMap.clear();
circlePolyDataActorMap.clear();
squareVisAttributesMap.clear();
squareDataMap.clear();
squarePolyDataMap.clear();
squareFilterMap.clear();
squarePolyDataMapperMap.clear();
squarePolyDataActorMap.clear();
for (auto& v : squareDataMap)
{v.second->Reset();}
polyhedronVisAttributesMap.clear();
polyhedronDataMap.clear();
polyhedronPolyMap.clear();
polyhedronPolyDataMap.clear();
polyhedronPolyDataCountMap.clear();
instancePositionMap.clear();
instanceRotationMap.clear();
instanceColoursMap.clear();
instancePolyDataMap.clear();
instanceTensorGlyphMap.clear();
instanceActorMap.clear();
}
void G4VtkSceneHandler::AddSolid (const G4Box& box) {
G4VSceneHandler::AddSolid(box);
#if 0
return;
const G4VModel* pv_model = GetModel();
if (!pv_model) { return ; }
G4PhysicalVolumeModel* pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (!pPVModel) { return ; }
//-- debug information
if(1) {
G4VPhysicalVolume *pv = pPVModel->GetCurrentPV();
G4LogicalVolume *lv = pv->GetLogicalVolume();
G4cout << "name=" << box.GetName() << " volumeType=" << pv->VolumeType() << " pvName=" << pv->GetName() << " lvName=" << lv->GetName() << " multiplicity=" << pv->GetMultiplicity() << " isparametrised=" << pv->IsParameterised() << " isreplicated=" << pv->IsReplicated() << " parametrisation=" << pv->GetParameterisation() << G4endl;
}
if(0) {
G4Material *mat = pPVModel->GetCurrentMaterial();
G4String name = mat->GetName();
G4double dens = mat->GetDensity()/(g/cm3);
G4int copyNo = pPVModel->GetCurrentPV()->GetCopyNo();
G4int depth = pPVModel->GetCurrentDepth();
G4cout << " name : " << box.GetName() << G4endl;
G4cout << " copy no.: " << copyNo << G4endl;
G4cout << " depth : " << depth << G4endl;
G4cout << " density : " << dens << " [g/cm3]" << G4endl;
G4cout << " location: " << pPVModel->GetCurrentPV()->GetObjectTranslation() << G4endl;
G4cout << " Multiplicity : " << pPVModel->GetCurrentPV()->GetMultiplicity() << G4endl;
G4cout << " Is replicated? : " << pPVModel->GetCurrentPV()->IsReplicated() << G4endl;
G4cout << " Is parameterised? : " << pPVModel->GetCurrentPV()->IsParameterised() << G4endl;
G4cout << " top phys. vol. name : " << pPVModel->GetTopPhysicalVolume()->GetName() << G4endl;
}
#endif
}
void G4VtkSceneHandler::AddCompound(const G4Mesh& mesh)
{
#ifdef G4VTKDEBUG
G4cout << "G4VtkSceneHandler::AddCompound" << G4endl;
#endif
if(mesh.GetMeshType() != G4Mesh::rectangle || mesh.GetMeshDepth() != 3)
{
G4VSceneHandler::AddCompound(mesh);
}
auto container = mesh.GetContainerVolume();
auto rep1 = container->GetLogicalVolume()->GetDaughter(0);
auto rep2 = rep1->GetLogicalVolume()->GetDaughter(0);
auto rep3 = rep2->GetLogicalVolume()->GetDaughter(0);
EAxis rep1_axis, rep2_axis, rep3_axis;
G4int rep1_nReplicas, rep2_nReplicas, rep3_nReplicas;
G4double rep1_width, rep2_width, rep3_width;
G4double rep1_offset, rep2_offset, rep3_offset;
G4bool rep1_consuming, rep2_consuming, rep3_consuming;
rep1->GetReplicationData(rep1_axis,rep1_nReplicas, rep1_width, rep1_offset, rep1_consuming);
rep2->GetReplicationData(rep2_axis,rep2_nReplicas, rep2_width, rep2_offset, rep2_consuming);
rep3->GetReplicationData(rep3_axis,rep3_nReplicas, rep3_width, rep3_offset, rep3_consuming);
// Instantiate a temporary G4PhysicalVolumeModel
G4ModelingParameters tmpMP;
tmpMP.SetCulling(false); // This avoids drawing transparent...
tmpMP.SetCullingInvisible(false); // ... or invisble volumes.
const G4bool useFullExtent = false; // To avoid calculating the extent
G4PhysicalVolumeModel tmpPVModel(container, G4PhysicalVolumeModel::UNLIMITED,
G4Transform3D(), &tmpMP, useFullExtent);
// Instantiate a pseudo scene so that we can make a "private" descent and fill vtkImageData
vtkSmartPointer<vtkImageData> imagedata = vtkSmartPointer<vtkImageData>::New();
imagedata->SetDimensions(rep1_nReplicas+1,rep2_nReplicas+1,rep3_nReplicas+1);
imagedata->SetSpacing(rep1_width,rep2_width,rep2_width);
imagedata->SetOrigin(0,0,0);
imagedata->AllocateScalars(VTK_DOUBLE, 1);
G4double halfX = 0., halfY = 0., halfZ = 0.;
struct PseudoScene : public G4PseudoScene
{
PseudoScene(
G4PhysicalVolumeModel* pvModel, // input...the following are output
vtkImageData *vtkId,
G4int nx, G4int ny, G4int nz,
G4double& halfX, G4double& halfY, G4double& halfZ) : fpPVModel(pvModel)
, fVtkId(vtkId)
, fNx(nx)
, fNy(ny)
, fNz(nz)
, fHalfX(halfX)
, fHalfY(halfY)
, fHalfZ(halfZ)
{}
using G4PseudoScene::AddSolid; // except for...
void AddSolid(const G4Box& box)
{
const G4Colour& colour = fpPVModel->GetCurrentLV()->GetVisAttributes()->GetColour();
// G4double density = fpPVModel->GetCurrentLV()->GetMaterial()->GetDensity();
const G4ThreeVector& position = fpCurrentObjectTransformation->getTranslation();
fHalfX = box.GetXHalfLength();
fHalfY = box.GetYHalfLength();
fHalfZ = box.GetZHalfLength();
fVtkId->SetScalarComponentFromDouble(int(position.x()/(2*fHalfX))+fNx,
int(position.y()/(2*fHalfY))+fNy,
int(position.z()/(2*fHalfZ))+fNz,
0,
(colour.GetRed() + colour.GetBlue() + colour.GetGreen())/3.0);
}
G4PhysicalVolumeModel* fpPVModel;
vtkImageData *fVtkId;
G4int fNx, fNy, fNz;
G4double &fHalfX, &fHalfY, &fHalfZ;
}
// construct the pseudoScene
pseudoScene(&tmpPVModel, imagedata, rep1_nReplicas, rep2_nReplicas, rep3_nReplicas, halfX, halfY, halfZ);
// Make private descent into the nested parameterisation
tmpPVModel.DescribeYourselfTo(pseudoScene);
vtkSmartPointer<vtkOpenGLGPUVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkOpenGLGPUVolumeRayCastMapper>::New();
volumeMapper->SetInputData(imagedata);
vtkNew<vtkVolume> volume;
volume->SetMapper(volumeMapper);
vtkSmartPointer<vtkMatrix4x4> vtkMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
vtkMatrix->SetElement(0,0,fObjectTransformation.xx());
vtkMatrix->SetElement(0,1,fObjectTransformation.xy());
vtkMatrix->SetElement(0,2,fObjectTransformation.xz());
vtkMatrix->SetElement(1,0,fObjectTransformation.yx());
vtkMatrix->SetElement(1,1,fObjectTransformation.yy());
vtkMatrix->SetElement(1,2,fObjectTransformation.yz());
vtkMatrix->SetElement(2,0,fObjectTransformation.zx());
vtkMatrix->SetElement(2,1,fObjectTransformation.zy());
vtkMatrix->SetElement(2,2,fObjectTransformation.zz());
vtkMatrix->SetElement(3,0, fObjectTransformation.dx());
vtkMatrix->SetElement(3,1, fObjectTransformation.dy());
vtkMatrix->SetElement(3,2, fObjectTransformation.dz());
vtkMatrix->SetElement(3,3, 1);
volume->SetUserMatrix(vtkMatrix);
auto *pVtkViewer = dynamic_cast<G4VtkViewer *>(fpViewer);
pVtkViewer->renderer->AddVolume(volume);
}
+399
View File
@@ -0,0 +1,399 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
//
// John Allison 5th April 2001
// A template for a simplest possible graphics driver.
//?? Lines or sections marked like this require specialisation for your driver.
#include "G4VtkViewer.hh"
#include "G4VSceneHandler.hh"
#include "G4VtkSceneHandler.hh"
#include "vtkRendererCollection.h"
#include "vtkLightCollection.h"
#include "vtkWindowToImageFilter.h"
#include "vtkImageWriter.h"
#include "vtkBMPWriter.h"
#include "vtkJPEGWriter.h"
#include "vtkPNGWriter.h"
#include "vtkPNMWriter.h"
#include "vtkTIFFWriter.h"
#include "vtkPostScriptWriter.h"
#include "vtkOBJExporter.h"
#include "vtkVRMLExporter.h"
#include "vtkSingleVTPExporter.h"
#include "vtkShadowMapPass.h"
#include "vtkShadowMapBakerPass.h"
#include "vtkSequencePass.h"
#include "vtkCameraPass.h"
#include "vtkRenderPass.h"
#include "vtkRenderPassCollection.h"
#include "vtkOpenGLRenderer.h"
G4VtkViewer::G4VtkViewer(G4VSceneHandler& sceneHandler, const G4String& name)
: G4VViewer(sceneHandler, sceneHandler.IncrementViewCount(), name)
{
// Set default and current view parameters
fVP.SetAutoRefresh(true);
fDefaultVP.SetAutoRefresh(true);
}
void G4VtkViewer::Initialise()
{
_renderWindow = vtkRenderWindow::New();
renderWindowInteractor = vtkRenderWindowInteractor::New();
#ifdef G4VTKDEBUG
G4cout << "G4VtkViewer::G4VtkViewer" << G4endl;
G4cout << "G4VtkViewer::G4VtkViewer> " << fVP.GetWindowSizeHintX() << " "
<< fVP.GetWindowSizeHintY() << G4endl;
G4cout << "G4VtkViewer::G4VtkViewer> " << fVP.GetWindowLocationHintX() << " "
<< fVP.GetWindowLocationHintY() << G4endl;
#endif
_renderWindow->SetSize(fVP.GetWindowSizeHintX(), fVP.GetWindowSizeHintY());
_renderWindow->SetPosition(fVP.GetWindowLocationHintX(),
fVP.GetWindowLocationHintY());
_renderWindow->SetWindowName("Vtk viewer");
_renderWindow->AddRenderer(renderer);
renderWindowInteractor->SetRenderWindow(_renderWindow);
// TODO proper camera parameter settings
camera->SetPosition(0, 0, 1000);
camera->SetFocalPoint(0, 0, 0);
renderer->SetActiveCamera(camera);
//renderer->SetUseHiddenLineRemoval(1); // TODO needs to be an option
//renderer->SetUseShadows(1); // TODO needs to be an option
// Set callback to match VTK parameters to Geant4
geant4Callback->SetGeant4ViewParameters(&fVP);
renderer->AddObserver(vtkCommand::EndEvent, geant4Callback);
vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =
vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
renderWindowInteractor->SetInteractorStyle(style);
// DrawShadows();
}
G4VtkViewer::~G4VtkViewer() {}
void G4VtkViewer::SetView() {
// background colour
const G4Colour backgroundColour = fVP.GetBackgroundColour();
renderer->SetBackground(backgroundColour.GetRed(), backgroundColour.GetGreen(), backgroundColour.GetBlue());
// target and camera positions
G4double radius = fSceneHandler.GetExtent().GetExtentRadius();
if(radius <= 0.)
{radius = 1.;}
G4double cameraDistance = fVP.GetCameraDistance(radius);
G4Point3D viewpointDirection = fVP.GetViewpointDirection();
G4Point3D targetPoint = fVP.GetCurrentTargetPoint();
G4Point3D cameraPosition =
targetPoint + viewpointDirection.unit() * cameraDistance;
renderer->GetActiveCamera()->SetFocalPoint(targetPoint.x(),
targetPoint.y(),
targetPoint.z());
renderer->GetActiveCamera()->SetPosition(cameraPosition.x(),
cameraPosition.y(),
cameraPosition.z());
renderer->GetActiveCamera()->SetParallelScale(cameraDistance);
// need to set camera distance and parallel scale on first set view
if(firstSetView)
{
geant4Callback->SetVtkInitialValues(cameraDistance, cameraDistance);
firstSetView = false;
}
// projection type and view angle and zoom factor
G4double fieldHalfAngle = fVP.GetFieldHalfAngle();
G4double zoomFactor = fVP.GetZoomFactor();
vtkCamera* activeCamera = renderer->GetActiveCamera();
if(fieldHalfAngle == 0) {
activeCamera->SetParallelProjection(1);
activeCamera->SetParallelScale(activeCamera->GetParallelScale()/zoomFactor);
}
else {
activeCamera->SetParallelProjection(0);
activeCamera->SetViewAngle(2*fieldHalfAngle/M_PI*180);
activeCamera->SetPosition(cameraPosition.x()/zoomFactor,
cameraPosition.y()/zoomFactor,
cameraPosition.z()/zoomFactor);
}
// camera roll
// renderer->GetActiveCamera()->SetRoll(0);
// camera up direction
const G4Vector3D upVector = fVP.GetUpVector();
renderer->GetActiveCamera()->SetViewUp(upVector.x(),
upVector.y(),
upVector.z());
// Light
const G4Vector3D lightDirection = fVP.GetLightpointDirection();
G4bool lightsMoveWithCamera = fVP.GetLightsMoveWithCamera();
G4Vector3D lightPosition =
targetPoint + lightDirection.unit() * cameraDistance;
vtkLightCollection* currentLights = renderer->GetLights();
if (currentLights->GetNumberOfItems() != 0)
{
auto currentLight = dynamic_cast<vtkLight*>(currentLights->GetItemAsObject(0));
if (currentLight)
{
currentLight->SetPosition(lightPosition.x(),
lightPosition.y(),
lightPosition.z());
if (lightsMoveWithCamera)
{currentLight->SetLightTypeToCameraLight();}
else
{currentLight->SetLightTypeToSceneLight();}
}
}
// Rotation style
G4ViewParameters::RotationStyle rotationStyle = fVP.GetRotationStyle();
if (rotationStyle == G4ViewParameters::RotationStyle::freeRotation) {
vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =
vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
renderWindowInteractor->SetInteractorStyle(style);
}
else if(rotationStyle == G4ViewParameters::RotationStyle::constrainUpDirection) {
// camera->SetViewUp(upVector.x(), upVector.y(), upVector.z());
vtkSmartPointer<vtkInteractorStyleTerrain> style =
vtkSmartPointer<vtkInteractorStyleTerrain>::New();
renderWindowInteractor->SetInteractorStyle(style);
}
}
void G4VtkViewer::ClearView() {
vtkActorCollection *actors = renderer->GetActors();
vtkActor *actor = actors->GetLastActor();
while(actor) {
#ifdef G4VTKDEBUG
G4cout << "G4VtkViewer::ClearView() remove actor " << actor << G4endl;
#endif
renderer->RemoveActor(actor);
actor = actors->GetLastActor();
}
vtkPropCollection *props = renderer->GetViewProps();
vtkProp *prop = props->GetLastProp();
while(prop) {
#ifdef G4VTKDEBUG
G4cout << "G4VtkViewer::ClearView() remove prop " << prop << G4endl;
#endif
renderer->RemoveViewProp(prop);
prop = props->GetLastProp();
}
G4VtkSceneHandler& fVtkSceneHandler =
dynamic_cast<G4VtkSceneHandler&>(fSceneHandler);
fVtkSceneHandler.Clear();
}
void G4VtkViewer::DrawView() {
// First, a view should decide when to re-visit the G4 kernel.
// Sometimes it might not be necessary, e.g., if the scene is stored
// in a graphical database (e.g., OpenGL's display lists) and only
// the viewing angle has changed. But graphics systems without a
// graphical database will always need to visit the G4 kernel.
NeedKernelVisit(); // Default is - always visit G4 kernel.
// Note: this routine sets the fNeedKernelVisit flag of *all* the
// views of the scene.
ProcessView(); // The basic logic is here.
// Add HUD
DrawViewHUD();
// ...before finally...
FinishView(); // Flush streams and/or swap buffers.
}
void G4VtkViewer::DrawViewHUD()
{
// make sure text is always visible
G4Colour colour = fVP.GetBackgroundColour();
infoTextActor->GetTextProperty()->SetColor(std::fmod(colour.GetRed() + 0.5, 1.0),
std::fmod(colour.GetGreen() + 0.5, 1.0),
std::fmod(colour.GetBlue() + 0.5, 1.0));
infoTextActor->GetTextProperty()->SetFontSize(20);
infoCallback->SetTextActor(infoTextActor);
renderer->AddObserver(vtkCommand::EndEvent, infoCallback);
renderer->AddActor(infoTextActor);
}
void G4VtkViewer::DrawShadows()
{
_renderWindow->SetMultiSamples(0);
vtkNew<vtkShadowMapPass> shadows;
vtkNew<vtkSequencePass> seq;
vtkNew<vtkRenderPassCollection> passes;
passes->AddItem(shadows->GetShadowMapBakerPass());
passes->AddItem(shadows);
seq->SetPasses(passes);
vtkNew<vtkCameraPass> cameraP;
cameraP->SetDelegatePass(seq);
// tell the renderer to use our render pass pipeline
vtkOpenGLRenderer* glrenderer = dynamic_cast<vtkOpenGLRenderer*>(renderer.GetPointer());
glrenderer->SetPass(cameraP);
}
void G4VtkViewer::ShowView()
{
#ifdef G4VTKDEBUG
G4cout << "G4VtkViewer::ShowView() called." << G4endl;
// static_cast<G4VtkSceneHandler&>(fSceneHandler).PrintStores();
#endif
G4VtkSceneHandler& fVtkSceneHandler =
dynamic_cast<G4VtkSceneHandler&>(fSceneHandler);
fVtkSceneHandler.Modified();
infoTextActor->GetTextProperty()->SetFontSize(28);
G4Colour colour = fVP.GetBackgroundColour();
// make sure text is always visible
infoTextActor->GetTextProperty()->SetColor(std::fmod(colour.GetRed() + 0.5, 1.0),
std::fmod(colour.GetGreen() + 0.5, 1.0),
std::fmod(colour.GetBlue() + 0.5, 1.0));
infoTextActor->GetTextProperty()->SetFontSize(20);
infoCallback->SetTextActor(infoTextActor);
renderer->AddObserver(vtkCommand::EndEvent, infoCallback);
geant4Callback->SetGeant4ViewParameters(&fVP);
renderer->AddObserver(vtkCommand::EndEvent, geant4Callback);
renderer->AddActor(infoTextActor);
_renderWindow->Render();
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
}
void G4VtkViewer::FinishView()
{
G4VtkSceneHandler& fVtkSceneHandler =
dynamic_cast<G4VtkSceneHandler&>(fSceneHandler);
fVtkSceneHandler.Modified();
_renderWindow->Render();
}
void G4VtkViewer::ExportScreenShot(G4String path, G4String format)
{
vtkImageWriter *imWriter = nullptr;
if(format == "bmp") {
imWriter = vtkBMPWriter::New();
}
else if (format == "jpg") {
imWriter = vtkJPEGWriter::New();
}
else if (format == "pnm") {
imWriter = vtkPNMWriter::New();
}
else if (format == "png") {
imWriter = vtkPNGWriter::New();
}
else if (format == "tiff") {
imWriter = vtkTIFFWriter::New();
}
else if (format == "ps") {
imWriter = vtkPostScriptWriter::New();
}
else {
imWriter = vtkPNGWriter::New();
}
_renderWindow->Render();
vtkSmartPointer<vtkWindowToImageFilter> winToImage = vtkSmartPointer<vtkWindowToImageFilter>::New();
winToImage->SetInput(_renderWindow);
winToImage->SetScale(1);
if(format == "ps")
{
winToImage->SetInputBufferTypeToRGB();
winToImage->ReadFrontBufferOff();
winToImage->Update();
}
else
{winToImage->SetInputBufferTypeToRGBA();}
imWriter->SetFileName((path+"."+format).c_str());
imWriter->SetInputConnection(winToImage->GetOutputPort());
imWriter->Write();
}
void G4VtkViewer::ExportOBJScene(G4String path)
{
vtkSmartPointer<vtkRenderWindow> _rw1 = vtkSmartPointer<vtkRenderWindow>::New();
_rw1->AddRenderer(_renderWindow->GetRenderers()->GetFirstRenderer());
vtkSmartPointer<vtkOBJExporter> exporter = vtkSmartPointer<vtkOBJExporter>::New();
exporter->SetRenderWindow(_rw1);
exporter->SetFilePrefix(path.c_str());
exporter->Write();
}
void G4VtkViewer::ExportVRMLScene(G4String path)
{
vtkSmartPointer<vtkRenderWindow> _rw1 = vtkSmartPointer<vtkRenderWindow>::New();
_rw1->AddRenderer(_renderWindow->GetRenderers()->GetFirstRenderer());
vtkSmartPointer<vtkVRMLExporter> exporter = vtkSmartPointer<vtkVRMLExporter>::New();
exporter->SetRenderWindow(_rw1);
exporter->SetFileName((path+".vrml").c_str());
exporter->Write();
}
void G4VtkViewer::ExportVTPScene(G4String path)
{
vtkSmartPointer<vtkRenderWindow> _rw1 = vtkSmartPointer<vtkRenderWindow>::New();
_rw1->AddRenderer(_renderWindow->GetRenderers()->GetFirstRenderer());
vtkSmartPointer<vtkSingleVTPExporter> exporter = vtkSmartPointer<vtkSingleVTPExporter>::New();
exporter->SetRenderWindow(_rw1);
exporter->SetFileName((path+".vtp").c_str());
exporter->Write();
}
@@ -0,0 +1,565 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkTensorGlyphColor.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkTensorGlyphColor.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkCell.h"
#include "vtkCellArray.h"
#include "vtkDataSet.h"
#include "vtkExecutive.h"
#include "vtkFloatArray.h"
#include "vtkDoubleArray.h"
#include "vtkMath.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkTransform.h"
vtkStandardNewMacro(vtkTensorGlyphColor)
// Construct object with scaling on and scale factor 1.0. Eigenvalues are
// extracted, glyphs are colored with input scalar data, and logarithmic
// scaling is turned off.
vtkTensorGlyphColor::vtkTensorGlyphColor()
{
this->Scaling = 1;
this->ScaleFactor = 1.0;
this->ExtractEigenvalues = 1;
this->ColorGlyphs = 1;
this->ColorMode = COLOR_BY_SCALARS;
this->ClampScaling = 0;
this->MaxScaleFactor = 100;
this->ThreeGlyphs = 0;
this->Symmetric = 0;
this->Length = 1.0;
this->SetNumberOfInputPorts(2);
// by default, process active point tensors
this->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS,
vtkDataSetAttributes::TENSORS);
// by default, process active point scalars
this->SetInputArrayToProcess(1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS,
vtkDataSetAttributes::SCALARS);
}
//----------------------------------------------------------------------------
vtkTensorGlyphColor::~vtkTensorGlyphColor() = default;
//----------------------------------------------------------------------------
int vtkTensorGlyphColor::RequestUpdateExtent(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
if (sourceInfo)
{
sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
0);
sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
1);
sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
0);
}
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()));
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()));
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()));
inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1);
return 1;
}
//----------------------------------------------------------------------------
int vtkTensorGlyphColor::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// get the input and output
vtkDataSet *input = vtkDataSet::SafeDownCast(
inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkPolyData *source = vtkPolyData::SafeDownCast(
sourceInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkPolyData *output = vtkPolyData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkDataArray *inTensors;
double tensor[9];
vtkDataArray *inScalars;
vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i;
int j;
vtkPoints *sourcePts;
vtkDataArray *sourceNormals;
vtkCellArray *sourceCells, *cells;
vtkPoints *newPts;
vtkFloatArray *newScalars=nullptr;
vtkFloatArray *newNormals=nullptr;
double x[3], s;
vtkTransform *trans;
vtkCell *cell;
vtkIdList *cellPts;
int npts;
vtkIdType *pts;
vtkIdType ptIncr, cellId;
vtkIdType subIncr;
int numDirs, dir, eigen_dir, symmetric_dir;
vtkMatrix4x4 *matrix;
double *m[3], w[3], *v[3];
double m0[3], m1[3], m2[3];
double v0[3], v1[3], v2[3];
double xv[3], yv[3], zv[3];
double maxScale;
numDirs = (this->ThreeGlyphs?3:1)*(this->Symmetric+1);
// set up working matrices
m[0] = m0; m[1] = m1; m[2] = m2;
v[0] = v0; v[1] = v1; v[2] = v2;
vtkDebugMacro(<<"Generating tensor glyphs");
vtkPointData *outPD = output->GetPointData();
inTensors = this->GetInputArrayToProcess(0, inputVector);
inScalars = this->GetInputArrayToProcess(1, inputVector);
numPts = input->GetNumberOfPoints();
if ( !inTensors || numPts < 1 )
{
vtkErrorMacro(<<"No data to glyph!");
return 1;
}
pts = new vtkIdType[source->GetMaxCellSize()];
trans = vtkTransform::New();
matrix = vtkMatrix4x4::New();
//
// Allocate storage for output PolyData
//
sourcePts = source->GetPoints();
numSourcePts = sourcePts->GetNumberOfPoints();
numSourceCells = source->GetNumberOfCells();
newPts = vtkPoints::New();
newPts->Allocate(numDirs*numPts*numSourcePts);
// Setting up for calls to PolyData::InsertNextCell()
if ( (sourceCells=source->GetVerts())->GetNumberOfCells() > 0 )
{
cells = vtkCellArray::New();
cells->Allocate(numDirs*numPts*sourceCells->GetSize());
output->SetVerts(cells);
cells->Delete();
}
if ( (sourceCells=this->GetSource()->GetLines())->GetNumberOfCells() > 0 )
{
cells = vtkCellArray::New();
cells->Allocate(numDirs*numPts*sourceCells->GetSize());
output->SetLines(cells);
cells->Delete();
}
if ( (sourceCells=this->GetSource()->GetPolys())->GetNumberOfCells() > 0 )
{
cells = vtkCellArray::New();
cells->Allocate(numDirs*numPts*sourceCells->GetSize());
output->SetPolys(cells);
cells->Delete();
}
if ( (sourceCells=this->GetSource()->GetStrips())->GetNumberOfCells() > 0 )
{
cells = vtkCellArray::New();
cells->Allocate(numDirs*numPts*sourceCells->GetSize());
output->SetStrips(cells);
cells->Delete();
}
// only copy scalar data through
vtkPointData *pd = this->GetSource()->GetPointData();
// generate scalars if eigenvalues are chosen or if scalars exist.
if (this->ColorGlyphs &&
((this->ColorMode == COLOR_BY_EIGENVALUES) ||
(inScalars && (this->ColorMode == COLOR_BY_SCALARS)) ) )
{
newScalars = vtkFloatArray::New();
newScalars->SetNumberOfComponents(4);
newScalars->Allocate(numDirs*numPts*numSourcePts);
if (this->ColorMode == COLOR_BY_EIGENVALUES)
{
newScalars->SetName("MaxEigenvalue");
}
else
{
newScalars->SetName(inScalars->GetName());
}
}
else
{
outPD->CopyAllOff();
outPD->CopyScalarsOn();
outPD->CopyAllocate(pd,numDirs*numPts*numSourcePts);
}
if ( (sourceNormals = pd->GetNormals()) )
{
newNormals = vtkFloatArray::New();
newNormals->SetNumberOfComponents(3);
newNormals->SetName("Normals");
newNormals->Allocate(numDirs*3*numPts*numSourcePts);
}
//
// First copy all topology (transformation independent)
//
for (inPtId=0; inPtId < numPts; inPtId++)
{
ptIncr = numDirs * inPtId * numSourcePts;
for (cellId=0; cellId < numSourceCells; cellId++)
{
cell = this->GetSource()->GetCell(cellId);
cellPts = cell->GetPointIds();
npts = cellPts->GetNumberOfIds();
for (dir=0; dir < numDirs; dir++)
{
// This variable may be removed, but that
// will not improve readability
subIncr = ptIncr + dir*numSourcePts;
for (i=0; i < npts; i++)
{
pts[i] = cellPts->GetId(i) + subIncr;
}
output->InsertNextCell(cell->GetCellType(),npts,pts);
}
}
}
//
// Traverse all Input points, transforming glyph at Source points
//
trans->PreMultiply();
for (inPtId=0; inPtId < numPts; inPtId++)
{
ptIncr = numDirs * inPtId * numSourcePts;
// Translation is postponed
// Symmetric tensor support
inTensors->GetTuple(inPtId, tensor);
if (inTensors->GetNumberOfComponents() == 6)
{
vtkMath::TensorFromSymmetricTensor(tensor);
}
// compute orientation vectors and scale factors from tensor
if ( this->ExtractEigenvalues ) // extract appropriate eigenfunctions
{
// We are interested in the symmetrical part of the tensor only, since
// eigenvalues are real if and only if the matrice of reals is symmetrical
for (j=0; j<3; j++)
{
for (i=0; i<3; i++)
{
m[i][j] = 0.5 * (tensor[i + 3 * j] + tensor[j + 3 * i]);
}
}
vtkMath::Jacobi(m, w, v);
//copy eigenvectors
xv[0] = v[0][0]; xv[1] = v[1][0]; xv[2] = v[2][0];
yv[0] = v[0][1]; yv[1] = v[1][1]; yv[2] = v[2][1];
zv[0] = v[0][2]; zv[1] = v[1][2]; zv[2] = v[2][2];
}
else //use tensor columns as eigenvectors
{
for (i=0; i<3; i++)
{
xv[i] = tensor[i];
yv[i] = tensor[i+3];
zv[i] = tensor[i+6];
}
w[0] = vtkMath::Normalize(xv);
w[1] = vtkMath::Normalize(yv);
w[2] = vtkMath::Normalize(zv);
}
// compute scale factors
w[0] *= this->ScaleFactor;
w[1] *= this->ScaleFactor;
w[2] *= this->ScaleFactor;
if ( this->ClampScaling )
{
for (maxScale=0.0, i=0; i<3; i++)
{
if ( maxScale < fabs(w[i]) )
{
maxScale = fabs(w[i]);
}
}
if ( maxScale > this->MaxScaleFactor )
{
maxScale = this->MaxScaleFactor / maxScale;
for (i=0; i<3; i++)
{
w[i] *= maxScale; //preserve overall shape of glyph
}
}
}
// normalization is postponed
// make sure scale is okay (non-zero) and scale data
for (maxScale=0.0, i=0; i<3; i++)
{
if ( w[i] > maxScale )
{
maxScale = w[i];
}
}
if ( maxScale == 0.0 )
{
maxScale = 1.0;
}
for (i=0; i<3; i++)
{
if ( w[i] == 0.0 )
{
w[i] = maxScale * 1.0e-06;
}
}
// Now do the real work for each "direction"
for (dir=0; dir < numDirs; dir++)
{
eigen_dir = dir%(this->ThreeGlyphs?3:1);
symmetric_dir = dir/(this->ThreeGlyphs?3:1);
// Remove previous scales ...
trans->Identity();
// translate Source to Input point
input->GetPoint(inPtId, x);
trans->Translate(x[0], x[1], x[2]);
// normalized eigenvectors rotate object for eigen direction 0
matrix->Element[0][0] = xv[0];
matrix->Element[0][1] = yv[0];
matrix->Element[0][2] = zv[0];
matrix->Element[1][0] = xv[1];
matrix->Element[1][1] = yv[1];
matrix->Element[1][2] = zv[1];
matrix->Element[2][0] = xv[2];
matrix->Element[2][1] = yv[2];
matrix->Element[2][2] = zv[2];
trans->Concatenate(matrix);
if (eigen_dir == 1)
{
trans->RotateZ(90.0);
}
if (eigen_dir == 2)
{
trans->RotateY(-90.0);
}
if (this->ThreeGlyphs)
{
trans->Scale(w[eigen_dir], this->ScaleFactor, this->ScaleFactor);
}
else
{
trans->Scale(w[0], w[1], w[2]);
}
// Mirror second set to the symmetric position
if (symmetric_dir == 1)
{
trans->Scale(-1.,1.,1.);
}
// if the eigenvalue is negative, shift to reverse direction.
// The && is there to ensure that we do not change the
// old behaviour of vtkTensorGlyphColors (which only used one dir),
// in case there is an oriented glyph, e.g. an arrow.
if (w[eigen_dir] < 0 && numDirs > 1)
{
trans->Translate(-this->Length, 0., 0.);
}
// multiply points (and normals if available) by resulting
// matrix
trans->TransformPoints(sourcePts,newPts);
// Apply the transformation to a series of points,
// and append the results to outPts.
if ( newNormals )
{
// a negative determinant means the transform turns the
// glyph surface inside out, and its surface normals all
// point inward. The following scale corrects the surface
// normals to point outward.
if (trans->GetMatrix()->Determinant() < 0)
{
trans->Scale(-1.0,-1.0,-1.0);
}
trans->TransformNormals(sourceNormals,newNormals);
}
// Copy point data from source
if ( this->ColorGlyphs && inScalars &&
(this->ColorMode == COLOR_BY_SCALARS) )
{
for (i=0; i < numSourcePts; i++)
{
auto st = inScalars->GetTuple(inPtId);
newScalars->InsertTuple4(ptIncr+i,st[0],st[1],st[2],st[3]);
}
}
else if (this->ColorGlyphs &&
(this->ColorMode == COLOR_BY_EIGENVALUES) )
{
// If ThreeGlyphs is false we use the first (largest)
// eigenvalue as scalar.
s = w[eigen_dir];
for (i=0; i < numSourcePts; i++)
{
newScalars->InsertTuple(ptIncr+i, &s);
}
}
else
{
for (i=0; i < numSourcePts; i++)
{
outPD->CopyData(pd,i,ptIncr+i);
}
}
ptIncr += numSourcePts;
}
}
vtkDebugMacro(<<"Generated " << numPts <<" tensor glyphs");
//
// Update output and release memory
//
delete [] pts;
output->SetPoints(newPts);
newPts->Delete();
if ( newScalars )
{
int idx = outPD->AddArray(newScalars);
outPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
newScalars->Delete();
}
if ( newNormals )
{
outPD->SetNormals(newNormals);
newNormals->Delete();
}
output->Squeeze();
trans->Delete();
matrix->Delete();
return 1;
}
//----------------------------------------------------------------------------
void vtkTensorGlyphColor::SetSourceConnection(int id, vtkAlgorithmOutput* algOutput)
{
if (id < 0)
{
vtkErrorMacro("Bad index " << id << " for source.");
return;
}
int numConnections = this->GetNumberOfInputConnections(1);
if (id < numConnections)
{
this->SetNthInputConnection(1, id, algOutput);
}
else if (id == numConnections && algOutput)
{
this->AddInputConnection(1, algOutput);
}
else if (algOutput)
{
vtkWarningMacro("The source id provided is larger than the maximum "
"source id, using " << numConnections << " instead.");
this->AddInputConnection(1, algOutput);
}
}
//----------------------------------------------------------------------------
void vtkTensorGlyphColor::SetSourceData(vtkPolyData *source)
{
this->SetInputData(1, source);
}
//----------------------------------------------------------------------------
vtkPolyData *vtkTensorGlyphColor::GetSource()
{
if (this->GetNumberOfInputConnections(1) < 1)
{
return nullptr;
}
return vtkPolyData::SafeDownCast(this->GetExecutive()->GetInputData(1, 0));
}
//----------------------------------------------------------------------------
int vtkTensorGlyphColor::FillInputPortInformation(int port, vtkInformation *info)
{
if (port == 1)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
return 1;
}
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
return 1;
}
//----------------------------------------------------------------------------
void vtkTensorGlyphColor::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Source: " << this->GetSource() << "\n";
os << indent << "Scaling: " << (this->Scaling ? "On\n" : "Off\n");
os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
os << indent << "Extract Eigenvalues: " << (this->ExtractEigenvalues ? "On\n" : "Off\n");
os << indent << "Color Glyphs: " << (this->ColorGlyphs ? "On\n" : "Off\n");
os << indent << "Color Mode: " << this->ColorMode << endl;
os << indent << "Clamp Scaling: " << (this->ClampScaling ? "On\n" : "Off\n");
os << indent << "Max Scale Factor: " << this->MaxScaleFactor << "\n";
os << indent << "Three Glyphs: " << (this->ThreeGlyphs ? "On\n" : "Off\n");
os << indent << "Symmetric: " << (this->Symmetric ? "On\n" : "Off\n");
os << indent << "Length: " << this->Length << "\n";
}