Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // G4GDMLWrite implementation 27 // 28 // Author: Zoltan Torzsok, November 2007 29 // -------------------------------------------------------------------- 30 31 #include <sys/stat.h> 32 #include <iostream> 33 34 #include "G4GDMLWrite.hh" 35 36 #include "G4LogicalVolume.hh" 37 #include "G4Transform3D.hh" 38 #include "G4PVDivision.hh" 39 40 G4bool G4GDMLWrite::addPointerToName = true; 41 42 // -------------------------------------------------------------------- 43 G4GDMLWrite::G4GDMLWrite() 44 { 45 } 46 47 // -------------------------------------------------------------------- 48 G4GDMLWrite::~G4GDMLWrite() 49 { 50 } 51 52 // -------------------------------------------------------------------- 53 G4bool G4GDMLWrite::FileExists(const G4String& fname) const 54 { 55 struct stat FileInfo; 56 return (stat(fname.c_str(), &FileInfo) == 0); 57 } 58 59 // -------------------------------------------------------------------- 60 G4GDMLWrite::VolumeMapType& G4GDMLWrite::VolumeMap() 61 { 62 static VolumeMapType instance; 63 return instance; 64 } 65 66 G4GDMLWrite::PhysVolumeMapType& G4GDMLWrite::PvolumeMap() 67 { 68 static PhysVolumeMapType instance; 69 return instance; 70 } 71 72 // -------------------------------------------------------------------- 73 G4GDMLWrite::DepthMapType& G4GDMLWrite::DepthMap() 74 { 75 static DepthMapType instance; 76 return instance; 77 } 78 79 // -------------------------------------------------------------------- 80 void G4GDMLWrite::AddExtension(xercesc::DOMElement*, 81 const G4LogicalVolume* const) 82 { 83 // Empty implementation. To be overwritten by user for specific extensions 84 // related to attributes associated to volumes 85 } 86 87 // -------------------------------------------------------------------- 88 void G4GDMLWrite::ExtensionWrite(xercesc::DOMElement*) 89 { 90 // Empty implementation. To be overwritten by user for specific extensions 91 } 92 93 // -------------------------------------------------------------------- 94 void G4GDMLWrite::AddAuxInfo(G4GDMLAuxListType* auxInfoList, 95 xercesc::DOMElement* element) 96 { 97 for(auto iaux = auxInfoList->cbegin(); iaux != auxInfoList->cend(); ++iaux) 98 { 99 xercesc::DOMElement* auxiliaryElement = NewElement("auxiliary"); 100 element->appendChild(auxiliaryElement); 101 102 auxiliaryElement->setAttributeNode(NewAttribute("auxtype", (*iaux).type)); 103 auxiliaryElement->setAttributeNode(NewAttribute("auxvalue", (*iaux).value)); 104 if(((*iaux).unit) != "") 105 { 106 auxiliaryElement->setAttributeNode(NewAttribute("auxunit", (*iaux).unit)); 107 } 108 109 if(iaux->auxList) 110 { 111 AddAuxInfo(iaux->auxList, auxiliaryElement); 112 } 113 } 114 return; 115 } 116 117 // -------------------------------------------------------------------- 118 void G4GDMLWrite::UserinfoWrite(xercesc::DOMElement* gdmlElement) 119 { 120 if(auxList.size() > 0) 121 { 122 #ifdef G4VERBOSE 123 G4cout << "G4GDML: Writing userinfo..." << G4endl; 124 #endif 125 userinfoElement = NewElement("userinfo"); 126 gdmlElement->appendChild(userinfoElement); 127 AddAuxInfo(&auxList, userinfoElement); 128 } 129 } 130 131 // -------------------------------------------------------------------- 132 G4String G4GDMLWrite::GenerateName(const G4String& name, const void* const ptr) 133 { 134 G4String nameOut; 135 std::stringstream stream; 136 stream << name; 137 if(addPointerToName) 138 { 139 stream << ptr; 140 }; 141 142 nameOut = G4String(stream.str()); 143 std::vector<char> toremove = { ' ', '/', ':', '#', '+' }; 144 for(auto c : toremove) 145 { 146 if(G4StrUtil::contains(nameOut, c)) 147 { 148 std::replace(nameOut.begin(), nameOut.end(), c, '_'); 149 } 150 } 151 return nameOut; 152 } 153 154 // -------------------------------------------------------------------- 155 xercesc::DOMAttr* G4GDMLWrite::NewAttribute(const G4String& name, 156 const G4String& value) 157 { 158 XMLCh* tempStr = NULL; 159 tempStr = xercesc::XMLString::transcode(name); 160 xercesc::DOMAttr* att = doc->createAttribute(tempStr); 161 xercesc::XMLString::release(&tempStr); 162 163 tempStr = xercesc::XMLString::transcode(value); 164 att->setValue(tempStr); 165 xercesc::XMLString::release(&tempStr); 166 167 return att; 168 } 169 170 // -------------------------------------------------------------------- 171 xercesc::DOMAttr* G4GDMLWrite::NewAttribute(const G4String& name, 172 const G4double& value) 173 { 174 XMLCh* tempStr = NULL; 175 tempStr = xercesc::XMLString::transcode(name); 176 xercesc::DOMAttr* att = doc->createAttribute(tempStr); 177 xercesc::XMLString::release(&tempStr); 178 179 std::ostringstream ostream; 180 ostream.precision(15); 181 ostream << value; 182 G4String str = ostream.str(); 183 184 tempStr = xercesc::XMLString::transcode(str); 185 att->setValue(tempStr); 186 xercesc::XMLString::release(&tempStr); 187 188 return att; 189 } 190 191 // -------------------------------------------------------------------- 192 xercesc::DOMElement* G4GDMLWrite::NewElement(const G4String& name) 193 { 194 XMLCh* tempStr = NULL; 195 tempStr = xercesc::XMLString::transcode(name); 196 xercesc::DOMElement* elem = doc->createElement(tempStr); 197 xercesc::XMLString::release(&tempStr); 198 199 return elem; 200 } 201 202 // -------------------------------------------------------------------- 203 G4Transform3D G4GDMLWrite::Write(const G4String& fname, 204 const G4LogicalVolume* const logvol, 205 const G4String& setSchemaLocation, 206 const G4int depth, G4bool refs) 207 { 208 SchemaLocation = setSchemaLocation; 209 addPointerToName = refs; 210 #ifdef G4VERBOSE 211 if(depth == 0) 212 { 213 G4cout << "G4GDML: Writing '" << fname << "'..." << G4endl; 214 } 215 else 216 { 217 G4cout << "G4GDML: Writing module '" << fname << "'..." << G4endl; 218 } 219 #endif 220 if(!overwriteOutputFile && FileExists(fname)) 221 { 222 G4String ErrorMessage = "File '" + fname + "' already exists!"; 223 G4Exception("G4GDMLWrite::Write()", "InvalidSetup", FatalException, 224 ErrorMessage); 225 } 226 227 VolumeMap().clear(); // The module map is global for all modules, 228 // so clear it only at once! 229 230 XMLCh* tempStr = NULL; 231 tempStr = xercesc::XMLString::transcode("LS"); 232 xercesc::DOMImplementationRegistry::getDOMImplementation(tempStr); 233 xercesc::XMLString::release(&tempStr); 234 tempStr = xercesc::XMLString::transcode("Range"); 235 xercesc::DOMImplementation* impl = 236 xercesc::DOMImplementationRegistry::getDOMImplementation(tempStr); 237 xercesc::XMLString::release(&tempStr); 238 tempStr = xercesc::XMLString::transcode("gdml"); 239 doc = impl->createDocument(0, tempStr, 0); 240 xercesc::XMLString::release(&tempStr); 241 xercesc::DOMElement* gdml = doc->getDocumentElement(); 242 243 #if XERCES_VERSION_MAJOR >= 3 244 // DOM L3 as per Xerces 3.0 API 245 xercesc::DOMLSSerializer* writer = 246 ((xercesc::DOMImplementationLS*) impl)->createLSSerializer(); 247 248 xercesc::DOMConfiguration* dc = writer->getDomConfig(); 249 dc->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true); 250 251 #else 252 253 xercesc::DOMWriter* writer = 254 ((xercesc::DOMImplementationLS*) impl)->createDOMWriter(); 255 256 if(writer->canSetFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true)) 257 writer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true); 258 259 #endif 260 261 gdml->setAttributeNode( 262 NewAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")); 263 gdml->setAttributeNode( 264 NewAttribute("xsi:noNamespaceSchemaLocation", SchemaLocation)); 265 266 ExtensionWrite(gdml); 267 DefineWrite(gdml); 268 MaterialsWrite(gdml); 269 SolidsWrite(gdml); 270 StructureWrite(gdml); 271 UserinfoWrite(gdml); 272 SetupWrite(gdml, logvol); 273 274 G4Transform3D R = TraverseVolumeTree(logvol, depth); 275 276 SurfacesWrite(); 277 xercesc::XMLFormatTarget* myFormTarget = 278 new xercesc::LocalFileFormatTarget(fname.c_str()); 279 280 try 281 { 282 #if XERCES_VERSION_MAJOR >= 3 283 // DOM L3 as per Xerces 3.0 API 284 xercesc::DOMLSOutput* theOutput = 285 ((xercesc::DOMImplementationLS*) impl)->createLSOutput(); 286 theOutput->setByteStream(myFormTarget); 287 writer->write(doc, theOutput); 288 #else 289 writer->writeNode(myFormTarget, *doc); 290 #endif 291 } catch(const xercesc::XMLException& toCatch) 292 { 293 char* message = xercesc::XMLString::transcode(toCatch.getMessage()); 294 G4cout << "G4GDML: Exception message is: " << message << G4endl; 295 xercesc::XMLString::release(&message); 296 return G4Transform3D::Identity; 297 } catch(const xercesc::DOMException& toCatch) 298 { 299 char* message = xercesc::XMLString::transcode(toCatch.msg); 300 G4cout << "G4GDML: Exception message is: " << message << G4endl; 301 xercesc::XMLString::release(&message); 302 return G4Transform3D::Identity; 303 } catch(...) 304 { 305 G4cout << "G4GDML: Unexpected Exception!" << G4endl; 306 return G4Transform3D::Identity; 307 } 308 309 delete myFormTarget; 310 writer->release(); 311 312 if(depth == 0) 313 { 314 G4cout << "G4GDML: Writing '" << fname << "' done !" << G4endl; 315 } 316 else 317 { 318 #ifdef G4VERBOSE 319 G4cout << "G4GDML: Writing module '" << fname << "' done !" << G4endl; 320 #endif 321 } 322 323 return R; 324 } 325 326 // -------------------------------------------------------------------- 327 void G4GDMLWrite::AddModule(const G4VPhysicalVolume* const physvol) 328 { 329 G4String fname = GenerateName(physvol->GetName(), physvol); 330 G4cout << "G4GDML: Adding module '" << fname << "'..." << G4endl; 331 332 if(physvol == nullptr) 333 { 334 G4Exception("G4GDMLWrite::AddModule()", "InvalidSetup", FatalException, 335 "Invalid NULL pointer is specified for modularization!"); 336 return; 337 } 338 if(dynamic_cast<const G4PVDivision*>(physvol)) 339 { 340 G4Exception("G4GDMLWrite::AddModule()", "InvalidSetup", FatalException, 341 "It is not possible to modularize by divisionvol!"); 342 return; 343 } 344 if(physvol->IsParameterised()) 345 { 346 G4Exception("G4GDMLWrite::AddModule()", "InvalidSetup", FatalException, 347 "It is not possible to modularize by parameterised volume!"); 348 return; 349 } 350 if(physvol->IsReplicated()) 351 { 352 G4Exception("G4GDMLWrite::AddModule()", "InvalidSetup", FatalException, 353 "It is not possible to modularize by replicated volume!"); 354 return; 355 } 356 357 PvolumeMap()[physvol] = fname; 358 } 359 360 // -------------------------------------------------------------------- 361 void G4GDMLWrite::AddModule(const G4int depth) 362 { 363 if(depth < 0) 364 { 365 G4Exception("G4GDMLWrite::AddModule()", "InvalidSetup", FatalException, 366 "Depth must be a positive number!"); 367 } 368 if(DepthMap().find(depth) != DepthMap().end()) 369 { 370 G4Exception("G4GDMLWrite::AddModule()", "InvalidSetup", FatalException, 371 "Adding module(s) at this depth is already requested!"); 372 } 373 DepthMap()[depth] = 0; 374 } 375 376 // -------------------------------------------------------------------- 377 G4String G4GDMLWrite::Modularize(const G4VPhysicalVolume* const physvol, 378 const G4int depth) 379 { 380 if(PvolumeMap().find(physvol) != PvolumeMap().cend()) 381 { 382 return PvolumeMap()[physvol]; // Modularize via physvol 383 } 384 385 if(DepthMap().find(depth) != DepthMap().cend()) // Modularize via depth 386 { 387 std::stringstream stream; 388 stream << "depth" << depth << "_module" << DepthMap()[depth] << ".gdml"; 389 DepthMap()[depth]++; // There can be more modules at this depth! 390 return G4String(stream.str()); 391 } 392 393 return G4String(""); // Empty string for module name = no modularization 394 // was requested at that level/physvol! 395 } 396 397 // -------------------------------------------------------------------- 398 void G4GDMLWrite::AddAuxiliary(G4GDMLAuxStructType myaux) 399 { 400 auxList.push_back(myaux); 401 } 402 403 // -------------------------------------------------------------------- 404 void G4GDMLWrite::SetOutputFileOverwrite(G4bool flag) 405 { 406 overwriteOutputFile = flag; 407 } 408 409 // -------------------------------------------------------------------- 410 void G4GDMLWrite::SetAddPointerToName(G4bool set) 411 { 412 addPointerToName = set; 413 } 414