Compare commits
3 Commits
ca5f576b99
...
a8c0d5edc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8c0d5edc2 | ||
|
|
dbb5f24933 | ||
|
|
1e6e3ae4f4 |
@@ -29,14 +29,14 @@ EmitterPrimary::EmitterPrimary()
|
|||||||
// Configuriamo le proprietà iniziali della particella
|
// Configuriamo le proprietà iniziali della particella
|
||||||
fParticleGun->SetParticleDefinition(particle);
|
fParticleGun->SetParticleDefinition(particle);
|
||||||
|
|
||||||
// Impostiamo la direzione della quantità di moto (es. lungo l'asse Z)
|
|
||||||
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0., 0., -1.));
|
|
||||||
|
|
||||||
// Impostiamo l'energia cinetica a 1 GeV
|
// Impostiamo l'energia cinetica a 1 GeV
|
||||||
fParticleGun->SetParticleEnergy(1.0 * GeV);
|
fParticleGun->SetParticleEnergy(1.0 * GeV);
|
||||||
|
|
||||||
// Impostiamo la posizione di partenza (origine)
|
// Initial position and direction through AffineTransform
|
||||||
fParticleGun->SetParticlePosition(G4ThreeVector(0., 0., 10. * m));
|
// 10m on Z axis, pointing towards origin
|
||||||
|
this->SetPosition(Vector3f(0, 0, 10000.0));
|
||||||
|
// Default orientation is identity (pointing along -Z if we rotate the puppet accordingly)
|
||||||
|
// But fParticleGun defaults are set here and overridden in GeneratePrimaries
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitterPrimary::~EmitterPrimary() {
|
EmitterPrimary::~EmitterPrimary() {
|
||||||
@@ -45,9 +45,14 @@ EmitterPrimary::~EmitterPrimary() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EmitterPrimary::GeneratePrimaries(G4Event *anEvent) {
|
void EmitterPrimary::GeneratePrimaries(G4Event *anEvent) {
|
||||||
// Questo metodo viene invocato all'inizio di ogni evento.
|
// Use position and direction from AffineTransform
|
||||||
// Qui potresti anche aggiungere una randomizzazione della posizione o
|
Vector3f pos = this->GetPosition();
|
||||||
// dell'energia.
|
// Assume default direction is along the -Z axis of the local frame
|
||||||
|
Vector4f dir4 = this->GetWorldMatrix() * Vector4f(0, 0, -1, 0);
|
||||||
|
Vector3f dir = dir4.head<3>().normalized();
|
||||||
|
|
||||||
|
fParticleGun->SetParticlePosition(G4ThreeVector(pos(0), pos(1), pos(2)));
|
||||||
|
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(dir(0), dir(1), dir(2)));
|
||||||
|
|
||||||
fParticleGun->GeneratePrimaryVertex(anEvent);
|
fParticleGun->GeneratePrimaryVertex(anEvent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,13 @@
|
|||||||
#include "G4VUserPrimaryGeneratorAction.hh"
|
#include "G4VUserPrimaryGeneratorAction.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
class QuadMesh;
|
||||||
|
}
|
||||||
|
|
||||||
#include "Math/QuadMesh.h"
|
#include "Math/QuadMesh.h"
|
||||||
|
#include "Core/Object.h"
|
||||||
|
#include "Math/Transform.h"
|
||||||
#include <vector> // Added for std::vector
|
#include <vector> // Added for std::vector
|
||||||
|
|
||||||
class G4ParticleGun;
|
class G4ParticleGun;
|
||||||
@@ -13,7 +19,7 @@ class G4Event;
|
|||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Geant {
|
namespace Geant {
|
||||||
|
|
||||||
class EmitterPrimary : public G4VUserPrimaryGeneratorAction
|
class EmitterPrimary : public G4VUserPrimaryGeneratorAction, public Object, public AffineTransform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EmitterPrimary();
|
EmitterPrimary();
|
||||||
@@ -22,11 +28,14 @@ class EmitterPrimary : public G4VUserPrimaryGeneratorAction
|
|||||||
// Metodo principale chiamato all'inizio di ogni evento
|
// Metodo principale chiamato all'inizio di ogni evento
|
||||||
virtual void GeneratePrimaries(G4Event*);
|
virtual void GeneratePrimaries(G4Event*);
|
||||||
|
|
||||||
|
virtual void Updated() override { ULIB_SIGNAL_EMIT(EmitterPrimary::Updated); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
G4ParticleGun* fParticleGun; // Puntatore al cannone di particelle
|
G4ParticleGun* fParticleGun; // Puntatore al cannone di particelle
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class QuadMeshEmitterPrimary : public EmitterPrimary
|
class QuadMeshEmitterPrimary : public EmitterPrimary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
#define U_TRANSFORM_H
|
#define U_TRANSFORM_H
|
||||||
|
|
||||||
#include <Eigen/Geometry>
|
#include <Eigen/Geometry>
|
||||||
|
#include "Math/Dense.h"
|
||||||
|
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
|
|
||||||
set(HEP_GEANT_SOURCES
|
set(HEP_GEANT_SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantEvent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantEvent.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/vtkEmitterPrimary.cpp
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
|
||||||
set(HEP_GEANT_HEADERS
|
set(HEP_GEANT_HEADERS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantEvent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantEvent.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/vtkEmitterPrimary.h
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
|
||||||
if(BUILD_TESTING)
|
if(BUILD_TESTING)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# TESTS
|
# TESTS
|
||||||
set(TESTS
|
set(TESTS
|
||||||
vtkGeantEventTest
|
vtkGeantEventTest
|
||||||
|
vtkEmitterPrimaryTest
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBRARIES
|
set(LIBRARIES
|
||||||
|
|||||||
124
src/Vtk/HEP/Geant/testing/vtkEmitterPrimaryTest.cpp
Normal file
124
src/Vtk/HEP/Geant/testing/vtkEmitterPrimaryTest.cpp
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
#include "Geant/Solid.h"
|
||||||
|
#include "HEP/Geant/GeantEvent.h"
|
||||||
|
#include "HEP/Geant/Scene.h"
|
||||||
|
#include "HEP/Geant/EmitterPrimary.hh"
|
||||||
|
#include "Math/ContainerBox.h"
|
||||||
|
#include "Math/Dense.h"
|
||||||
|
#include "Math/Units.h"
|
||||||
|
#include "Vtk/uLibVtkViewer.h"
|
||||||
|
#include "Vtk/HEP/Geant/vtkGeantEvent.h"
|
||||||
|
#include "Vtk/HEP/Geant/vtkEmitterPrimary.h"
|
||||||
|
#include "Vtk/vtkContainerBox.h"
|
||||||
|
|
||||||
|
#include <vtkSmartPointer.h>
|
||||||
|
#include <vtkCallbackCommand.h>
|
||||||
|
#include <vtkRenderWindowInteractor.h>
|
||||||
|
#include <vtkProperty.h>
|
||||||
|
#include <vtkRenderer.h>
|
||||||
|
#include <vtkRenderWindow.h>
|
||||||
|
|
||||||
|
#include <Geant4/Randomize.hh>
|
||||||
|
#include <Geant4/G4ParticleGun.hh>
|
||||||
|
#include <Geant4/G4SystemOfUnits.hh>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace uLib;
|
||||||
|
|
||||||
|
struct AppState {
|
||||||
|
Geant::Scene* scene;
|
||||||
|
Vtk::Viewer* viewer;
|
||||||
|
Vector<Geant::GeantEvent> results;
|
||||||
|
};
|
||||||
|
|
||||||
|
void KeyPressCallbackFunction(vtkObject* caller, long unsigned int eventId, void* clientData, void* callData) {
|
||||||
|
auto* interactor = static_cast<vtkRenderWindowInteractor*>(caller);
|
||||||
|
auto* state = static_cast<AppState*>(clientData);
|
||||||
|
|
||||||
|
std::string key = interactor->GetKeySym();
|
||||||
|
if (key == "Return") {
|
||||||
|
std::cout << "--> Firing muon from current emitter position..." << std::endl;
|
||||||
|
|
||||||
|
// Run one event
|
||||||
|
state->scene->RunSimulation(1, state->results);
|
||||||
|
|
||||||
|
if (!state->results.empty()) {
|
||||||
|
// Get the last event
|
||||||
|
Geant::GeantEvent* lastEvent = &state->results.back();
|
||||||
|
std::cout << " Collected event " << lastEvent->GetEventID()
|
||||||
|
<< " with " << lastEvent->Path().size() << " steps." << std::endl;
|
||||||
|
|
||||||
|
// Wrap it for VTK
|
||||||
|
Vtk::vtkGeantEvent* vtkEvent = new Vtk::vtkGeantEvent(lastEvent);
|
||||||
|
state->viewer->AddPuppet(*vtkEvent);
|
||||||
|
|
||||||
|
// Re-render
|
||||||
|
state->viewer->GetRenderer()->Render();
|
||||||
|
state->viewer->GetRenderWindow()->Render();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << " No event collected." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
// 1. Setup Geant4 Scene
|
||||||
|
Geant::Scene scene;
|
||||||
|
scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR");
|
||||||
|
|
||||||
|
ContainerBox iron_box;
|
||||||
|
iron_box.Scale(Vector3f(10_m, 10_m, 10_m));
|
||||||
|
iron_box.SetPosition(Vector3f(0, 0, 0));
|
||||||
|
Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box);
|
||||||
|
iron_cube->SetNistMaterial("G4_Fe");
|
||||||
|
iron_cube->Update();
|
||||||
|
scene.AddSolid(iron_cube);
|
||||||
|
|
||||||
|
Geant::EmitterPrimary* emitter = new Geant::EmitterPrimary();
|
||||||
|
emitter->SetPosition(Vector3f(0, 0, 14_m));
|
||||||
|
scene.SetEmitter(emitter);
|
||||||
|
scene.Initialize();
|
||||||
|
|
||||||
|
// 2. Setup VTK Viewer
|
||||||
|
Vtk::Viewer viewer;
|
||||||
|
viewer.GetRenderer()->SetBackground(0.05, 0.05, 0.1);
|
||||||
|
|
||||||
|
// Visualize world box
|
||||||
|
Vtk::vtkContainerBox* vtkWorld = new Vtk::vtkContainerBox(scene.GetWorldBox());
|
||||||
|
vtkWorld->ShowScaleMeasures(true);
|
||||||
|
vtkWorld->SetRepresentation(Vtk::Puppet::Wireframe);
|
||||||
|
vtkWorld->SetSelectable(false);
|
||||||
|
viewer.AddPuppet(*vtkWorld);
|
||||||
|
|
||||||
|
// Visualize iron cube
|
||||||
|
Vtk::vtkContainerBox* vtkIron = new Vtk::vtkContainerBox(&iron_box);
|
||||||
|
vtkIron->SetOpacity(0.2);
|
||||||
|
vtkIron->SetRepresentation(Vtk::Puppet::Surface);
|
||||||
|
viewer.AddPuppet(*vtkIron);
|
||||||
|
|
||||||
|
// Visualize Emitter
|
||||||
|
Vtk::vtkEmitterPrimary* vtkEmitter = new Vtk::vtkEmitterPrimary(*emitter);
|
||||||
|
viewer.AddPuppet(*vtkEmitter);
|
||||||
|
|
||||||
|
// 3. Event Handling
|
||||||
|
AppState state = { &scene, &viewer, {} };
|
||||||
|
|
||||||
|
vtkSmartPointer<vtkCallbackCommand> keyCallback = vtkSmartPointer<vtkCallbackCommand>::New();
|
||||||
|
keyCallback->SetCallback(KeyPressCallbackFunction);
|
||||||
|
keyCallback->SetClientData(&state);
|
||||||
|
|
||||||
|
viewer.GetInteractor()->AddObserver(vtkCommand::KeyPressEvent, keyCallback);
|
||||||
|
|
||||||
|
std::cout << "=================================================" << std::endl;
|
||||||
|
std::cout << " Geant Muon Interactive Emitter Test" << std::endl;
|
||||||
|
std::cout << " Use the Widget to move/rotate the Arrow (Emitter)" << std::endl;
|
||||||
|
std::cout << " Press [ENTER] to fire a muon" << std::endl;
|
||||||
|
std::cout << " Press [q] to exit" << std::endl;
|
||||||
|
std::cout << "=================================================" << std::endl;
|
||||||
|
|
||||||
|
viewer.ZoomAuto();
|
||||||
|
viewer.Start();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
72
src/Vtk/HEP/Geant/vtkEmitterPrimary.cpp
Normal file
72
src/Vtk/HEP/Geant/vtkEmitterPrimary.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#include "vtkEmitterPrimary.h"
|
||||||
|
#include <vtkActor.h>
|
||||||
|
#include <vtkArrowSource.h>
|
||||||
|
#include <vtkMatrix4x4.h>
|
||||||
|
#include <vtkNew.h>
|
||||||
|
#include <vtkPolyDataMapper.h>
|
||||||
|
#include <vtkTransform.h>
|
||||||
|
#include <vtkTransformPolyDataFilter.h>
|
||||||
|
#include "Math/vtkDense.h"
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
namespace Vtk {
|
||||||
|
|
||||||
|
vtkEmitterPrimary::vtkEmitterPrimary(Geant::EmitterPrimary &emitter)
|
||||||
|
: m_emitter(emitter), m_Poly(nullptr), m_Actor(vtkActor::New()) {
|
||||||
|
|
||||||
|
vtkNew<vtkArrowSource> arrow;
|
||||||
|
|
||||||
|
// Default arrow is along X+. Rotate to point towards Z- relative to the origin
|
||||||
|
vtkNew<vtkTransform> transform;
|
||||||
|
transform->RotateY(90.0);
|
||||||
|
|
||||||
|
vtkNew<vtkTransformPolyDataFilter> transformFilter;
|
||||||
|
transformFilter->SetTransform(transform);
|
||||||
|
transformFilter->SetInputConnection(arrow->GetOutputPort());
|
||||||
|
transformFilter->Update();
|
||||||
|
|
||||||
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
||||||
|
mapper->SetInputData(transformFilter->GetOutput());
|
||||||
|
m_Actor->SetMapper(mapper);
|
||||||
|
m_Actor->SetScale(1000.0); // 1 meter long
|
||||||
|
|
||||||
|
vtkNew<vtkMatrix4x4> vmat;
|
||||||
|
Matrix4fToVtk(m_emitter.GetWorldMatrix(), vmat);
|
||||||
|
m_Actor->SetUserMatrix(vmat);
|
||||||
|
|
||||||
|
this->SetProp(m_Actor);
|
||||||
|
|
||||||
|
Object::connect(&m_emitter, &Object::Updated, this, &vtkEmitterPrimary::contentUpdate);
|
||||||
|
this->contentUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkEmitterPrimary::~vtkEmitterPrimary() {
|
||||||
|
Object::disconnect(&m_emitter, &Object::Updated, this, &vtkEmitterPrimary::contentUpdate);
|
||||||
|
m_Actor->Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkEmitterPrimary::contentUpdate() {
|
||||||
|
vtkMatrix4x4 *vmat = m_Actor->GetUserMatrix();
|
||||||
|
if (!vmat) {
|
||||||
|
vtkNew<vtkMatrix4x4> mat;
|
||||||
|
m_Actor->SetUserMatrix(mat);
|
||||||
|
vmat = mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix4f transform = m_emitter.GetWorldMatrix();
|
||||||
|
Matrix4fToVtk(transform, vmat);
|
||||||
|
|
||||||
|
Puppet::Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkEmitterPrimary::Update() {
|
||||||
|
vtkMatrix4x4 *vmat = m_Actor->GetUserMatrix();
|
||||||
|
if (!vmat) return;
|
||||||
|
|
||||||
|
Matrix4f transform = VtkToMatrix4f(vmat);
|
||||||
|
m_emitter.SetMatrix(transform);
|
||||||
|
m_emitter.Updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vtk
|
||||||
|
} // namespace uLib
|
||||||
32
src/Vtk/HEP/Geant/vtkEmitterPrimary.h
Normal file
32
src/Vtk/HEP/Geant/vtkEmitterPrimary.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef VTK_GEANT_EMITTERPRIMARY_H
|
||||||
|
#define VTK_GEANT_EMITTERPRIMARY_H
|
||||||
|
|
||||||
|
#include "Vtk/uLibVtkInterface.h"
|
||||||
|
#include "HEP/Geant/EmitterPrimary.hh"
|
||||||
|
|
||||||
|
class vtkConeSource;
|
||||||
|
class vtkLineSource;
|
||||||
|
class vtkPolyData;
|
||||||
|
class vtkActor;
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
namespace Vtk {
|
||||||
|
|
||||||
|
class vtkEmitterPrimary : public Puppet {
|
||||||
|
public:
|
||||||
|
vtkEmitterPrimary(Geant::EmitterPrimary &emitter);
|
||||||
|
virtual ~vtkEmitterPrimary();
|
||||||
|
|
||||||
|
virtual void contentUpdate();
|
||||||
|
virtual void Update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Geant::EmitterPrimary &m_emitter;
|
||||||
|
vtkPolyData *m_Poly;
|
||||||
|
vtkActor *m_Actor;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vtk
|
||||||
|
} // namespace uLib
|
||||||
|
|
||||||
|
#endif // VTK_GEANT_EMITTERPRIMARY_H
|
||||||
@@ -215,6 +215,7 @@ vtkProp *Puppet::GetProp()
|
|||||||
void Puppet::SetProp(vtkProp *prop)
|
void Puppet::SetProp(vtkProp *prop)
|
||||||
{
|
{
|
||||||
if(prop) {
|
if(prop) {
|
||||||
|
prop->SetPickable(d->m_Selectable);
|
||||||
if (auto* p3d = vtkProp3D::SafeDownCast(prop)) {
|
if (auto* p3d = vtkProp3D::SafeDownCast(prop)) {
|
||||||
d->m_Assembly->AddPart(p3d);
|
d->m_Assembly->AddPart(p3d);
|
||||||
}
|
}
|
||||||
@@ -414,6 +415,11 @@ void Puppet::SetOpacity(double alpha)
|
|||||||
void Puppet::SetSelectable(bool selectable)
|
void Puppet::SetSelectable(bool selectable)
|
||||||
{
|
{
|
||||||
d->m_Selectable = selectable;
|
d->m_Selectable = selectable;
|
||||||
|
vtkProp3DCollection *props = d->m_Assembly->GetParts();
|
||||||
|
props->InitTraversal();
|
||||||
|
for (int i = 0; i < props->GetNumberOfItems(); ++i) {
|
||||||
|
props->GetNextProp3D()->SetPickable(selectable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Puppet::IsSelectable() const
|
bool Puppet::IsSelectable() const
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ vtkHandlerWidget::vtkHandlerWidget() {
|
|||||||
this->m_OverlayRenderer->EraseOff();
|
this->m_OverlayRenderer->EraseOff();
|
||||||
this->m_OverlayRenderer->InteractiveOff();
|
this->m_OverlayRenderer->InteractiveOff();
|
||||||
this->Priority = 50.0; // Higher priority to beat camera style
|
this->Priority = 50.0; // Higher priority to beat camera style
|
||||||
|
this->m_TranslationEnabled = true;
|
||||||
|
this->m_RotationEnabled = true;
|
||||||
|
this->m_ScalingEnabled = true;
|
||||||
this->CreateGizmos();
|
this->CreateGizmos();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +134,8 @@ void vtkHandlerWidget::SetEnabled(int enabling) {
|
|||||||
this->m_OverlayRenderer->AddActor(m_ScaleY);
|
this->m_OverlayRenderer->AddActor(m_ScaleY);
|
||||||
this->m_OverlayRenderer->AddActor(m_ScaleZ);
|
this->m_OverlayRenderer->AddActor(m_ScaleZ);
|
||||||
|
|
||||||
|
this->UpdateVisibility();
|
||||||
|
|
||||||
this->InvokeEvent(::vtkCommand::EnableEvent, nullptr);
|
this->InvokeEvent(::vtkCommand::EnableEvent, nullptr);
|
||||||
} else {
|
} else {
|
||||||
if (!this->Enabled)
|
if (!this->Enabled)
|
||||||
@@ -454,6 +459,63 @@ void vtkHandlerWidget::PlaceWidget(double bounds[6]) {
|
|||||||
this->UpdateGizmoPosition();
|
this->UpdateGizmoPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vtkHandlerWidget::SetTranslationEnabled(bool enabled) {
|
||||||
|
this->m_TranslationEnabled = enabled;
|
||||||
|
this->UpdateVisibility();
|
||||||
|
if (this->Interactor) this->Interactor->Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkHandlerWidget::SetRotationEnabled(bool enabled) {
|
||||||
|
this->m_RotationEnabled = enabled;
|
||||||
|
this->UpdateVisibility();
|
||||||
|
if (this->Interactor) this->Interactor->Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkHandlerWidget::SetScalingEnabled(bool enabled) {
|
||||||
|
this->m_ScalingEnabled = enabled;
|
||||||
|
this->UpdateVisibility();
|
||||||
|
if (this->Interactor) this->Interactor->Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkHandlerWidget::UpdateVisibility() {
|
||||||
|
if (!m_AxesX) return;
|
||||||
|
|
||||||
|
m_AxesX->SetVisibility(m_TranslationEnabled);
|
||||||
|
m_AxesY->SetVisibility(m_TranslationEnabled);
|
||||||
|
m_AxesZ->SetVisibility(m_TranslationEnabled);
|
||||||
|
|
||||||
|
m_RotX->SetVisibility(m_RotationEnabled);
|
||||||
|
m_RotY->SetVisibility(m_RotationEnabled);
|
||||||
|
m_RotZ->SetVisibility(m_RotationEnabled);
|
||||||
|
m_RotCam->SetVisibility(m_RotationEnabled);
|
||||||
|
|
||||||
|
m_ScaleX->SetVisibility(m_ScalingEnabled);
|
||||||
|
m_ScaleY->SetVisibility(m_ScalingEnabled);
|
||||||
|
m_ScaleZ->SetVisibility(m_ScalingEnabled);
|
||||||
|
|
||||||
|
// Update picker list
|
||||||
|
if (m_Picker) {
|
||||||
|
m_Picker->InitializePickList();
|
||||||
|
if (m_TranslationEnabled) {
|
||||||
|
m_Picker->AddPickList(m_AxesX);
|
||||||
|
m_Picker->AddPickList(m_AxesY);
|
||||||
|
m_Picker->AddPickList(m_AxesZ);
|
||||||
|
}
|
||||||
|
if (m_RotationEnabled) {
|
||||||
|
m_Picker->AddPickList(m_RotX);
|
||||||
|
m_Picker->AddPickList(m_RotY);
|
||||||
|
m_Picker->AddPickList(m_RotZ);
|
||||||
|
m_Picker->AddPickList(m_RotCam);
|
||||||
|
}
|
||||||
|
if (m_ScalingEnabled) {
|
||||||
|
m_Picker->AddPickList(m_ScaleX);
|
||||||
|
m_Picker->AddPickList(m_ScaleY);
|
||||||
|
m_Picker->AddPickList(m_ScaleZ);
|
||||||
|
}
|
||||||
|
m_Picker->PickFromListOn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void vtkHandlerWidget::PlaceWidget() { this->UpdateGizmoPosition(); }
|
void vtkHandlerWidget::PlaceWidget() { this->UpdateGizmoPosition(); }
|
||||||
|
|
||||||
void vtkHandlerWidget::SetTransform(::vtkTransform *t) {
|
void vtkHandlerWidget::SetTransform(::vtkTransform *t) {
|
||||||
|
|||||||
@@ -99,14 +99,25 @@ public:
|
|||||||
void GetTransform(::vtkTransform *t);
|
void GetTransform(::vtkTransform *t);
|
||||||
|
|
||||||
::vtkRenderer *GetOverlayRenderer() { return this->m_OverlayRenderer; }
|
::vtkRenderer *GetOverlayRenderer() { return this->m_OverlayRenderer; }
|
||||||
|
|
||||||
|
void SetTranslationEnabled(bool enabled);
|
||||||
|
bool GetTranslationEnabled() const { return m_TranslationEnabled; }
|
||||||
|
void SetRotationEnabled(bool enabled);
|
||||||
|
bool GetRotationEnabled() const { return m_RotationEnabled; }
|
||||||
|
void SetScalingEnabled(bool enabled);
|
||||||
|
bool GetScalingEnabled() const { return m_ScalingEnabled; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void CreateGizmos();
|
void CreateGizmos();
|
||||||
void UpdateGizmoPosition();
|
void UpdateGizmoPosition();
|
||||||
void Highlight(::vtkProp *prop);
|
void Highlight(::vtkProp *prop);
|
||||||
|
void UpdateVisibility();
|
||||||
|
|
||||||
vtkSmartPointer<::vtkRenderer> m_OverlayRenderer;
|
vtkSmartPointer<::vtkRenderer> m_OverlayRenderer;
|
||||||
ReferenceFrame m_Frame;
|
ReferenceFrame m_Frame;
|
||||||
|
bool m_TranslationEnabled;
|
||||||
|
bool m_RotationEnabled;
|
||||||
|
bool m_ScalingEnabled;
|
||||||
|
|
||||||
int Interaction;
|
int Interaction;
|
||||||
::vtkProp *m_HighlightedProp;
|
::vtkProp *m_HighlightedProp;
|
||||||
|
|||||||
@@ -190,38 +190,78 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
|
|||||||
iren->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);
|
iren->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);
|
||||||
|
|
||||||
// Keyboard events for widget coordinate frame
|
// Keyboard events for widget coordinate frame
|
||||||
vtkNew<vtkCallbackCommand> keyCallback;
|
m_KeyCallback = vtkSmartPointer<vtkCallbackCommand>::New();
|
||||||
keyCallback->SetClientData(this);
|
m_KeyCallback->SetClientData(this);
|
||||||
keyCallback->SetCallback([](vtkObject* caller, unsigned long, void* clientdata, void*){
|
m_KeyCallback->SetCallback([](vtkObject* caller, unsigned long event, void* clientdata, void*){
|
||||||
auto* iren = static_cast<vtkRenderWindowInteractor*>(caller);
|
auto* iren = static_cast<vtkRenderWindowInteractor*>(caller);
|
||||||
auto* self = static_cast<Viewport*>(clientdata);
|
auto* self = static_cast<Viewport*>(clientdata);
|
||||||
|
|
||||||
if (!self->m_HandlerWidget || !self->m_HandlerWidget->GetEnabled()) return;
|
|
||||||
|
|
||||||
std::string key = iren->GetKeySym();
|
std::string key = iren->GetKeySym();
|
||||||
if (key == "l") {
|
bool handled = false;
|
||||||
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::LOCAL);
|
|
||||||
std::cout << "Widget Frame: LOCAL" << std::endl;
|
if (self->m_HandlerWidget && self->m_HandlerWidget->GetEnabled()) {
|
||||||
|
if (key == "l") {
|
||||||
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
|
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::LOCAL);
|
||||||
|
std::cout << "Widget Frame: LOCAL" << std::endl;
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (key == "g") {
|
||||||
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
|
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::GLOBAL);
|
||||||
|
std::cout << "Widget Frame: GLOBAL" << std::endl;
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (key == "c") {
|
||||||
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
|
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::CENTER);
|
||||||
|
std::cout << "Widget Frame: CENTER" << std::endl;
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (key == "k") {
|
||||||
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
|
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::CENTER_LOCAL);
|
||||||
|
std::cout << "Widget Frame: CENTER_LOCAL" << std::endl;
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (key == "1") {
|
||||||
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
|
self->m_HandlerWidget->SetTranslationEnabled(!self->m_HandlerWidget->GetTranslationEnabled());
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (key == "2") {
|
||||||
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
|
self->m_HandlerWidget->SetRotationEnabled(!self->m_HandlerWidget->GetRotationEnabled());
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
else if (key == "3") {
|
||||||
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
|
self->m_HandlerWidget->SetScalingEnabled(!self->m_HandlerWidget->GetScalingEnabled());
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (key == "g") {
|
|
||||||
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::GLOBAL);
|
if (key == "f") {
|
||||||
std::cout << "Widget Frame: GLOBAL" << std::endl;
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
|
self->ZoomSelected();
|
||||||
|
}
|
||||||
|
handled = true;
|
||||||
}
|
}
|
||||||
else if (key == "c") {
|
|
||||||
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::CENTER);
|
if (handled) {
|
||||||
std::cout << "Widget Frame: CENTER" << std::endl;
|
self->m_KeyCallback->SetAbortFlag(1);
|
||||||
|
iren->Render();
|
||||||
}
|
}
|
||||||
else if (key == "k") {
|
|
||||||
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::CENTER_LOCAL);
|
|
||||||
std::cout << "Widget Frame: CENTER_LOCAL" << std::endl;
|
|
||||||
}
|
|
||||||
else if (key == "s") {
|
|
||||||
self->ZoomSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
iren->Render();
|
|
||||||
});
|
});
|
||||||
iren->AddObserver(vtkCommand::KeyPressEvent, keyCallback);
|
iren->AddObserver(vtkCommand::KeyPressEvent, m_KeyCallback, 1.0);
|
||||||
|
iren->AddObserver(vtkCommand::CharEvent, m_KeyCallback, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewport::Reset()
|
void Viewport::Reset()
|
||||||
@@ -262,14 +302,18 @@ void Viewport::ZoomSelected()
|
|||||||
|
|
||||||
if (bounds[0] > bounds[1]) return; // Invalid bounds
|
if (bounds[0] > bounds[1]) return; // Invalid bounds
|
||||||
|
|
||||||
// Expand bounds by 1.5 from center
|
// Expand bounds by a factor from center (e.g. 2.0 to have some margin)
|
||||||
double center[3] = {(bounds[0] + bounds[1]) / 2.0, (bounds[2] + bounds[3]) / 2.0, (bounds[4] + bounds[5]) / 2.0};
|
double center[3] = {(bounds[0] + bounds[1]) / 2.0, (bounds[2] + bounds[3]) / 2.0, (bounds[4] + bounds[5]) / 2.0};
|
||||||
double h_ext[3] = {(bounds[1] - bounds[0]) / 2.0, (bounds[3] - bounds[2]) / 2.0, (bounds[5] - bounds[4]) / 2.0};
|
double h_ext[3] = {(bounds[1] - bounds[0]) / 2.0, (bounds[3] - bounds[2]) / 2.0, (bounds[5] - bounds[4]) / 2.0};
|
||||||
|
|
||||||
|
// Ensure a minimum size to avoid camera issues with flat/point objects
|
||||||
|
double max_h = std::max({h_ext[0], h_ext[1], h_ext[2], 0.1});
|
||||||
|
|
||||||
double newBounds[6];
|
double newBounds[6];
|
||||||
for (int i=0; i<3; ++i) {
|
for (int i=0; i<3; ++i) {
|
||||||
newBounds[2*i] = center[i] - 1.5 * h_ext[i];
|
double current_h = std::max(h_ext[i], max_h * 0.1);
|
||||||
newBounds[2*i+1] = center[i] + 1.5 * h_ext[i];
|
newBounds[2*i] = center[i] - 2.5 * current_h;
|
||||||
|
newBounds[2*i+1] = center[i] + 2.5 * current_h;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Renderer->ResetCamera(newBounds);
|
m_Renderer->ResetCamera(newBounds);
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ protected:
|
|||||||
vtkSmartPointer<vtkHandlerWidget> m_HandlerWidget;
|
vtkSmartPointer<vtkHandlerWidget> m_HandlerWidget;
|
||||||
std::vector<Puppet*> m_Puppets;
|
std::vector<Puppet*> m_Puppets;
|
||||||
vtkSmartPointer<vtkCellPicker> m_Picker;
|
vtkSmartPointer<vtkCellPicker> m_Picker;
|
||||||
|
vtkSmartPointer<vtkCallbackCommand> m_KeyCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vtk
|
} // namespace Vtk
|
||||||
|
|||||||
Reference in New Issue
Block a user