Import Geant4 11.0.0 source tree
This commit is contained in:
committed by
Ben Morgan
parent
6399a014b6
commit
80e2389dd8
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
Reference in New Issue
Block a user