From 2ce75be5032c36661846cf180c9abeb7312eb8f8 Mon Sep 17 00:00:00 2001 From: Markus Frank Date: Mon, 9 Oct 2023 16:28:57 +0200 Subject: [PATCH] Allow to load CAD files with relative path w/r to declaring xml file (Issue 1166) --- DDCAD/src/plugins/CADPlugins.cpp | 31 +++++++++++++++++-- examples/DDCAD/CMakeLists.txt | 2 +- .../compact/Check_Shape_RelativePath.xml | 30 ++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 examples/DDCAD/compact/Check_Shape_RelativePath.xml diff --git a/DDCAD/src/plugins/CADPlugins.cpp b/DDCAD/src/plugins/CADPlugins.cpp index 8a646ebe9..17f9c037a 100644 --- a/DDCAD/src/plugins/CADPlugins.cpp +++ b/DDCAD/src/plugins/CADPlugins.cpp @@ -20,11 +20,36 @@ #include // C/C++ include files +#include using namespace std; using namespace dd4hep; using namespace dd4hep::detail; +/// If the path to the CAD file does not directly exist try to resolve it: +static string resolve_path(xml_h e, const string& file) { + error_code errc; + std::string fname; + /// Use the xml utilities in the DocumentHandler to resolve the relative path + if ( file.length() > 7 && file.substr(0,7) == "file://" ) + fname = file.substr(7); + else + fname = file; + if ( !filesystem::exists(fname, errc) ) { + string fn = xml::DocumentHandler::system_path(e, fname); + if ( fn.length() > 7 && fn.substr(0,7) == "file://" ) + fn = fn.substr(7); + if ( !std::filesystem::exists(fn, errc) ) { + auto fp = filesystem::path(xml::DocumentHandler::system_path(e)).parent_path(); + except("CAD_Shape","+++ CAD file: %s (= %s + %s) is not accessible [%d: %s]", + fn.c_str(), fp.c_str(), fname.c_str(), + errc.value(), errc.message().c_str()); + } + return fn; + } + return fname; +} + static void* read_CAD_Volume(Detector& dsc, int argc, char** argv) { string fname; double scale = 1.0; @@ -61,7 +86,7 @@ DECLARE_DD4HEP_CONSTRUCTOR(DD4hep_read_CAD_volumes,read_CAD_Volume) static Handle create_CAD_Shape(Detector& dsc, xml_h e) { xml_elt_t elt(e); cad::ASSIMPReader rdr(dsc); - string fname = elt.attr(_U(ref)); + string fname = resolve_path(e, elt.attr(_U(ref))); long flags = elt.hasAttr(_U(flags)) ? elt.attr(_U(flags)) : 0; double unit = elt.hasAttr(_U(unit)) ? elt.attr(_U(unit)) : dd4hep::cm; @@ -97,7 +122,7 @@ DECLARE_XML_SHAPE(CAD_Shape__shape_constructor,create_CAD_Shape) static Handle create_CAD_Assembly(Detector& dsc, xml_h e) { xml_elt_t elt(e); - string fname = elt.attr(_U(ref)); + string fname = resolve_path(e, elt.attr(_U(ref))); double unit = elt.hasAttr(_U(unit)) ? elt.attr(_U(unit)) : dd4hep::cm; auto volumes = cad::ASSIMPReader(dsc).readVolumes(fname, unit); if ( volumes.empty() ) { @@ -159,8 +184,8 @@ DECLARE_XML_VOLUME(CAD_Assembly__volume_constructor,create_CAD_Assembly) */ static Handle create_CAD_Volume(Detector& dsc, xml_h e) { xml_elt_t elt(e); - string fname = elt.attr(_U(ref)); double unit = elt.attr(_U(unit)); + string fname = resolve_path(e, elt.attr(_U(ref))); long flags = elt.hasAttr(_U(flags)) ? elt.attr(_U(flags)) : 0; cad::ASSIMPReader rdr(dsc); diff --git a/examples/DDCAD/CMakeLists.txt b/examples/DDCAD/CMakeLists.txt index 91f2d8a2f..0d9e38ec7 100644 --- a/examples/DDCAD/CMakeLists.txt +++ b/examples/DDCAD/CMakeLists.txt @@ -72,7 +72,7 @@ endforeach() # # Multi-shape tests # Not working: OBJ_spider -list(APPEND DDCAD_Tests_MV COB_dwarf MS3D_jeep) +list(APPEND DDCAD_Tests_MV COB_dwarf MS3D_jeep RelativePath) foreach (test ${DDCAD_Tests_MV}) dd4hep_add_test_reg( DDCAD_Check_Shape_${test} COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_DDCAD.sh" diff --git a/examples/DDCAD/compact/Check_Shape_RelativePath.xml b/examples/DDCAD/compact/Check_Shape_RelativePath.xml new file mode 100644 index 000000000..39b1627b2 --- /dev/null +++ b/examples/DDCAD/compact/Check_Shape_RelativePath.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + +