Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4HepRepFileSceneHandler.cc
Go to the documentation of this file.
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 // $Id$
27 //
28 //
29 // Joseph Perl 27th January 2002
30 // A base class for a scene handler to export geometry and trajectories
31 // to the HepRep xml file format.
32 
34 #include "G4HepRepFile.hh"
35 #include "G4HepRepMessenger.hh"
36 #include "G4UIcommand.hh"
37 
38 #include "G4PhysicalConstants.hh"
39 #include "G4SystemOfUnits.hh"
40 #include "G4Version.hh"
41 #include "G4VSolid.hh"
42 #include "G4PhysicalVolumeModel.hh"
43 #include "G4VPhysicalVolume.hh"
44 #include "G4LogicalVolume.hh"
45 #include "G4RotationMatrix.hh"
46 #include "G4Material.hh"
47 #include "G4Polymarker.hh"
48 #include "G4Polyline.hh"
49 #include "G4Text.hh"
50 #include "G4Circle.hh"
51 #include "G4Square.hh"
52 #include "G4Polyhedron.hh"
53 #include "G4NURBS.hh"
54 #include "G4VTrajectory.hh"
55 #include "G4VTrajectoryPoint.hh"
56 #include "G4TrajectoriesModel.hh"
57 #include "G4VHit.hh"
58 #include "G4AttDef.hh"
59 #include "G4AttValue.hh"
60 #include "G4AttCheck.hh"
61 #include "G4VisManager.hh"
62 #include "G4VisTrajContext.hh"
63 #include "G4VTrajectoryModel.hh"
64 
65 //HepRep
66 #include "G4HepRepFileXMLWriter.hh"
67 
69 // Counter for HepRep scene handlers.
70 
72  const G4String& name):
73 G4VSceneHandler(system, fSceneIdCount++, name)
74 {
75  hepRepXMLWriter = ((G4HepRepFile*)(&system))->GetHepRepXMLWriter();
76  fileCounter = 0;
77 
78  inPrimitives2D = false;
79  warnedAbout3DText = false;
80  warnedAbout2DMarkers = false;
81  haveVisible = false;
82  drawingTraj = false;
83  doneInitTraj = false;
84  drawingHit = false;
85  doneInitHit = false;
86 }
87 
88 
90 
91 
93  G4VisManager* visManager = G4VisManager::GetInstance();
94  const G4VTrajectoryModel* model = visManager->CurrentTrajDrawModel();
95  trajContext = & model->GetContext();
96 
97  G4VSceneHandler::BeginModeling(); // Required: see G4VSceneHandler.hh.
98 }
99 
100 
102  G4VSceneHandler::EndModeling(); // Required: see G4VSceneHandler.hh.
103 }
104 
106 (const G4Transform3D& objectTransformation) {
107 #ifdef G4HEPREPFILEDEBUG
108  G4cout << "G4HepRepFileSceneHandler::BeginPrimitives2D() " << G4endl;
109 #endif
110  inPrimitives2D = true;
111  G4VSceneHandler::BeginPrimitives2D(objectTransformation);
112 }
113 
115 #ifdef G4HEPREPFILEDEBUG
116  G4cout << "G4HepRepFileSceneHandler::EndPrimitives2D() " << G4endl;
117 #endif
119  inPrimitives2D = false;
120 }
121 
122 
123 #ifdef G4HEPREPFILEDEBUG
124 void G4HepRepFileSceneHandler::PrintThings() {
125  G4cout <<
126  " with transformation "
128  G4PhysicalVolumeModel* pPVModel =
129  dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
130  if (pPVModel) {
131  G4VPhysicalVolume* pCurrentPV = pPVModel->GetCurrentPV();
132  G4LogicalVolume* pCurrentLV = pPVModel->GetCurrentLV();
133  G4int currentDepth = pPVModel->GetCurrentDepth();
134  G4cout <<
135  "\n current physical volume: "
136  << pCurrentPV->GetName() <<
137  "\n current logical volume: "
138  << pCurrentLV->GetName() <<
139  "\n current depth of geometry tree: "
140  << currentDepth;
141  }
142  G4cout << G4endl;
143 }
144 #endif
145 
146 
148 #ifdef G4HEPREPFILEDEBUG
149  G4cout <<
150  "G4HepRepFileSceneHandler::AddSolid(const G4Box& box) called for "
151  << box.GetName()
152  << G4endl;
153  PrintThings();
154 #endif
155 
156  if (drawingTraj)
157  return;
158 
159  if (drawingHit)
160  InitHit();
161 
162  haveVisible = false;
163  AddHepRepInstance("Prism", NULL);
164 
166 
167  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
168  return;
169 
170  hepRepXMLWriter->addPrimitive();
171 
172  G4double dx = box.GetXHalfLength();
173  G4double dy = box.GetYHalfLength();
174  G4double dz = box.GetZHalfLength();
175 
176  G4Point3D vertex1(G4Point3D( dx, dy,-dz));
177  G4Point3D vertex2(G4Point3D( dx,-dy,-dz));
178  G4Point3D vertex3(G4Point3D(-dx,-dy,-dz));
179  G4Point3D vertex4(G4Point3D(-dx, dy,-dz));
180  G4Point3D vertex5(G4Point3D( dx, dy, dz));
181  G4Point3D vertex6(G4Point3D( dx,-dy, dz));
182  G4Point3D vertex7(G4Point3D(-dx,-dy, dz));
183  G4Point3D vertex8(G4Point3D(-dx, dy, dz));
184 
185  vertex1 = (fObjectTransformation) * vertex1;
186  vertex2 = (fObjectTransformation) * vertex2;
187  vertex3 = (fObjectTransformation) * vertex3;
188  vertex4 = (fObjectTransformation) * vertex4;
189  vertex5 = (fObjectTransformation) * vertex5;
190  vertex6 = (fObjectTransformation) * vertex6;
191  vertex7 = (fObjectTransformation) * vertex7;
192  vertex8 = (fObjectTransformation) * vertex8;
193 
194  hepRepXMLWriter->addPoint(vertex1.x(), vertex1.y(), vertex1.z());
195  hepRepXMLWriter->addPoint(vertex2.x(), vertex2.y(), vertex2.z());
196  hepRepXMLWriter->addPoint(vertex3.x(), vertex3.y(), vertex3.z());
197  hepRepXMLWriter->addPoint(vertex4.x(), vertex4.y(), vertex4.z());
198  hepRepXMLWriter->addPoint(vertex5.x(), vertex5.y(), vertex5.z());
199  hepRepXMLWriter->addPoint(vertex6.x(), vertex6.y(), vertex6.z());
200  hepRepXMLWriter->addPoint(vertex7.x(), vertex7.y(), vertex7.z());
201  hepRepXMLWriter->addPoint(vertex8.x(), vertex8.y(), vertex8.z());
202 }
203 
204 
206 #ifdef G4HEPREPFILEDEBUG
207  G4cout <<
208  "G4HepRepFileSceneHandler::AddSolid(const G4Cons& cons) called for "
209  << cons.GetName()
210  << G4endl;
211  PrintThings();
212 #endif
213 
214  // HepRApp does not correctly represent the end faces of cones at
215  // non-standard angles, let the base class convert these solids to polygons.
216  G4RotationMatrix r = fObjectTransformation.getRotation();
217  G4bool linedUpWithAnAxis = (std::fabs(r.phiX())<=.001 ||
218  std::fabs(r.phiY())<=.001 ||
219  std::fabs(r.phiZ())<=.001 ||
220  std::fabs(r.phiX()-pi)<=.001 ||
221  std::fabs(r.phiY()-pi)<=.001 ||
222  std::fabs(r.phiZ()-pi)<=.001);
223  //G4cout << "Angle X:" << r.phiX() << ", Angle Y:" << r.phiY() << ", Angle Z:" << r.phiZ() << G4endl;
224  //G4cout << "linedUpWithAnAxis:" << linedUpWithAnAxis << G4endl;
225 
226  // HepRep does not have a primitive for a cut cone,
227  // so if this cone is cut, let the base class convert this
228  // solid to polygons.
230  if (cons.GetDeltaPhiAngle() < twopi || !linedUpWithAnAxis || messenger->renderCylAsPolygons())
231  {
232  G4VSceneHandler::AddSolid(cons); // Invoke default action.
233  } else {
234 
235  if (drawingTraj)
236  return;
237 
238  if (drawingHit)
239  InitHit();
240 
241  haveVisible = false;
242  AddHepRepInstance("Cylinder", NULL);
243 
244  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
245  return;
246 
247  G4Point3D vertex1(G4Point3D( 0., 0., -cons.GetZHalfLength()));
248  G4Point3D vertex2(G4Point3D( 0., 0., cons.GetZHalfLength()));
249 
250  vertex1 = (fObjectTransformation) * vertex1;
251  vertex2 = (fObjectTransformation) * vertex2;
252 
253  // Outer cylinder.
254  hepRepXMLWriter->addPrimitive();
255  hepRepXMLWriter->addAttValue("Radius1",messenger->getScale() * cons.GetOuterRadiusMinusZ());
256  hepRepXMLWriter->addAttValue("Radius2",messenger->getScale() * cons.GetOuterRadiusPlusZ());
257  hepRepXMLWriter->addPoint(vertex1.x(), vertex1.y(), vertex1.z());
258  hepRepXMLWriter->addPoint(vertex2.x(), vertex2.y(), vertex2.z());
259 
260  // Inner cylinder.
261  hepRepXMLWriter->addPrimitive();
262  hepRepXMLWriter->addAttValue("Radius1",messenger->getScale() * cons.GetInnerRadiusMinusZ());
263  hepRepXMLWriter->addAttValue("Radius2",messenger->getScale() * cons.GetInnerRadiusPlusZ());
264  hepRepXMLWriter->addPoint(vertex1.x(), vertex1.y(), vertex1.z());
265  hepRepXMLWriter->addPoint(vertex2.x(), vertex2.y(), vertex2.z());
266  }
267 }
268 
269 
271 #ifdef G4HEPREPFILEDEBUG
272  G4cout <<
273  "G4HepRepFileSceneHandler::AddSolid(const G4Tubs& tubs) called for "
274  << tubs.GetName()
275  << G4endl;
276  PrintThings();
277 #endif
278 
279  // HepRApp does not correctly represent the end faces of cylinders at
280  // non-standard angles, let the base class convert these solids to polygons.
281  G4RotationMatrix r = fObjectTransformation.getRotation();
282  G4bool linedUpWithAnAxis = (std::fabs(r.phiX())<=.001 ||
283  std::fabs(r.phiY())<=.001 ||
284  std::fabs(r.phiZ())<=.001 ||
285  std::fabs(r.phiX()-pi)<=.001 ||
286  std::fabs(r.phiY()-pi)<=.001 ||
287  std::fabs(r.phiZ()-pi)<=.001);
288  //G4cout << "Angle X:" << r.phiX() << ", Angle Y:" << r.phiY() << ", Angle Z:" << r.phiZ() << G4endl;
289  //G4cout << "linedUpWithAnAxis:" << linedUpWithAnAxis << G4endl;
290 
291  // HepRep does not have a primitive for a cut cylinder,
292  // so if this cylinder is cut, let the base class convert this
293  // solid to polygons.
295  if (tubs.GetDeltaPhiAngle() < twopi || !linedUpWithAnAxis || messenger->renderCylAsPolygons())
296  {
297  G4VSceneHandler::AddSolid(tubs); // Invoke default action.
298  } else {
299 
300  if (drawingTraj)
301  return;
302 
303  if (drawingHit)
304  InitHit();
305 
306  haveVisible = false;
307  AddHepRepInstance("Cylinder", NULL);
308 
309  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
310  return;
311 
312  G4Point3D vertex1(G4Point3D( 0., 0., -tubs.GetZHalfLength()));
313  G4Point3D vertex2(G4Point3D( 0., 0., tubs.GetZHalfLength()));
314 
315  vertex1 = (fObjectTransformation) * vertex1;
316  vertex2 = (fObjectTransformation) * vertex2;
317 
318  // Outer cylinder.
319  hepRepXMLWriter->addPrimitive();
320  hepRepXMLWriter->addAttValue("Radius1", messenger->getScale() * tubs.GetOuterRadius());
321  hepRepXMLWriter->addAttValue("Radius2", messenger->getScale() * tubs.GetOuterRadius());
322  hepRepXMLWriter->addPoint(vertex1.x(), vertex1.y(), vertex1.z());
323  hepRepXMLWriter->addPoint(vertex2.x(), vertex2.y(), vertex2.z());
324 
325  // Inner cylinder.
326  if (tubs.GetInnerRadius() != 0.) {
327  hepRepXMLWriter->addPrimitive();
328  hepRepXMLWriter->addAttValue("Radius1", messenger->getScale() * tubs.GetInnerRadius());
329  hepRepXMLWriter->addAttValue("Radius2", messenger->getScale() * tubs.GetInnerRadius());
330  hepRepXMLWriter->addPoint(vertex1.x(), vertex1.y(), vertex1.z());
331  hepRepXMLWriter->addPoint(vertex2.x(), vertex2.y(), vertex2.z());
332  }
333  }
334 }
335 
336 
338 #ifdef G4HEPREPFILEDEBUG
339  G4cout <<
340  "G4HepRepFileSceneHandler::AddSolid(const G4Trd& trd) called for "
341  << trd.GetName()
342  << G4endl;
343  PrintThings();
344 #endif
345 
346  if (drawingTraj)
347  return;
348 
349  if (drawingHit)
350  InitHit();
351 
352  haveVisible = false;
353  AddHepRepInstance("Prism", NULL);
354 
356 
357  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
358  return;
359 
360  hepRepXMLWriter->addPrimitive();
361 
362  G4double dx1 = trd.GetXHalfLength1();
363  G4double dy1 = trd.GetYHalfLength1();
364  G4double dx2 = trd.GetXHalfLength2();
365  G4double dy2 = trd.GetYHalfLength2();
366  G4double dz = trd.GetZHalfLength();
367 
368  G4Point3D vertex1(G4Point3D( dx1, dy1,-dz));
369  G4Point3D vertex2(G4Point3D( dx1,-dy1,-dz));
370  G4Point3D vertex3(G4Point3D(-dx1,-dy1,-dz));
371  G4Point3D vertex4(G4Point3D(-dx1, dy1,-dz));
372  G4Point3D vertex5(G4Point3D( dx2, dy2, dz));
373  G4Point3D vertex6(G4Point3D( dx2,-dy2, dz));
374  G4Point3D vertex7(G4Point3D(-dx2,-dy2, dz));
375  G4Point3D vertex8(G4Point3D(-dx2, dy2, dz));
376 
377  vertex1 = (fObjectTransformation) * vertex1;
378  vertex2 = (fObjectTransformation) * vertex2;
379  vertex3 = (fObjectTransformation) * vertex3;
380  vertex4 = (fObjectTransformation) * vertex4;
381  vertex5 = (fObjectTransformation) * vertex5;
382  vertex6 = (fObjectTransformation) * vertex6;
383  vertex7 = (fObjectTransformation) * vertex7;
384  vertex8 = (fObjectTransformation) * vertex8;
385 
386  hepRepXMLWriter->addPoint(vertex1.x(), vertex1.y(), vertex1.z());
387  hepRepXMLWriter->addPoint(vertex2.x(), vertex2.y(), vertex2.z());
388  hepRepXMLWriter->addPoint(vertex3.x(), vertex3.y(), vertex3.z());
389  hepRepXMLWriter->addPoint(vertex4.x(), vertex4.y(), vertex4.z());
390  hepRepXMLWriter->addPoint(vertex5.x(), vertex5.y(), vertex5.z());
391  hepRepXMLWriter->addPoint(vertex6.x(), vertex6.y(), vertex6.z());
392  hepRepXMLWriter->addPoint(vertex7.x(), vertex7.y(), vertex7.z());
393  hepRepXMLWriter->addPoint(vertex8.x(), vertex8.y(), vertex8.z());
394 }
395 
396 
398 #ifdef G4HEPREPFILEDEBUG
399  G4cout <<
400  "G4HepRepFileSceneHandler::AddSolid(const G4Trap& trap) called for "
401  << trap.GetName()
402  << G4endl;
403  PrintThings();
404 #endif
405  G4VSceneHandler::AddSolid(trap); // Invoke default action.
406 }
407 
408 
410 #ifdef G4HEPREPFILEDEBUG
411  G4cout <<
412  "G4HepRepFileSceneHandler::AddSolid(const G4Sphere& sphere) called for "
413  << sphere.GetName()
414  << G4endl;
415  PrintThings();
416 #endif
417  G4VSceneHandler::AddSolid(sphere); // Invoke default action.
418 }
419 
420 
422 #ifdef G4HEPREPFILEDEBUG
423  G4cout <<
424  "G4HepRepFileSceneHandler::AddSolid(const G4Para& para) called for "
425  << para.GetName()
426  << G4endl;
427  PrintThings();
428 #endif
429  G4VSceneHandler::AddSolid(para); // Invoke default action.
430 }
431 
432 
434 #ifdef G4HEPREPFILEDEBUG
435  G4cout <<
436  "G4HepRepFileSceneHandler::AddSolid(const G4Torus& torus) called for "
437  << torus.GetName()
438  << G4endl;
439  PrintThings();
440 #endif
441  G4VSceneHandler::AddSolid(torus); // Invoke default action.
442 }
443 
444 
446 #ifdef G4HEPREPFILEDEBUG
447  G4cout <<
448  "G4HepRepFileSceneHandler::AddSolid(const G4Polycone& polycone) called for "
449  << polycone.GetName()
450  << G4endl;
451  PrintThings();
452 #endif
453  G4VSceneHandler::AddSolid(polycone); // Invoke default action.
454 }
455 
456 
458 #ifdef G4HEPREPFILEDEBUG
459  G4cout <<
460  "G4HepRepFileSceneHandler::AddSolid(const G4Polyhedra& polyhedra) called for "
461  << polyhedra.GetName()
462  << G4endl;
463  PrintThings();
464 #endif
465  G4VSceneHandler::AddSolid(polyhedra); // Invoke default action.
466 }
467 
468 
470 #ifdef G4HEPREPFILEDEBUG
471  G4cout <<
472  "G4HepRepFileSceneHandler::AddSolid(const G4Solid& solid) called for "
473  << solid.GetName()
474  << G4endl;
475  PrintThings();
476 #endif
477  G4VSceneHandler::AddSolid(solid); // Invoke default action.
478 }
479 
480 
482 #ifdef G4HEPREPFILEDEBUG
483  G4cout << "G4HepRepFileSceneHandler::AddCompound(const G4VTrajectory&) " << G4endl;
484 #endif
485 
486  G4TrajectoriesModel* pTrModel =
487  dynamic_cast<G4TrajectoriesModel*>(fpModel);
488  if (!pTrModel) G4Exception
489  ("G4HepRepFileSceneHandler::AddCompound(const G4VTrajectory&)",
490  "vis-HepRep0001", FatalException, "Not a G4TrajectoriesModel.");
491 
492  // Pointers to hold trajectory attribute values and definitions.
493  std::vector<G4AttValue>* rawTrajAttValues = traj.CreateAttValues();
494  trajAttValues =
495  new std::vector<G4AttValue>;
496  trajAttDefs =
497  new std::map<G4String,G4AttDef>;
498 
499  // Iterators to use with attribute values and definitions.
500  std::vector<G4AttValue>::iterator iAttVal;
501  std::map<G4String,G4AttDef>::const_iterator iAttDef;
502  G4int i;
503 
504  // Get trajectory attributes and definitions in standard HepRep style
505  // (uniform units, 3Vectors decomposed).
506  if (rawTrajAttValues) {
507  G4bool error = G4AttCheck(rawTrajAttValues,
508  traj.GetAttDefs()).Standard(trajAttValues,trajAttDefs);
509  if (error) {
510  G4cout << "G4HepRepFileSceneHandler::AddCompound(traj):"
511  "\nERROR found during conversion to standard trajectory attributes."
512  << G4endl;
513  }
514 #ifdef G4HEPREPFILEDEBUG
515  G4cout <<
516  "G4HepRepFileSceneHandler::AddCompound(traj): standardised attributes:\n"
517  << G4AttCheck(trajAttValues,trajAttDefs) << G4endl;
518 #endif
519  delete rawTrajAttValues;
520  }
521 
522  // Open the HepRep output file if it is not already open.
523  CheckFileOpen();
524 
525  // Add the Event Data Type if it hasn't already been added.
526  if (strcmp("Event Data",hepRepXMLWriter->prevTypeName[0])!=0) {
527  hepRepXMLWriter->addType("Event Data",0);
528  hepRepXMLWriter->addInstance();
529  }
530 
531  // Add the Trajectories Type.
532  G4String previousName = hepRepXMLWriter->prevTypeName[1];
533  hepRepXMLWriter->addType("Trajectories",1);
534 
535  // If this is the first trajectory of this event,
536  // specify attribute values common to all trajectories.
537  if (strcmp("Trajectories",previousName)!=0) {
538  hepRepXMLWriter->addAttValue("Layer",100);
539 
540  // Take all Trajectory attDefs from first trajectory.
541  // Would rather be able to get these attDefs without needing a reference from any
542  // particular trajectory, but don't know how to do that.
543  // Write out trajectory attribute definitions.
544  if (trajAttValues && trajAttDefs) {
545  for (iAttVal = trajAttValues->begin();
546  iAttVal != trajAttValues->end(); ++iAttVal) {
547  iAttDef = trajAttDefs->find(iAttVal->GetName());
548  if (iAttDef != trajAttDefs->end()) {
549  // Protect against incorrect use of Category. Anything value other than the
550  // standard ones will be considered to be in the physics category.
551  G4String category = iAttDef->second.GetCategory();
552  if (strcmp(category,"Draw")!=0 &&
553  strcmp(category,"Physics")!=0 &&
554  strcmp(category,"Association")!=0 &&
555  strcmp(category,"PickAction")!=0)
556  category = "Physics";
557  hepRepXMLWriter->addAttDef(iAttVal->GetName(), iAttDef->second.GetDesc(),
558  category, iAttDef->second.GetExtra());
559  }
560  }
561  }
562 
563  // Take all TrajectoryPoint attDefs from first point of first trajectory.
564  // Would rather be able to get these attDefs without needing a reference from any
565  // particular point, but don't know how to do that.
566  if ((trajContext->GetDrawStepPts() || trajContext->GetDrawAuxPts())
567  && traj.GetPointEntries()>0) {
568  G4VTrajectoryPoint* aTrajectoryPoint = traj.GetPoint(0);
569 
570  // Pointers to hold trajectory point attribute values and definitions.
571  std::vector<G4AttValue>* rawPointAttValues = aTrajectoryPoint->CreateAttValues();
572  std::vector<G4AttValue>* pointAttValues =
573  new std::vector<G4AttValue>;
574  std::map<G4String,G4AttDef>* pointAttDefs =
575  new std::map<G4String,G4AttDef>;
576 
577  // Get first trajectory point's attributes and definitions in standard HepRep style
578  // (uniform units, 3Vectors decomposed).
579  if (rawPointAttValues) {
580  G4bool error = G4AttCheck(rawPointAttValues,
581  aTrajectoryPoint->GetAttDefs()).Standard(pointAttValues,pointAttDefs);
582  if (error) {
583  G4cout << "G4HepRepFileSceneHandler::AddCompound(traj):"
584  "\nERROR found during conversion to standard first point attributes." << G4endl;
585  }
586 
587  // Write out point attribute definitions.
588  if (pointAttValues && pointAttDefs) {
589  for (iAttVal = pointAttValues->begin();
590  iAttVal != pointAttValues->end(); ++iAttVal) {
591  iAttDef =
592  pointAttDefs->find(iAttVal->GetName());
593  if (iAttDef != pointAttDefs->end()) {
594  // Protect against incorrect use of Category. Anything value other than the
595  // standard ones will be considered to be in the physics category.
596  G4String category = iAttDef->second.GetCategory();
597  if (strcmp(category,"Draw")!=0 &&
598  strcmp(category,"Physics")!=0 &&
599  strcmp(category,"Association")!=0 &&
600  strcmp(category,"PickAction")!=0)
601  category = "Physics";
602  // Do not write out the Aux or Pos attribute. Aux does not conform to the HepRep rule
603  // that each object can have only one instance of a given AttValue.
604  // Both of these attributes are redundant to actual position information of the point.
605  if (strcmp(iAttVal->GetName(),"Aux-X")!=0 &&
606  strcmp(iAttVal->GetName(),"Aux-Y")!=0 &&
607  strcmp(iAttVal->GetName(),"Aux-Z")!=0 &&
608  strcmp(iAttVal->GetName(),"Pos-X")!=0 &&
609  strcmp(iAttVal->GetName(),"Pos-Y")!=0 &&
610  strcmp(iAttVal->GetName(),"Pos-Z")!=0)
611  hepRepXMLWriter->addAttDef(iAttVal->GetName(), iAttDef->second.GetDesc(),
612  category, iAttDef->second.GetExtra());
613  }
614  }
615  }
616  delete rawPointAttValues;
617  }
618 
619  // Clean up point attributes.
620  if (pointAttValues)
621  delete pointAttValues;
622  if (pointAttDefs)
623  delete pointAttDefs;
624  }
625  } // end of special treatment for when this is the first trajectory.
626 
627  // Now that we have written out all of the attributes that are based on the
628  // trajectory's particulars, call base class to deconstruct trajectory into polyline and/or points
629  // (or nothing if trajectory is to be filtered out).
630  // If base class calls for drawing points, no points will actually be drawn there since we
631  // instead need to do point drawing from here (in order to obtain the points attributes,
632  // not available from AddPrimitive(...point). Instead, such a call will just serve to set the
633  // flag that tells us that point drawing was requested for this trajectory (depends on several
634  // factors including i_mode, trajContext and filtering).
635  drawingTraj = true;
636  doneInitTraj = false;
638  drawingTraj = false;
639 
640  // Draw step points.
641  if (trajContext->GetDrawStepPts()) {
642  if (!doneInitTraj)
643  InitTrajectory();
644  // Create Trajectory Points as a subType of Trajectories.
645  // Note that we should create this heprep type even if there are no actual points.
646  // This allows the user to tell that points don't exist (admittedly odd) rather
647  // than that they were omitted by the drawing mode.
648  previousName = hepRepXMLWriter->prevTypeName[2];
649  hepRepXMLWriter->addType("Trajectory Step Points",2);
650 
651  float redness;
652  float greenness;
653  float blueness;
654  G4int markSize;
655  G4bool visible;
656  G4bool square;
657  G4Colour colour = trajContext->GetStepPtsColour();
658  redness = colour.GetRed();
659  greenness = colour.GetGreen();
660  blueness = colour.GetBlue();
661  markSize = (G4int) trajContext->GetStepPtsSize();
662  visible = (G4int) trajContext->GetStepPtsVisible();
663  square = (trajContext->GetStepPtsType()==G4Polymarker::squares);
664 
665  // Avoiding drawing anything black on black.
666  if (redness==0. && greenness==0. && blueness==0.) {
667  redness = 1.;
668  greenness = 1.;
669  blueness = 1.;
670  }
671 
672  // Specify attributes common to all trajectory points.
673  if (strcmp("Trajectory Step Points",previousName)!=0) {
674  hepRepXMLWriter->addAttValue("DrawAs","Point");
675  hepRepXMLWriter->addAttValue("MarkColor", redness, greenness, blueness);
676  hepRepXMLWriter->addAttValue("MarkSize",markSize);
677  hepRepXMLWriter->addAttValue("Layer",110);
678  hepRepXMLWriter->addAttValue("Visibility",visible);
679  if (square)
680  hepRepXMLWriter->addAttValue("MarkName","square");
681  else
682  hepRepXMLWriter->addAttValue("MarkName","dot");
683  }
684 
685  // Loop over all points on this trajectory.
686  for (i = 0; i < traj.GetPointEntries(); i++) {
687  G4VTrajectoryPoint* aTrajectoryPoint = traj.GetPoint(i);
688 
689  // Each point is a separate instance of the type Trajectory Points.
690  hepRepXMLWriter->addInstance();
691 
692  // Pointers to hold trajectory point attribute values and definitions.
693  std::vector<G4AttValue>* rawPointAttValues = aTrajectoryPoint->CreateAttValues();
694  std::vector<G4AttValue>* pointAttValues =
695  new std::vector<G4AttValue>;
696  std::map<G4String,G4AttDef>* pointAttDefs =
697  new std::map<G4String,G4AttDef>;
698 
699  // Get trajectory point attributes and definitions in standard HepRep style
700  // (uniform units, 3Vectors decomposed).
701  if (rawPointAttValues) {
702  G4bool error = G4AttCheck(rawPointAttValues,
703  aTrajectoryPoint->GetAttDefs()).Standard(pointAttValues,pointAttDefs);
704  if (error) {
705  G4cout << "G4HepRepFileSceneHandler::AddCompound(traj):"
706  "\nERROR found during conversion to standard point attributes." << G4endl;
707  }
708 
709  // Write out point attribute values.
710  if (pointAttValues) {
711  for (iAttVal = pointAttValues->begin();
712  iAttVal != pointAttValues->end(); ++iAttVal)
713  // Do not write out the Aux or Pos attribute. Aux does not conform to the HepRep rule
714  // that each object can have only one instance of a given AttValue.
715  // Both of these attributes are redundant to actual position information of the point.
716  if (strcmp(iAttVal->GetName(),"Aux-X")!=0 &&
717  strcmp(iAttVal->GetName(),"Aux-Y")!=0 &&
718  strcmp(iAttVal->GetName(),"Aux-Z")!=0 &&
719  strcmp(iAttVal->GetName(),"Pos-X")!=0 &&
720  strcmp(iAttVal->GetName(),"Pos-Y")!=0 &&
721  strcmp(iAttVal->GetName(),"Pos-Z")!=0)
722  hepRepXMLWriter->addAttValue(iAttVal->GetName(), iAttVal->GetValue());
723  delete pointAttValues;
724  }
725  delete rawPointAttValues;
726  }
727 
728  // Clean up point attributes.
729  if (pointAttDefs)
730  delete pointAttDefs;
731 
732  // Each trajectory point is made of a single primitive, a point.
733  hepRepXMLWriter->addPrimitive();
734  G4Point3D vertex = aTrajectoryPoint->GetPosition();
735  hepRepXMLWriter->addPoint(vertex.x(), vertex.y(), vertex.z());
736  }
737  }
738 
739  // Draw Auxiliary Points
740  if (trajContext->GetDrawAuxPts()) {
741  if (!doneInitTraj)
742  InitTrajectory();
743  // Create Trajectory Points as a subType of Trajectories.
744  // Note that we should create this heprep type even if there are no actual points.
745  // This allows the user to tell that points don't exist (admittedly odd) rather
746  // than that they were omitted by the drawing mode.
747  previousName = hepRepXMLWriter->prevTypeName[2];
748  hepRepXMLWriter->addType("Trajectory Auxiliary Points",2);
749 
750  float redness;
751  float greenness;
752  float blueness;
753  G4int markSize;
754  G4bool visible;
755  G4bool square;
756  G4Colour colour = trajContext->GetAuxPtsColour();
757  redness = colour.GetRed();
758  greenness = colour.GetGreen();
759  blueness = colour.GetBlue();
760  markSize = (G4int) trajContext->GetAuxPtsSize();
761  visible = (G4int) trajContext->GetAuxPtsVisible();
762  square = (trajContext->GetAuxPtsType()==G4Polymarker::squares);
763 
764  // Avoiding drawing anything black on black.
765  if (redness==0. && greenness==0. && blueness==0.) {
766  redness = 1.;
767  greenness = 1.;
768  blueness = 1.;
769  }
770 
771  // Specify attributes common to all trajectory points.
772  if (strcmp("Trajectory Auxiliary Points",previousName)!=0) {
773  hepRepXMLWriter->addAttValue("DrawAs","Point");
774  hepRepXMLWriter->addAttValue("MarkColor", redness, greenness, blueness);
775  hepRepXMLWriter->addAttValue("MarkSize",markSize);
776  hepRepXMLWriter->addAttValue("Layer",110);
777  hepRepXMLWriter->addAttValue("Visibility",visible);
778  if (square)
779  hepRepXMLWriter->addAttValue("MarkName","Square");
780  else
781  hepRepXMLWriter->addAttValue("MarkName","Dot");
782  }
783 
784  // Loop over all points on this trajectory.
785  for (i = 0; i < traj.GetPointEntries(); i++) {
786  G4VTrajectoryPoint* aTrajectoryPoint = traj.GetPoint(i);
787 
788  // Each point is a separate instance of the type Trajectory Points.
789  hepRepXMLWriter->addInstance();
790 
791  // Pointers to hold trajectory point attribute values and definitions.
792  std::vector<G4AttValue>* rawPointAttValues = aTrajectoryPoint->CreateAttValues();
793  std::vector<G4AttValue>* pointAttValues =
794  new std::vector<G4AttValue>;
795  std::map<G4String,G4AttDef>* pointAttDefs =
796  new std::map<G4String,G4AttDef>;
797 
798  // Get trajectory point attributes and definitions in standard HepRep style
799  // (uniform units, 3Vectors decomposed).
800  if (rawPointAttValues) {
801  G4bool error = G4AttCheck(rawPointAttValues,
802  aTrajectoryPoint->GetAttDefs()).Standard(pointAttValues,pointAttDefs);
803  if (error) {
804  G4cout << "G4HepRepFileSceneHandler::AddCompound(traj):"
805  "\nERROR found during conversion to standard point attributes." << G4endl;
806  }
807 
808  // Write out point attribute values.
809  if (pointAttValues) {
810  for (iAttVal = pointAttValues->begin();
811  iAttVal != pointAttValues->end(); ++iAttVal)
812  // Do not write out the Aux or Pos attribute. Aux does not conform to the HepRep rule
813  // that each object can have only one instance of a given AttValue.
814  // Both of these attributes are redundant to actual position information of the point.
815  if (strcmp(iAttVal->GetName(),"Aux-X")!=0 &&
816  strcmp(iAttVal->GetName(),"Aux-Y")!=0 &&
817  strcmp(iAttVal->GetName(),"Aux-Z")!=0 &&
818  strcmp(iAttVal->GetName(),"Pos-X")!=0 &&
819  strcmp(iAttVal->GetName(),"Pos-Y")!=0 &&
820  strcmp(iAttVal->GetName(),"Pos-Z")!=0)
821  hepRepXMLWriter->addAttValue(iAttVal->GetName(), iAttVal->GetValue());
822  delete pointAttValues;
823  }
824  delete rawPointAttValues;
825  }
826 
827  // Clean up point attributes.
828  if (pointAttDefs)
829  delete pointAttDefs;
830 
831  // Each trajectory point is made of a single primitive, a point.
832  G4Point3D vertex = aTrajectoryPoint->GetPosition();
833 
834  // Loop over auxiliary points associated with this Trajectory Point.
835  const std::vector<G4ThreeVector>* auxiliaries = aTrajectoryPoint->GetAuxiliaryPoints();
836  if (0 != auxiliaries) {
837  for (size_t iAux=0; iAux<auxiliaries->size(); ++iAux) {
838  const G4ThreeVector auxPos((*auxiliaries)[iAux]);
839  hepRepXMLWriter->addPrimitive();
840  hepRepXMLWriter->addPoint(auxPos.x(), auxPos.y(), auxPos.z());
841  }
842  }
843  }
844  }
845 }
846 
847 
849 #ifdef G4HEPREPFILEDEBUG
850  G4cout << "G4HepRepFileSceneHandler::AddCompound(G4VHit&) " << G4endl;
851 #endif
852 
853  // Pointers to hold hit attribute values and definitions.
854  std::vector<G4AttValue>* rawHitAttValues = hit.CreateAttValues();
855  hitAttValues =
856  new std::vector<G4AttValue>;
857  hitAttDefs =
858  new std::map<G4String,G4AttDef>;
859 
860  // Iterators to use with attribute values and definitions.
861  std::vector<G4AttValue>::iterator iAttVal;
862  std::map<G4String,G4AttDef>::const_iterator iAttDef;
863 
864  // Get hit attributes and definitions in standard HepRep style
865  // (uniform units, 3Vectors decomposed).
866  if (rawHitAttValues) {
867  G4bool error = G4AttCheck(rawHitAttValues,
868  hit.GetAttDefs()).Standard(hitAttValues,hitAttDefs);
869  if (error) {
870  G4cout << "G4HepRepFileSceneHandler::AddCompound(hit):"
871  "\nERROR found during conversion to standard hit attributes."
872  << G4endl;
873  }
874 #ifdef G4HEPREPFILEDEBUG
875  G4cout <<
876  "G4HepRepFileSceneHandler::AddCompound(hit): standardised attributes:\n"
877  << G4AttCheck(hitAttValues,hitAttDefs) << G4endl;
878 #endif
879  delete rawHitAttValues;
880  }
881 
882  // Open the HepRep output file if it is not already open.
883  CheckFileOpen();
884 
885  // Add the Event Data Type if it hasn't already been added.
886  if (strcmp("Event Data",hepRepXMLWriter->prevTypeName[0])!=0) {
887  hepRepXMLWriter->addType("Event Data",0);
888  hepRepXMLWriter->addInstance();
889  }
890 
891  // Find out the current HitType.
892  G4String hitType = "Hits";
893  if (hitAttValues) {
894  G4bool found = false;
895  for (iAttVal = hitAttValues->begin();
896  iAttVal != hitAttValues->end() && !found; ++iAttVal) {
897  if (strcmp(iAttVal->GetName(),"HitType")==0) {
898  hitType = iAttVal->GetValue();
899  found = true;
900  }
901  }
902  }
903 
904  // Add the Hits Type.
905  G4String previousName = hepRepXMLWriter->prevTypeName[1];
906  hepRepXMLWriter->addType(hitType,1);
907 
908  // If this is the first hit of this event,
909  // specify attribute values common to all hits.
910  if (strcmp(hitType,previousName)!=0) {
911  hepRepXMLWriter->addAttValue("Layer",130);
912 
913  // Take all Hit attDefs from first hit.
914  // Would rather be able to get these attDefs without needing a reference from any
915  // particular hit, but don't know how to do that.
916  // Write out hit attribute definitions.
917  if (hitAttValues && hitAttDefs) {
918  for (iAttVal = hitAttValues->begin();
919  iAttVal != hitAttValues->end(); ++iAttVal) {
920  iAttDef = hitAttDefs->find(iAttVal->GetName());
921  if (iAttDef != hitAttDefs->end()) {
922  // Protect against incorrect use of Category. Anything value other than the
923  // standard ones will be considered to be in the physics category.
924  G4String category = iAttDef->second.GetCategory();
925  if (strcmp(category,"Draw")!=0 &&
926  strcmp(category,"Physics")!=0 &&
927  strcmp(category,"Association")!=0 &&
928  strcmp(category,"PickAction")!=0)
929  category = "Physics";
930  hepRepXMLWriter->addAttDef(iAttVal->GetName(), iAttDef->second.GetDesc(),
931  category, iAttDef->second.GetExtra());
932  }
933  }
934  }
935  } // end of special treatment for when this is the first hit.
936 
937  // Now that we have written out all of the attributes that are based on the
938  // hit's particulars, call base class to deconstruct hit into a primitives.
939  drawingHit = true;
940  doneInitHit = false;
941  G4VSceneHandler::AddCompound(hit); // Invoke default action.
942  drawingHit = false;
943 }
944 
945 
947  if (!doneInitTraj) {
948  // For every trajectory, add an instance of Type Trajectory.
949  hepRepXMLWriter->addInstance();
950 
951  // Write out the trajectory's attribute values.
952  if (trajAttValues) {
953  std::vector<G4AttValue>::iterator iAttVal;
954  for (iAttVal = trajAttValues->begin();
955  iAttVal != trajAttValues->end(); ++iAttVal)
956  hepRepXMLWriter->addAttValue(iAttVal->GetName(), iAttVal->GetValue());
957  delete trajAttValues;
958  }
959 
960  // Clean up trajectory attributes.
961  if (trajAttDefs)
962  delete trajAttDefs;
963 
964  doneInitTraj = true;
965  }
966 }
967 
968 
970  if (!doneInitHit) {
971  // For every hit, add an instance of Type Hit.
972  hepRepXMLWriter->addInstance();
973 
974  // Write out the hit's attribute values.
975  if (hitAttValues) {
976  std::vector<G4AttValue>::iterator iAttVal;
977  for (iAttVal = hitAttValues->begin();
978  iAttVal != hitAttValues->end(); ++iAttVal)
979  hepRepXMLWriter->addAttValue(iAttVal->GetName(), iAttVal->GetValue());
980  delete hitAttValues;
981  }
982 
983  // Clean up hit attributes.
984  if (hitAttDefs)
985  delete hitAttDefs;
986 
987  doneInitHit = true;
988  }
989 }
990 
991 
993 #ifdef G4HEPREPFILEDEBUG
994  G4cout <<
995  "G4HepRepFileSceneHandler::AddPrimitive(const G4Polyline& polyline) called:"
996  "\n polyline: " << polyline
997  << G4endl;
998  PrintThings();
999 #endif
1000 
1002 
1003  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
1004  return;
1005 
1006  if (inPrimitives2D) {
1007  if (!warnedAbout2DMarkers) {
1008  G4cout << "HepRepFile does not currently support 2D lines." << G4endl;
1009  warnedAbout2DMarkers = true;
1010  }
1011  return;
1012  }
1013 
1014  if (drawingTraj)
1015  InitTrajectory();
1016 
1017  if (drawingHit)
1018  InitHit();
1019 
1020  haveVisible = true;
1021  AddHepRepInstance("Line", polyline);
1022 
1023  hepRepXMLWriter->addPrimitive();
1024 
1025  for (size_t i=0; i < polyline.size(); i++) {
1026  G4Point3D vertex = (fObjectTransformation) * polyline[i];
1027  hepRepXMLWriter->addPoint(vertex.x(), vertex.y(), vertex.z());
1028  }
1029 }
1030 
1031 
1032 
1034 #ifdef G4HEPREPFILEDEBUG
1035  G4cout <<
1036  "G4HepRepFileSceneHandler::AddPrimitive(const G4Polymarker& line) called"
1037  << G4endl;
1038  PrintThings();
1039 #endif
1040 
1042 
1043  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
1044  return;
1045 
1046  if (inPrimitives2D) {
1047  if (!warnedAbout2DMarkers) {
1048  G4cout << "HepRepFile does not currently support 2D lines." << G4endl;
1049  warnedAbout2DMarkers = true;
1050  }
1051  return;
1052  }
1053 
1054  MarkerSizeType sizeType;
1055  G4double size = GetMarkerSize (line, sizeType);
1056  if (sizeType==world)
1057  size = 4.;
1058 
1059  if (drawingTraj)
1060  return;
1061 
1062  if (drawingHit)
1063  InitHit();
1064 
1065  haveVisible = true;
1066  AddHepRepInstance("Point", line);
1067 
1068  hepRepXMLWriter->addAttValue("MarkName", "Dot");
1069  hepRepXMLWriter->addAttValue("MarkSize", (G4int) size);
1070 
1071  hepRepXMLWriter->addPrimitive();
1072 
1073  for (size_t i=0; i < line.size(); i++) {
1074  G4Point3D vertex = (fObjectTransformation) * line[i];
1075  hepRepXMLWriter->addPoint(vertex.x(), vertex.y(), vertex.z());
1076  }
1077 }
1078 
1079 
1081 #ifdef G4HEPREPFILEDEBUG
1082  G4cout <<
1083  "G4HepRepFileSceneHandler::AddPrimitive(const G4Text& text) called:"
1084  "\n text: " << text.GetText()
1085  << G4endl;
1086  PrintThings();
1087 #endif
1088 
1089  if (!inPrimitives2D) {
1090  if (!warnedAbout3DText) {
1091  G4cout << "HepRepFile does not currently support 3D text." << G4endl;
1092  G4cout << "HepRep browsers can directly display text attributes on request." << G4endl;
1093  G4cout << "See Application Developers Guide for how to attach attributes to viewable objects." << G4endl;
1094  warnedAbout3DText = true;
1095  }
1096  return;
1097  }
1098 
1099  MarkerSizeType sizeType;
1100  G4double size = GetMarkerSize (text, sizeType);
1101  if (sizeType==world)
1102  size = 12.;
1103 
1104  haveVisible = true;
1105  AddHepRepInstance("Text", text);
1106 
1107  hepRepXMLWriter->addAttValue("VAlign", "Top");
1108  hepRepXMLWriter->addAttValue("HAlign", "Left");
1109  hepRepXMLWriter->addAttValue("FontName", "Arial");
1110  hepRepXMLWriter->addAttValue("FontStyle", "Plain");
1111  hepRepXMLWriter->addAttValue("FontSize", (G4int) size);
1112  hepRepXMLWriter->addAttValue("FontHasBanner", "TRUE");
1113  hepRepXMLWriter->addAttValue("FontBannerColor", "0,0,0");
1114 
1115  const G4Colour& colour = GetTextColour(text);
1116  float redness = colour.GetRed();
1117  float greenness = colour.GetGreen();
1118  float blueness = colour.GetBlue();
1119 
1120  // Avoiding drawing anything black on black.
1121  if (redness==0. && greenness==0. && blueness==0.) {
1122  redness = 1.;
1123  greenness = 1.;
1124  blueness = 1.;
1125  }
1126  hepRepXMLWriter->addAttValue("FontColor",redness,greenness,blueness);
1127 
1128  hepRepXMLWriter->addPrimitive();
1129 
1130  hepRepXMLWriter->addAttValue("Text", text.GetText());
1131  hepRepXMLWriter->addAttValue("VPos", .99-text.GetYOffset());
1132  hepRepXMLWriter->addAttValue("HPos", text.GetXOffset());
1133 }
1134 
1135 
1137 #ifdef G4HEPREPFILEDEBUG
1138  G4cout <<
1139  "G4HepRepFileSceneHandler::AddPrimitive(const G4Circle& circle) called:"
1140  "\n radius: " << circle.GetWorldRadius()
1141  << G4endl;
1142  PrintThings();
1143 #endif
1144 
1146 
1147  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
1148  return;
1149 
1150  if (inPrimitives2D) {
1151  if (!warnedAbout2DMarkers) {
1152  G4cout << "HepRepFile does not currently support 2D circles." << G4endl;
1153  warnedAbout2DMarkers = true;
1154  }
1155  return;
1156  }
1157 
1158  MarkerSizeType sizeType;
1159  G4double size = GetMarkerSize (circle, sizeType);
1160  if (sizeType==world)
1161  size = 4.;
1162 
1163  if (drawingTraj)
1164  return;
1165 
1166  if (drawingHit)
1167  InitHit();
1168 
1169  haveVisible = true;
1170  AddHepRepInstance("Point", circle);
1171 
1172  hepRepXMLWriter->addAttValue("MarkName", "Dot");
1173  hepRepXMLWriter->addAttValue("MarkSize", (G4int) size);
1174 
1175  hepRepXMLWriter->addPrimitive();
1176 
1177  G4Point3D center = (fObjectTransformation) * circle.GetPosition();
1178  hepRepXMLWriter->addPoint(center.x(), center.y(), center.z());
1179 }
1180 
1181 
1183 #ifdef G4HEPREPFILEDEBUG
1184  G4cout <<
1185  "G4HepRepFileSceneHandler::AddPrimitive(const G4Square& square) called:"
1186  "\n side: " << square.GetWorldRadius()
1187  << G4endl;
1188  PrintThings();
1189 #endif
1190 
1192 
1193  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
1194  return;
1195 
1196  if (inPrimitives2D) {
1197  if (!warnedAbout2DMarkers) {
1198  G4cout << "HepRepFile does not currently support 2D squares." << G4endl;
1199  warnedAbout2DMarkers = true;
1200  }
1201  return;
1202  }
1203 
1204  MarkerSizeType sizeType;
1205  G4double size = GetMarkerSize (square, sizeType);
1206  if (sizeType==world)
1207  size = 4.;
1208 
1209  if (drawingTraj)
1210  return;
1211 
1212  if (drawingHit)
1213  InitHit();
1214 
1215  haveVisible = true;
1216  AddHepRepInstance("Point", square);
1217 
1218  hepRepXMLWriter->addAttValue("MarkName", "Square");
1219  hepRepXMLWriter->addAttValue("MarkSize", (G4int) size);
1220 
1221  hepRepXMLWriter->addPrimitive();
1222 
1223  G4Point3D center = (fObjectTransformation) * square.GetPosition();
1224  hepRepXMLWriter->addPoint(center.x(), center.y(), center.z());
1225 }
1226 
1227 
1229 #ifdef G4HEPREPFILEDEBUG
1230  G4cout <<
1231  "G4HepRepFileSceneHandler::AddPrimitive(const G4Polyhedron& polyhedron) called."
1232  << G4endl;
1233  PrintThings();
1234 #endif
1235 
1237 
1238  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
1239  return;
1240 
1241  if(polyhedron.GetNoFacets()==0)return;
1242 
1243  if (drawingTraj)
1244  return;
1245 
1246  if (drawingHit)
1247  InitHit();
1248 
1249  haveVisible = true;
1250  AddHepRepInstance("Polygon", polyhedron);
1251 
1252  G4Normal3D surfaceNormal;
1253  G4Point3D vertex;
1254 
1255  G4bool notLastFace;
1256  do {
1257  hepRepXMLWriter->addPrimitive();
1258  notLastFace = polyhedron.GetNextNormal (surfaceNormal);
1259 
1260  G4int edgeFlag = 1;
1261  G4bool notLastEdge;
1262  do {
1263  notLastEdge = polyhedron.GetNextVertex (vertex, edgeFlag);
1264  vertex = (fObjectTransformation) * vertex;
1265  hepRepXMLWriter->addPoint(vertex.x(), vertex.y(), vertex.z());
1266  } while (notLastEdge);
1267  } while (notLastFace);
1268 }
1269 
1270 
1272 #ifdef G4HEPREPFILEDEBUG
1273  G4cout <<
1274  "G4HepRepFileSceneHandler::AddPrimitive(const G4NURBS& nurbs) called."
1275  << G4endl;
1276  PrintThings();
1277 #endif
1278  G4cout << "G4HepRepFileSceneHandler::AddPrimitive G4NURBS : not implemented. " << G4endl;
1279 }
1280 
1281 
1283  return hepRepXMLWriter;
1284 }
1285 
1286 
1287 void G4HepRepFileSceneHandler::AddHepRepInstance(const char* primName,
1288  const G4Visible visible) {
1289 #ifdef G4HEPREPFILEDEBUG
1290  G4cout <<
1291  "G4HepRepFileSceneHandler::AddHepRepInstance called."
1292  << G4endl;
1293 #endif
1294 
1295  // Open the HepRep output file if it is not already open.
1296  CheckFileOpen();
1297 
1298  G4VPhysicalVolume* pCurrentPV = 0;
1299  G4LogicalVolume* pCurrentLV = 0;
1300  G4int currentDepth = 0;
1301  G4PhysicalVolumeModel* pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
1302  if (pPVModel) {
1303  pCurrentPV = pPVModel->GetCurrentPV();
1304  pCurrentLV = pPVModel->GetCurrentLV();
1305  currentDepth = pPVModel->GetCurrentDepth();
1306  }
1307 
1308 #ifdef G4HEPREPFILEDEBUG
1309  G4cout <<
1310  "pCurrentPV:" << pCurrentPV << ", readyForTransients:" << fReadyForTransients
1311  << G4endl;
1312 #endif
1313 
1314  if (drawingTraj || drawingHit) {
1315  // In this case, HepRep type, layer and instance were already created
1316  // in the AddCompound method.
1317  }
1318  else if (fReadyForTransients) {
1319  if (strcmp("Event Data",hepRepXMLWriter->prevTypeName[0])!=0) {
1320  hepRepXMLWriter->addType("Event Data",0);
1321  hepRepXMLWriter->addInstance();
1322  }
1323 
1324  // Applications have the option of either calling AddSolid(G4VTrajectory&) and
1325  // AddSolid(G4VHits&), or of just decomposing these into simpler primitives.
1326  // In the former case, drawing will be handled above and will include setting of
1327  // physics attributes.
1328  // In the latter case, which is an older style of working, we end up drawing the
1329  // trajectories and hits here, where we have no access to physics attributes.
1330  // We receive primitives here. We can figure out that these are transients, but we
1331  // have to guess exactly what these transients represent.
1332  // We assume the primitives are being used as in G4VTrajectory, hence we assume:
1333  // Lines are Trajectories
1334  // Squares that come after we've seen trajectories are Auxiliary Points
1335  // Circles that come after we've seen trajectories are Step Points
1336  // Other primitives are Hits
1337 
1338  int layer;
1339 
1340  if (strcmp("Text",primName)==0) {
1341  hepRepXMLWriter->addType("EventID",1);
1342  } else {
1343  if (strcmp("Line",primName)==0) {
1344  hepRepXMLWriter->addType("TransientPolylines",1);
1345  layer = 100;
1346  } else {
1347  if (strcmp(hepRepXMLWriter->prevTypeName[1],"TransientPolylines")==0 &&
1348  strcmp("Square",primName)==0)
1349  {
1350  hepRepXMLWriter->addType("AuxiliaryPoints",2);
1351  layer = 110;
1352  } else {
1353  if (strcmp(hepRepXMLWriter->prevTypeName[1],"TransientPolylines")==0 &&
1354  strcmp("Circle",primName)==0)
1355  {
1356  hepRepXMLWriter->addType("StepPoints",2);
1357  layer = 120;
1358  } else {
1359  hepRepXMLWriter->addType("Hits",1);
1360  layer = 130;
1361  }
1362  }
1363  }
1364  hepRepXMLWriter->addAttValue("Layer",layer);
1365  }
1366 
1367  hepRepXMLWriter->addInstance();
1368 
1369  // Handle Type declaration for Axes, Ruler, etc.
1370  } else if (pCurrentPV==0) {
1371  if (strcmp("AxesEtc",hepRepXMLWriter->prevTypeName[0])!=0) {
1372  hepRepXMLWriter->addType("AxesEtc",0);
1373  hepRepXMLWriter->addInstance();
1374  }
1375 
1376  int layer;
1377 
1378  if (strcmp("Text",primName)==0) {
1379  hepRepXMLWriter->addType("Text",1);
1380  } else {
1381  if (strcmp("Line",primName)==0) {
1382  hepRepXMLWriter->addType("Polylines",1);
1383  layer = 100;
1384  } else {
1385  hepRepXMLWriter->addType("Points",1);
1386  layer = 130;
1387  }
1388  hepRepXMLWriter->addAttValue("Layer",layer);
1389  }
1390 
1391  hepRepXMLWriter->addInstance();
1392 
1393  // Handle Type declaration for Detector Geometry,
1394  // replacing G4's top geometry level name "worldPhysical" with the
1395  // name "Detector Geometry".
1396  } else {
1397  //G4cout << "CurrentDepth" << currentDepth << G4endl;
1398  //G4cout << "currentName" << pCurrentPV->GetName() << G4endl;
1399  if (strcmp("Detector Geometry",hepRepXMLWriter->prevTypeName[0])!=0) {
1400  //G4cout << "Adding Det Geom type" << G4endl;
1401  hepRepXMLWriter->addType("Detector Geometry",0);
1402  hepRepXMLWriter->addInstance();
1403  }
1404 
1405  // Re-insert any layers of the hierarchy that were removed by G4's culling process.
1406  // Don't bother checking if same type name as last instance.
1407  if(strcmp(hepRepXMLWriter->prevTypeName[currentDepth+1],pCurrentPV->GetName())!=0) {
1408  //G4cout << "Looking for mother of:" << pCurrentLV->GetName() << G4endl;
1410  typedef std::vector<PVNodeID> PVPath;
1411  const PVPath& drawnPVPath = pPVModel->GetDrawnPVPath();
1412  PVPath::const_reverse_iterator ri = ++drawnPVPath.rbegin();
1413  G4int drawnMotherDepth;
1414  if (ri != drawnPVPath.rend()) {
1415  // This volume has a mother.
1416  drawnMotherDepth = ri->GetNonCulledDepth();
1417  //G4cout << "drawnMotherDepth" << drawnMotherDepth << G4endl;
1418  } else {
1419  // This volume has no mother. Must be a top level volume.
1420  drawnMotherDepth = -1;
1421  //G4cout << "Mother must be very top" << G4endl;
1422  }
1423 
1424  while (drawnMotherDepth < (currentDepth-1)) {
1425  G4String culledParentName = "Culled parent of " + pCurrentPV->GetName();
1426  //G4cout << "Inserting culled layer " << culledParentName << " at depth:" << drawnMotherDepth+2 << G4endl;
1427  hepRepXMLWriter->addType(culledParentName, drawnMotherDepth+2);
1428  hepRepXMLWriter->addInstance();
1429  drawnMotherDepth ++;
1430  }
1431  }
1432 
1433  // Add the HepRepType for the current volume.
1434  hepRepXMLWriter->addType(pCurrentPV->GetName(),currentDepth+1);
1435  hepRepXMLWriter->addInstance();
1436 
1438 
1439  if (fpVisAttribs && (fpVisAttribs->IsVisible()==0) && messenger->getCullInvisibles())
1440  return;
1441 
1442  // Additional attributes.
1443  hepRepXMLWriter->addAttValue("Layer",hepRepXMLWriter->typeDepth);
1444  hepRepXMLWriter->addAttValue("LVol", pCurrentLV->GetName());
1445  G4Region* region = pCurrentLV->GetRegion();
1446  G4String regionName = region? region->GetName(): G4String("No region");
1447  hepRepXMLWriter->addAttValue("Region", regionName);
1448  hepRepXMLWriter->addAttValue("RootRegion", pCurrentLV->IsRootRegion());
1449  hepRepXMLWriter->addAttValue("Solid", pCurrentLV->GetSolid()->GetName());
1450  hepRepXMLWriter->addAttValue("EType", pCurrentLV->GetSolid()->GetEntityType());
1451  G4Material * material = pPVModel->GetCurrentMaterial();
1452  G4String matName = material? material->GetName(): G4String("No material");
1453  hepRepXMLWriter->addAttValue("Material", matName);
1454  G4double matDensity = material? material->GetDensity(): 0.;
1455  hepRepXMLWriter->addAttValue("Density", matDensity*m3/kg);
1456  G4State matState = material? material->GetState(): kStateUndefined;
1457  hepRepXMLWriter->addAttValue("State", matState);
1458  G4double matRadlen = material? material->GetRadlen(): 0.;
1459  hepRepXMLWriter->addAttValue("Radlen", matRadlen/m);
1460  }
1461 
1462  hepRepXMLWriter->addAttValue("DrawAs",primName);
1463 
1464  // Handle color and visibility attributes.
1465  float redness;
1466  float greenness;
1467  float blueness;
1468  G4bool isVisible;
1469 
1470  if (fpVisAttribs || haveVisible) {
1471  G4Colour colour;
1472 
1473  if (fpVisAttribs) {
1474  colour = fpVisAttribs->GetColour();
1475  isVisible = fpVisAttribs->IsVisible();
1476  } else {
1477  colour = GetColour(visible);
1478  isVisible = fpViewer->
1479  GetApplicableVisAttributes(visible.GetVisAttributes())->IsVisible();
1480  }
1481 
1482  redness = colour.GetRed();
1483  greenness = colour.GetGreen();
1484  blueness = colour.GetBlue();
1485 
1486  // Avoiding drawing anything black on black.
1487  if (redness==0. && greenness==0. && blueness==0.) {
1488  redness = 1.;
1489  greenness = 1.;
1490  blueness = 1.;
1491  }
1492  } else {
1493 #ifdef G4HEPREPFILEDEBUG
1494  G4cout <<
1495  "G4HepRepFileSceneHandler::AddHepRepInstance using default colour."
1496  << G4endl;
1497 #endif
1498  redness = 1.;
1499  greenness = 1.;
1500  blueness = 1.;
1501  isVisible = true;
1502  }
1503 
1504  if (strcmp(primName,"Point")==0)
1505  hepRepXMLWriter->addAttValue("MarkColor",redness,greenness,blueness);
1506  else
1507  hepRepXMLWriter->addAttValue("LineColor",redness,greenness,blueness);
1508 
1509  hepRepXMLWriter->addAttValue("Visibility",isVisible);
1510 }
1511 
1512 
1513 void G4HepRepFileSceneHandler::CheckFileOpen() {
1514 #ifdef G4HEPREPFILEDEBUG
1515  G4cout <<
1516  "G4HepRepFileSceneHandler::CheckFileOpen called."
1517  << G4endl;
1518 #endif
1519 
1520  if (!hepRepXMLWriter->isOpen) {
1521  G4String newFileSpec;
1522 
1524 
1525  if (messenger->getOverwrite()) {
1526  newFileSpec = messenger->getFileDir()+messenger->getFileName()+".heprep";
1527  } else {
1528  newFileSpec = messenger->getFileDir()+messenger->getFileName()+G4UIcommand::ConvertToString(fileCounter)+".heprep";
1529  }
1530 
1531  G4cout << "HepRepFile writing to " << newFileSpec << G4endl;
1532 
1533  hepRepXMLWriter->open(newFileSpec);
1534 
1535  if (!messenger->getOverwrite())
1536  fileCounter++;
1537 
1538  hepRepXMLWriter->addAttDef("Generator", "HepRep Data Generator", "Physics","");
1539  G4String versionString = G4Version;
1540  versionString = versionString.substr(1,versionString.size()-2);
1541  versionString = " Geant4 version " + versionString + " " + G4Date;
1542  hepRepXMLWriter->addAttValue("Generator", versionString);
1543 
1544  hepRepXMLWriter->addAttDef("LVol", "Logical Volume", "Physics","");
1545  hepRepXMLWriter->addAttDef("Region", "Cuts Region", "Physics","");
1546  hepRepXMLWriter->addAttDef("RootRegion", "Root Region", "Physics","");
1547  hepRepXMLWriter->addAttDef("Solid", "Solid Name", "Physics","");
1548  hepRepXMLWriter->addAttDef("EType", "Entity Type", "Physics","");
1549  hepRepXMLWriter->addAttDef("Material", "Material Name", "Physics","");
1550  hepRepXMLWriter->addAttDef("Density", "Material Density", "Physics","kg/m3");
1551  hepRepXMLWriter->addAttDef("State", "Material State", "Physics","");
1552  hepRepXMLWriter->addAttDef("Radlen", "Material Radiation Length", "Physics","m");
1553  }
1554 }
1555 
1556 
1558  // This is typically called after an update and before drawing hits
1559  // of the next event. To simulate the clearing of "transients"
1560  // (hits, etc.) the detector is redrawn...
1561  if (fpViewer) {
1562  fpViewer -> SetView();
1563  fpViewer -> ClearView();
1564  fpViewer -> DrawView();
1565  }
1566 }