From 453e8344d918a69981175fe1aefee2b0fbbfa6c4 Mon Sep 17 00:00:00 2001
From: Ben Couturier <ben.couturier@cern.ch>
Date: Fri, 18 Sep 2020 17:48:47 +0200
Subject: [PATCH] Added geoWebDisplay command that uses jsroot to render the
 Geometry

---
 DDCore/CMakeLists.txt                  |  2 +-
 DDCore/src/plugins/StandardPlugins.cpp | 62 ++++++++++++++++++++++++++
 UtilityApps/CMakeLists.txt             |  4 ++
 UtilityApps/src/webdisplay.cpp         | 42 +++++++++++++++++
 4 files changed, 109 insertions(+), 1 deletion(-)
 create mode 100644 UtilityApps/src/webdisplay.cpp

diff --git a/DDCore/CMakeLists.txt b/DDCore/CMakeLists.txt
index 482cff231..405c39dd6 100644
--- a/DDCore/CMakeLists.txt
+++ b/DDCore/CMakeLists.txt
@@ -89,7 +89,7 @@ target_include_directories(DDCore
 target_link_libraries(DDCore
   PUBLIC
   DD4hep::DDParsers
-  ROOT::Core ROOT::Rint ROOT::Tree ROOT::Physics ROOT::Geom ROOT::GenVector
+  ROOT::Core ROOT::Rint ROOT::Tree ROOT::Physics ROOT::Geom ROOT::GenVector ROOT::ROOTEve
   ${XML_LIBRARIES} ${CMAKE_DL_LIBS}
   )
 
diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp
index 0dc88e0ca..39fcd6c46 100644
--- a/DDCore/src/plugins/StandardPlugins.cpp
+++ b/DDCore/src/plugins/StandardPlugins.cpp
@@ -40,6 +40,9 @@
 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,17,0)
 #include <TGDMLMatrix.h>
 #endif
+#include "ROOT/RDirectory.hxx"
+#include "ROOT/REveGeomViewer.hxx"
+
 
 // C/C++ include files
 #include <cerrno>
@@ -164,6 +167,65 @@ static long display(Detector& description, int argc, char** argv) {
 }
 DECLARE_APPLY(DD4hep_GeometryDisplay,display)
 
+/// Basic entry point to display the currently loaded geometry using the ROOT7 jsroot viewer
+/**
+ *  Factory: DD4hep_GeometryWebDisplay
+ *
+ */
+static long webdisplay(Detector& description, int argc, char** argv) {
+  TGeoManager& mgr = description.manager();
+  int vislevel = 6, visopt = 1;
+  string detector = "/world";
+  const char* opt = "ogl";
+  for(int i = 0; i < argc && argv[i]; ++i)  {
+    if ( 0 == ::strncmp("-option",argv[i],4) )
+      opt = argv[++i];
+    else if ( 0 == ::strncmp("-level",argv[i],4) )
+      vislevel = ::atol(argv[++i]);
+    else if ( 0 == ::strncmp("-visopt",argv[i],4) )
+      visopt = ::atol(argv[++i]);
+    else if ( 0 == ::strncmp("-detector",argv[i],4) )
+      detector = argv[++i];
+    else  {
+      cout <<
+        "Usage: -plugin <name> -arg [-arg]                                                   \n"
+        "     -detector <string> Top level DetElement path. Default: '/world'                \n"
+        "     -option   <string> ROOT Draw option.    Default: 'ogl'                         \n"
+        "     -level    <number> Visualization level  [TGeoManager::SetVisLevel]  Default: 4 \n"
+        "     -visopt   <number> Visualization option [TGeoManager::SetVisOption] Default: 1 \n"       
+        "\tArguments given: " << arguments(argc,argv) << endl << flush;
+      ::exit(EINVAL);
+    }
+  }
+  mgr.SetVisLevel(vislevel);
+  mgr.SetVisOption(visopt);
+  TGeoVolume* vol = mgr.GetTopVolume();
+  if ( detector != "/world" )   {
+    DetElement elt = detail::tools::findElement(description,detector);
+    if ( !elt.isValid() )  {
+      except("DD4hep_GeometryWebDisplay","+++ Invalid DetElement path: %s",detector.c_str());
+    }
+    if ( !elt.placement().isValid() )   {
+      except("DD4hep_GeometryWebDisplay","+++ Invalid DetElement placement: %s",detector.c_str());
+    }
+    vol = elt.placement().volume();
+  }
+
+  if (vol) {
+    auto viewer = std::make_shared<ROOT::Experimental::REveGeomViewer>(&mgr);
+    viewer->SelectVolume(vol->GetName());
+    viewer->SetLimits();
+    viewer->SetDrawOptions(opt);
+    viewer->Show();
+    // add to global heap to avoid immediate destroy of RGeomViewer
+    ROOT::Experimental::RDirectory::Heap().Add( "geom_viewer", viewer );
+    return 1;
+  }
+  return 0;
+}
+DECLARE_APPLY(DD4hep_GeometryWebDisplay,webdisplay)
+
+
 /// Basic entry point to execute a public function from a library
 /**
  *  Factory: DD4hep_Function
diff --git a/UtilityApps/CMakeLists.txt b/UtilityApps/CMakeLists.txt
index b01c90e64..6fcdac99f 100644
--- a/UtilityApps/CMakeLists.txt
+++ b/UtilityApps/CMakeLists.txt
@@ -13,6 +13,9 @@ SET_PROPERTY(DIRECTORY . PROPERTY PACKAGE_NAME UtilityApps)
 add_executable(geoDisplay src/display.cpp)
 target_link_libraries(geoDisplay DD4hep::DDCore)
 #-----------------------------------------------------------------------------------
+add_executable(geoWebDisplay src/webdisplay.cpp)
+target_link_libraries(geoWebDisplay DD4hep::DDCore)
+#-----------------------------------------------------------------------------------
 add_executable(geoConverter src/converter.cpp)
 target_link_libraries(geoConverter DD4hep::DDCore)
 #-----------------------------------------------------------------------------------
@@ -78,6 +81,7 @@ add_executable(teveDisplay src/teve_display.cpp src/next_event_dummy.cpp G__eve.
 target_link_libraries(teveDisplay DD4hep::DDRec ROOT::Core ROOT::Eve ROOT::Gui ROOT::Graf3d ROOT::RGL )
 
 INSTALL(TARGETS geoDisplay
+  geoWebDisplay
   geoConverter
   geoPluginRun
   dumpBfield
diff --git a/UtilityApps/src/webdisplay.cpp b/UtilityApps/src/webdisplay.cpp
new file mode 100644
index 000000000..2e751cd81
--- /dev/null
+++ b/UtilityApps/src/webdisplay.cpp
@@ -0,0 +1,42 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+// Framework include files
+#include "run_plugin.h"
+
+//______________________________________________________________________________
+int main(int argc,char** argv)  {
+  std::vector<const char*> av;
+  std::string level, visopt, opt, detector;
+  bool dry = false;
+  for(int i=0; i<argc; ++i)  {
+    if ( i==1 && argv[i][0] != '-' ) av.emplace_back("-input");
+    if      ( strncmp(argv[i],"-load-only",4) == 0 ) dry = true, av.emplace_back(argv[i]);
+    else if ( strncmp(argv[i],"-dry-run",4)   == 0 ) dry = true, av.emplace_back(argv[i]);
+    else if ( strncmp(argv[i],"-visopt",4)    == 0 ) visopt   = argv[++i];
+    else if ( strncmp(argv[i],"-level", 4)    == 0 ) level    = argv[++i];
+    else if ( strncmp(argv[i],"-option",4)    == 0 ) opt      = argv[++i];
+    else if ( strncmp(argv[i],"-detector",4)  == 0 ) detector = argv[++i];
+    else av.emplace_back(argv[i]);
+  }
+  if ( !dry )   {
+    av.emplace_back("-interactive");
+    av.emplace_back("-plugin");
+    av.emplace_back("DD4hep_GeometryWebDisplay");
+    if ( !opt.empty()      ) av.emplace_back("-opt"),      av.emplace_back(opt.c_str());
+    if ( !level.empty()    ) av.emplace_back("-level"),    av.emplace_back(level.c_str());
+    if ( !visopt.empty()   ) av.emplace_back("-visopt"),   av.emplace_back(visopt.c_str());
+    if ( !detector.empty() ) av.emplace_back("-detector"), av.emplace_back(detector.c_str());
+  }
+  return dd4hep::execute::main_plugins("DD4hep_GeometryWebDisplay", av.size(), (char**)&av[0]);
+}
-- 
GitLab