00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "G4GDMLWriteStructure.hh"
00036
00037 #include "G4Material.hh"
00038 #include "G4ReflectedSolid.hh"
00039 #include "G4DisplacedSolid.hh"
00040 #include "G4LogicalVolumeStore.hh"
00041 #include "G4PhysicalVolumeStore.hh"
00042 #include "G4PVDivision.hh"
00043 #include "G4PVReplica.hh"
00044 #include "G4OpticalSurface.hh"
00045 #include "G4LogicalSkinSurface.hh"
00046 #include "G4LogicalBorderSurface.hh"
00047
00048 G4GDMLWriteStructure::G4GDMLWriteStructure()
00049 : G4GDMLWriteParamvol()
00050 {
00051 }
00052
00053 G4GDMLWriteStructure::~G4GDMLWriteStructure()
00054 {
00055 }
00056
00057 void
00058 G4GDMLWriteStructure::DivisionvolWrite(xercesc::DOMElement* volumeElement,
00059 const G4PVDivision* const divisionvol)
00060 {
00061 EAxis axis = kUndefined;
00062 G4int number = 0;
00063 G4double width = 0.0;
00064 G4double offset = 0.0;
00065 G4bool consuming = false;
00066
00067 divisionvol->GetReplicationData(axis,number,width,offset,consuming);
00068 axis = divisionvol->GetDivisionAxis();
00069
00070 G4String unitString("mm");
00071 G4String axisString("kUndefined");
00072 if (axis==kXAxis) { axisString = "kXAxis"; }
00073 else if (axis==kYAxis) { axisString = "kYAxis"; }
00074 else if (axis==kZAxis) { axisString = "kZAxis"; }
00075 else if (axis==kRho) { axisString = "kRho"; }
00076 else if (axis==kPhi) { axisString = "kPhi"; unitString = "rad"; }
00077
00078 const G4String name
00079 = GenerateName(divisionvol->GetName(),divisionvol);
00080 const G4String volumeref
00081 = GenerateName(divisionvol->GetLogicalVolume()->GetName(),
00082 divisionvol->GetLogicalVolume());
00083
00084 xercesc::DOMElement* divisionvolElement = NewElement("divisionvol");
00085 divisionvolElement->setAttributeNode(NewAttribute("axis",axisString));
00086 divisionvolElement->setAttributeNode(NewAttribute("number",number));
00087 divisionvolElement->setAttributeNode(NewAttribute("width",width));
00088 divisionvolElement->setAttributeNode(NewAttribute("offset",offset));
00089 divisionvolElement->setAttributeNode(NewAttribute("unit",unitString));
00090 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
00091 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
00092 divisionvolElement->appendChild(volumerefElement);
00093 volumeElement->appendChild(divisionvolElement);
00094 }
00095
00096 void G4GDMLWriteStructure::PhysvolWrite(xercesc::DOMElement* volumeElement,
00097 const G4VPhysicalVolume* const physvol,
00098 const G4Transform3D& T,
00099 const G4String& ModuleName)
00100 {
00101 HepGeom::Scale3D scale;
00102 HepGeom::Rotate3D rotate;
00103 HepGeom::Translate3D translate;
00104
00105 T.getDecomposition(scale,rotate,translate);
00106
00107 const G4ThreeVector scl(scale(0,0),scale(1,1),scale(2,2));
00108 const G4ThreeVector rot = GetAngles(rotate.getRotation());
00109 const G4ThreeVector pos = T.getTranslation();
00110
00111 const G4String name = GenerateName(physvol->GetName(),physvol);
00112
00113 xercesc::DOMElement* physvolElement = NewElement("physvol");
00114 physvolElement->setAttributeNode(NewAttribute("name",name));
00115 volumeElement->appendChild(physvolElement);
00116
00117 const G4String volumeref
00118 = GenerateName(physvol->GetLogicalVolume()->GetName(),
00119 physvol->GetLogicalVolume());
00120
00121 if (ModuleName.empty())
00122 {
00123 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
00124 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
00125 physvolElement->appendChild(volumerefElement);
00126 }
00127 else
00128 {
00129 xercesc::DOMElement* fileElement = NewElement("file");
00130 fileElement->setAttributeNode(NewAttribute("name",ModuleName));
00131 fileElement->setAttributeNode(NewAttribute("volname",volumeref));
00132 physvolElement->appendChild(fileElement);
00133 }
00134
00135 if (std::fabs(pos.x()) > kLinearPrecision
00136 || std::fabs(pos.y()) > kLinearPrecision
00137 || std::fabs(pos.z()) > kLinearPrecision)
00138 {
00139 PositionWrite(physvolElement,name+"_pos",pos);
00140 }
00141 if (std::fabs(rot.x()) > kAngularPrecision
00142 || std::fabs(rot.y()) > kAngularPrecision
00143 || std::fabs(rot.z()) > kAngularPrecision)
00144 {
00145 RotationWrite(physvolElement,name+"_rot",rot);
00146 }
00147 if (std::fabs(scl.x()-1.0) > kRelativePrecision
00148 || std::fabs(scl.y()-1.0) > kRelativePrecision
00149 || std::fabs(scl.z()-1.0) > kRelativePrecision)
00150 {
00151 ScaleWrite(physvolElement,name+"_scl",scl);
00152 }
00153 }
00154
00155 void G4GDMLWriteStructure::ReplicavolWrite(xercesc::DOMElement* volumeElement,
00156 const G4VPhysicalVolume* const replicavol)
00157 {
00158 EAxis axis = kUndefined;
00159 G4int number = 0;
00160 G4double width = 0.0;
00161 G4double offset = 0.0;
00162 G4bool consuming = false;
00163 G4String unitString("mm");
00164
00165 replicavol->GetReplicationData(axis,number,width,offset,consuming);
00166
00167 const G4String volumeref
00168 = GenerateName(replicavol->GetLogicalVolume()->GetName(),
00169 replicavol->GetLogicalVolume());
00170
00171 xercesc::DOMElement* replicavolElement = NewElement("replicavol");
00172 replicavolElement->setAttributeNode(NewAttribute("number",number));
00173 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
00174 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
00175 replicavolElement->appendChild(volumerefElement);
00176 xercesc::DOMElement* replicateElement = NewElement("replicate_along_axis");
00177 replicavolElement->appendChild(replicateElement);
00178
00179 xercesc::DOMElement* dirElement = NewElement("direction");
00180 if(axis==kXAxis)
00181 { dirElement->setAttributeNode(NewAttribute("x","1")); }
00182 else if(axis==kYAxis)
00183 { dirElement->setAttributeNode(NewAttribute("y","1")); }
00184 else if(axis==kZAxis)
00185 { dirElement->setAttributeNode(NewAttribute("z","1")); }
00186 else if(axis==kRho)
00187 { dirElement->setAttributeNode(NewAttribute("rho","1")); }
00188 else if(axis==kPhi)
00189 { dirElement->setAttributeNode(NewAttribute("phi","1"));
00190 unitString="rad"; }
00191 replicateElement->appendChild(dirElement);
00192
00193 xercesc::DOMElement* widthElement = NewElement("width");
00194 widthElement->setAttributeNode(NewAttribute("value",width));
00195 widthElement->setAttributeNode(NewAttribute("unit",unitString));
00196 replicateElement->appendChild(widthElement);
00197
00198 xercesc::DOMElement* offsetElement = NewElement("offset");
00199 offsetElement->setAttributeNode(NewAttribute("value",offset));
00200 offsetElement->setAttributeNode(NewAttribute("unit",unitString));
00201 replicateElement->appendChild(offsetElement);
00202
00203 volumeElement->appendChild(replicavolElement);
00204 }
00205
00206 void G4GDMLWriteStructure::
00207 BorderSurfaceCache(const G4LogicalBorderSurface* const bsurf)
00208 {
00209 if (!bsurf) { return; }
00210
00211 const G4SurfaceProperty* psurf = bsurf->GetSurfaceProperty();
00212
00213
00214
00215 xercesc::DOMElement* borderElement = NewElement("bordersurface");
00216 borderElement->setAttributeNode(NewAttribute("name", bsurf->GetName()));
00217 borderElement->setAttributeNode(NewAttribute("surfaceproperty",
00218 psurf->GetName()));
00219
00220 const G4String volumeref1 = GenerateName(bsurf->GetVolume1()->GetName(),
00221 bsurf->GetVolume1());
00222 const G4String volumeref2 = GenerateName(bsurf->GetVolume2()->GetName(),
00223 bsurf->GetVolume2());
00224 xercesc::DOMElement* volumerefElement1 = NewElement("physvolref");
00225 xercesc::DOMElement* volumerefElement2 = NewElement("physvolref");
00226 volumerefElement1->setAttributeNode(NewAttribute("ref",volumeref1));
00227 volumerefElement2->setAttributeNode(NewAttribute("ref",volumeref2));
00228 borderElement->appendChild(volumerefElement1);
00229 borderElement->appendChild(volumerefElement2);
00230
00231 if (FindOpticalSurface(psurf))
00232 {
00233 const G4OpticalSurface* opsurf =
00234 dynamic_cast<const G4OpticalSurface*>(psurf);
00235 if (!opsurf)
00236 {
00237 G4Exception("G4GDMLWriteStructure::BorderSurfaceCache()",
00238 "InvalidSetup", FatalException, "No optical surface found!");
00239 return;
00240 }
00241 OpticalSurfaceWrite(solidsElement, opsurf);
00242 }
00243
00244 borderElementVec.push_back(borderElement);
00245 }
00246
00247 void G4GDMLWriteStructure::
00248 SkinSurfaceCache(const G4LogicalSkinSurface* const ssurf)
00249 {
00250 if (!ssurf) { return; }
00251
00252 const G4SurfaceProperty* psurf = ssurf->GetSurfaceProperty();
00253
00254
00255
00256 xercesc::DOMElement* skinElement = NewElement("skinsurface");
00257 skinElement->setAttributeNode(NewAttribute("name", ssurf->GetName()));
00258 skinElement->setAttributeNode(NewAttribute("surfaceproperty",
00259 psurf->GetName()));
00260
00261 const G4String volumeref = GenerateName(ssurf->GetLogicalVolume()->GetName(),
00262 ssurf->GetLogicalVolume());
00263 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
00264 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
00265 skinElement->appendChild(volumerefElement);
00266
00267 if (FindOpticalSurface(psurf))
00268 {
00269 const G4OpticalSurface* opsurf =
00270 dynamic_cast<const G4OpticalSurface*>(psurf);
00271 if (!opsurf)
00272 {
00273 G4Exception("G4GDMLWriteStructure::SkinSurfaceCache()",
00274 "InvalidSetup", FatalException, "No optical surface found!");
00275 return;
00276 }
00277 OpticalSurfaceWrite(solidsElement, opsurf);
00278 }
00279
00280 skinElementVec.push_back(skinElement);
00281 }
00282
00283 G4bool G4GDMLWriteStructure::FindOpticalSurface(const G4SurfaceProperty* psurf)
00284 {
00285 const G4OpticalSurface* osurf = dynamic_cast<const G4OpticalSurface*>(psurf);
00286 std::vector<const G4OpticalSurface*>::const_iterator pos;
00287 pos = std::find(opt_vec.begin(), opt_vec.end(), osurf);
00288 if (pos != opt_vec.end()) { return false; }
00289
00290 opt_vec.push_back(osurf);
00291 return true;
00292 }
00293
00294 const G4LogicalSkinSurface*
00295 G4GDMLWriteStructure::GetSkinSurface(const G4LogicalVolume* const lvol)
00296 {
00297 G4LogicalSkinSurface* surf = 0;
00298 G4int nsurf = G4LogicalSkinSurface::GetNumberOfSkinSurfaces();
00299 if (nsurf)
00300 {
00301 const G4LogicalSkinSurfaceTable* stable =
00302 G4LogicalSkinSurface::GetSurfaceTable();
00303 std::vector<G4LogicalSkinSurface*>::const_iterator pos;
00304 for (pos = stable->begin(); pos != stable->end(); pos++)
00305 {
00306 if (lvol == (*pos)->GetLogicalVolume())
00307 {
00308 surf = *pos; break;
00309 }
00310 }
00311 }
00312 return surf;
00313 }
00314
00315 const G4LogicalBorderSurface*
00316 G4GDMLWriteStructure::GetBorderSurface(const G4VPhysicalVolume* const pvol)
00317 {
00318 G4LogicalBorderSurface* surf = 0;
00319 G4int nsurf = G4LogicalBorderSurface::GetNumberOfBorderSurfaces();
00320 if (nsurf)
00321 {
00322 const G4LogicalBorderSurfaceTable* btable =
00323 G4LogicalBorderSurface::GetSurfaceTable();
00324 std::vector<G4LogicalBorderSurface*>::const_iterator pos;
00325 for (pos = btable->begin(); pos != btable->end(); pos++)
00326 {
00327 if (pvol == (*pos)->GetVolume1())
00328 {
00329 surf = *pos; break;
00330 }
00331 }
00332 }
00333 return surf;
00334 }
00335
00336 void G4GDMLWriteStructure::SurfacesWrite()
00337 {
00338 G4cout << "G4GDML: Writing surfaces..." << G4endl;
00339
00340 std::vector<xercesc::DOMElement*>::const_iterator pos;
00341 for (pos = skinElementVec.begin(); pos != skinElementVec.end(); pos++)
00342 {
00343 structureElement->appendChild(*pos);
00344 }
00345 for (pos = borderElementVec.begin(); pos != borderElementVec.end(); pos++)
00346 {
00347 structureElement->appendChild(*pos);
00348 }
00349 }
00350
00351 void G4GDMLWriteStructure::StructureWrite(xercesc::DOMElement* gdmlElement)
00352 {
00353 G4cout << "G4GDML: Writing structure..." << G4endl;
00354
00355 structureElement = NewElement("structure");
00356 gdmlElement->appendChild(structureElement);
00357 }
00358
00359 G4Transform3D G4GDMLWriteStructure::
00360 TraverseVolumeTree(const G4LogicalVolume* const volumePtr, const G4int depth)
00361 {
00362 if (VolumeMap().find(volumePtr) != VolumeMap().end())
00363 {
00364 return VolumeMap()[volumePtr];
00365 }
00366
00367 G4VSolid* solidPtr = volumePtr->GetSolid();
00368 G4Transform3D R,invR;
00369 G4int trans=0;
00370
00371 while (true)
00372 {
00373 if (trans>maxTransforms)
00374 {
00375 G4String ErrorMessage = "Referenced solid in volume '"
00376 + volumePtr->GetName()
00377 + "' was displaced/reflected too many times!";
00378 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
00379 "InvalidSetup", FatalException, ErrorMessage);
00380 }
00381
00382 if (G4ReflectedSolid* refl = dynamic_cast<G4ReflectedSolid*>(solidPtr))
00383 {
00384 R = R*refl->GetTransform3D();
00385 solidPtr = refl->GetConstituentMovedSolid();
00386 trans++;
00387 continue;
00388 }
00389
00390 if (G4DisplacedSolid* disp = dynamic_cast<G4DisplacedSolid*>(solidPtr))
00391 {
00392 R = R*G4Transform3D(disp->GetObjectRotation(),
00393 disp->GetObjectTranslation());
00394 solidPtr = disp->GetConstituentMovedSolid();
00395 trans++;
00396 continue;
00397 }
00398
00399 break;
00400 }
00401
00402
00403
00404 if (trans>0) { invR = R.inverse(); }
00405
00406 const G4String name
00407 = GenerateName(volumePtr->GetName(),volumePtr);
00408 const G4String materialref
00409 = GenerateName(volumePtr->GetMaterial()->GetName(),
00410 volumePtr->GetMaterial());
00411 const G4String solidref
00412 = GenerateName(solidPtr->GetName(),solidPtr);
00413
00414 xercesc::DOMElement* volumeElement = NewElement("volume");
00415 volumeElement->setAttributeNode(NewAttribute("name",name));
00416 xercesc::DOMElement* materialrefElement = NewElement("materialref");
00417 materialrefElement->setAttributeNode(NewAttribute("ref",materialref));
00418 volumeElement->appendChild(materialrefElement);
00419 xercesc::DOMElement* solidrefElement = NewElement("solidref");
00420 solidrefElement->setAttributeNode(NewAttribute("ref",solidref));
00421 volumeElement->appendChild(solidrefElement);
00422
00423 const G4int daughterCount = volumePtr->GetNoDaughters();
00424
00425 for (G4int i=0;i<daughterCount;i++)
00426 {
00427 const G4VPhysicalVolume* const physvol = volumePtr->GetDaughter(i);
00428 const G4String ModuleName = Modularize(physvol,depth);
00429
00430 G4Transform3D daughterR;
00431
00432 if (ModuleName.empty())
00433 {
00434 daughterR = TraverseVolumeTree(physvol->GetLogicalVolume(),depth+1);
00435 }
00436 else
00437 {
00438 G4GDMLWriteStructure writer;
00439 daughterR = writer.Write(ModuleName,physvol->GetLogicalVolume(),
00440 SchemaLocation,depth+1);
00441 }
00442
00443 if (const G4PVDivision* const divisionvol
00444 = dynamic_cast<const G4PVDivision*>(physvol))
00445 {
00446 if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
00447 {
00448 G4String ErrorMessage = "Division volume in '"
00449 + name
00450 + "' can not be related to reflected solid!";
00451 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
00452 "InvalidSetup", FatalException, ErrorMessage);
00453 }
00454 DivisionvolWrite(volumeElement,divisionvol);
00455 } else
00456 if (physvol->IsParameterised())
00457 {
00458 if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
00459 {
00460 G4String ErrorMessage = "Parameterised volume in '"
00461 + name
00462 + "' can not be related to reflected solid!";
00463 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
00464 "InvalidSetup", FatalException, ErrorMessage);
00465 }
00466 ParamvolWrite(volumeElement,physvol);
00467 } else
00468 if (physvol->IsReplicated())
00469 {
00470 if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
00471 {
00472 G4String ErrorMessage = "Replica volume in '"
00473 + name
00474 + "' can not be related to reflected solid!";
00475 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
00476 "InvalidSetup", FatalException, ErrorMessage);
00477 }
00478 ReplicavolWrite(volumeElement,physvol);
00479 }
00480 else
00481 {
00482 G4RotationMatrix rot;
00483
00484 if (physvol->GetFrameRotation() != 0)
00485 {
00486 rot = *(physvol->GetFrameRotation());
00487 }
00488 G4Transform3D P(rot,physvol->GetObjectTranslation());
00489 PhysvolWrite(volumeElement,physvol,invR*P*daughterR,ModuleName);
00490 }
00491 BorderSurfaceCache(GetBorderSurface(physvol));
00492 }
00493
00494 structureElement->appendChild(volumeElement);
00495
00496
00497
00498 VolumeMap()[volumePtr] = R;
00499
00500 AddExtension(volumeElement, volumePtr);
00501
00502
00503 AddMaterial(volumePtr->GetMaterial());
00504
00505
00506 AddSolid(solidPtr);
00507
00508 SkinSurfaceCache(GetSkinSurface(volumePtr));
00509
00510 return R;
00511 }