/*////////////////////////////////////////////////////////////////////////////// // CMT Cosmic Muon Tomography project ////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova All rights reserved Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > ------------------------------------------------------------------ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. //////////////////////////////////////////////////////////////////////////////*/ #include "Vtk/HEP/Detectors/vtkDetectorChamber.h" #include "Vtk/HEP/Detectors/vtkMuonScatter.h" #include "Math/Units.h" #include "Vtk/HEP/Detectors/vtkDetectorChamber.h" #include "Vtk/HEP/Detectors/vtkMuonScatter.h" #include "Vtk/uLibVtkViewer.h" #include #include #include #include #include #include #define BOOST_TEST_MODULE vtkDetectorMuonProjectionTest #include using namespace uLib; // A simple prop3d class to represent an arrow indicative of a projected muon hit class vtkArrowProp3D : public Vtk::Prop3D { public: vtkArrowProp3D() : m_Actor(vtkActor::New()) { vtkNew arrow; vtkNew mapper; mapper->SetInputConnection(arrow->GetOutputPort()); m_Actor->SetMapper(mapper); this->SetProp(m_Actor); m_Actor->GetProperty()->SetColor(1, 1, 0); // Yellow color for visibility } virtual ~vtkArrowProp3D() { m_Actor->Delete(); } void SetProjection(const HLine3f &line) { HPoint3f p = line.origin; HVector3f d = line.direction; d.normalize(); vtkNew t; t->Translate(p.x(), p.y(), p.z()); // vtkArrowSource initially points along X+ (1, 0, 0) double vtk_x[3] = {1, 0, 0}; double vtk_d[3] = {d.x(), d.y(), d.z()}; double axis[3]; vtkMath::Cross(vtk_x, vtk_d, axis); double dot = vtkMath::Dot(vtk_x, vtk_d); double angle = vtkMath::DegreesFromRadians(acos(dot)); // Handle parallel or anti-parallel cases if (vtkMath::Norm(axis) < 1e-6) { if (dot < 0) { t->RotateY(180); // Reverse direction if anti-parallel } } else { t->RotateWXYZ(angle, axis); } t->Scale(100, 100, 100); // Scale the arrow for visual prominence m_Actor->SetUserTransform(t); } private: vtkActor *m_Actor; }; BOOST_AUTO_TEST_CASE(vtkDetectorMuonProjectionTest) { using namespace uLib::literals; // 1. Prepare a scene with two detector chambers DetectorChamber d1, d2; d1.Scale(Vector3f(1_m, 1_m, 10_cm)); d1.Translate(Vector3f(0, 0, -0.5_m)); d2.Scale(Vector3f(1_m, 1_m, 10_cm)); d2.Translate(Vector3f(0, 0, 0.5_m)); // 2. Setup a muon event that crosses the detectors MuonScatter event; // Set an origin slightly offset and point it toward (0,0,0) HPoint3f mu_origin(20_cm, 30_cm, -1_m); event.LineIn().origin = mu_origin; // Direction is toward (0,0,0) HVector3f mu_dir = (HPoint3f(0,0,0) - mu_origin); mu_dir.normalize(); event.LineIn().direction = mu_dir; // Let's make the track continue straight for a simple projection test event.LineOut().origin = mu_origin - mu_dir * 3_m; event.LineOut().direction = -mu_dir; MuonEvent mu_event; mu_event.LineIn() = event.LineIn(); mu_event.LineOut() = event.LineOut(); // 3. Project the muon on each detector to find the projection points MuonEvent mu_proj1 = d1.ProjectMuonEvent(mu_event); MuonEvent mu_proj2 = d2.ProjectMuonEvent(mu_event); Vtk::DetectorChamber v_d1(&d1); Vtk::DetectorChamber v_d2(&d2); Vtk::MuonScatter v_event(event); v_event.AddPocaPoint(HPoint3f(0, 0, 0)); v_event.SetColor(1, 0, 0); // Red muon event v_d1.SetRepresentation(Vtk::Prop3D::Surface); v_d1.SetOpacity(0.3); v_d2.SetRepresentation(Vtk::Prop3D::Surface); v_d2.SetOpacity(0.3); // 5. Add two arrows to mark where the projection is located on the chambers vtkArrowProp3D v_p1, v_p2; v_p1.SetProjection(mu_proj1.LineIn()); v_p2.SetProjection(mu_proj2.LineIn()); if (std::getenv("CTEST_PROJECT_NAME") == nullptr) { Vtk::Viewer viewer; viewer.SetGridAxis(Vtk::Viewport::Z); viewer.AddProp3D(v_d1); viewer.AddProp3D(v_d2); viewer.AddProp3D(v_event); viewer.AddProp3D(v_p1); viewer.AddProp3D(v_p2); viewer.Start(); } BOOST_CHECK(true); }