Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/visualization/management/src/G4ViewParameters.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ]

  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 //
 27 //
 28 // 
 29 // John Allison  19th July 1996
 30 // View parameters and options.
 31 
 32 #include "G4ViewParameters.hh"
 33 
 34 #include "G4VisManager.hh"
 35 #include "G4VPhysicalVolume.hh"
 36 #include "G4UnitsTable.hh"
 37 #include "G4SystemOfUnits.hh"
 38 #include "G4Polyhedron.hh"
 39 
 40 #include <sstream>
 41 #include <cmath>
 42 
 43 G4ViewParameters::G4ViewParameters ():
 44   fDrawingStyle (wireframe),
 45   fNumberOfCloudPoints(10000),
 46   fAuxEdgeVisible (false),
 47   fCulling (true),
 48   fCullInvisible (true),
 49   fDensityCulling (false),
 50   fVisibleDensity (0.01 * g / cm3),
 51   fCullCovered (false),
 52   fCBDAlgorithmNumber (0),
 53   fSection (false),
 54   fSectionPlane (),
 55   fCutawayMode (cutawayUnion),
 56   fCutawayPlanes (),
 57   fExplodeFactor (1.),
 58   fNoOfSides (),
 59   fViewpointDirection (G4Vector3D (0., 0., 1.)),  // On z-axis.
 60   fUpVector (G4Vector3D (0., 1., 0.)),            // y-axis up.
 61   fFieldHalfAngle (0.),                           // Orthogonal projection.
 62   fZoomFactor (1.),
 63   fScaleFactor (G4Vector3D (1., 1., 1.)),
 64   fCurrentTargetPoint (),
 65   fDolly (0.),
 66   fLightsMoveWithCamera (false),
 67   fRelativeLightpointDirection (G4Vector3D (1., 1., 1.)),
 68   fActualLightpointDirection (G4Vector3D (1., 1., 1.)),
 69   fDefaultVisAttributes (),
 70   fDefaultTextVisAttributes (G4Colour (0., 0., 1.)),
 71   fDefaultMarker (),
 72   fGlobalMarkerScale (1.),
 73   fGlobalLineWidthScale (1.),
 74   fMarkerNotHidden (true),
 75   fWindowSizeHintX (600),
 76   fWindowSizeHintY (600),
 77   fWindowLocationHintX(0),
 78   fWindowLocationHintY(0),
 79   fWindowLocationHintXNegative(true),
 80   fWindowLocationHintYNegative(false),
 81   fGeometryMask(0),
 82   fAutoRefresh (false),
 83   fBackgroundColour (G4Colour(0.,0.,0.)),         // Black
 84   fPicking (false),
 85   fRotationStyle (constrainUpDirection),
 86   fStartTime(-G4VisAttributes::fVeryLongTime),
 87   fEndTime(G4VisAttributes::fVeryLongTime),
 88   fFadeFactor(0.),
 89   fDisplayHeadTime(false),
 90   fDisplayHeadTimeX(-0.9),
 91   fDisplayHeadTimeY(-0.9),
 92   fDisplayHeadTimeSize(24.),
 93   fDisplayHeadTimeRed(0.),
 94   fDisplayHeadTimeGreen(1.),
 95   fDisplayHeadTimeBlue(1.),
 96   fDisplayLightFront(false),
 97   fDisplayLightFrontX(0.),
 98   fDisplayLightFrontY(0.),
 99   fDisplayLightFrontZ(0.),
100   fDisplayLightFrontT(0.),
101   fDisplayLightFrontRed(0.),
102   fDisplayLightFrontGreen(1.),
103   fDisplayLightFrontBlue(0.)
104 {
105   // Pick up default no of sides from G4Polyhedron.
106   // Note that this parameter is variously called:
107   //   No of sides
108   //   NumberOfRotationSteps
109   //   Line segments per circle
110   // It refers to the approximation of a circle by a polygon of
111   // stated number of sides.
112   fNoOfSides = G4Polyhedron::GetNumberOfRotationSteps();
113   
114   fDefaultMarker.SetScreenSize (5.);
115   // Markers are 5 pixels "overall" size, i.e., diameter.
116 }
117 
118 G4ViewParameters::~G4ViewParameters () {}
119 
120 void G4ViewParameters::MultiplyScaleFactor
121 (const G4Vector3D& scaleFactorMultiplier) {
122   fScaleFactor.setX(fScaleFactor.x() * scaleFactorMultiplier.x());
123   fScaleFactor.setY(fScaleFactor.y() * scaleFactorMultiplier.y());
124   fScaleFactor.setZ(fScaleFactor.z() * scaleFactorMultiplier.z());
125 }
126 
127 G4Vector3D& G4ViewParameters::GetActualLightpointDirection () {
128   SetViewAndLights (fViewpointDirection);
129   return fActualLightpointDirection;
130 }
131 
132 // Useful quantities - begin snippet.
133 // Here Follow functions to evaluate the above algorithms as a
134 // function of the radius of the Bounding Sphere of the object being
135 // viewed.  Call them in the order given - for efficiency, later
136 // functions depend on the results of earlier ones (Store the
137 // results of earlier functions in your own temporary variables -
138 // see, for example, G4OpenGLView::SetView ().)
139 
140 G4double G4ViewParameters::GetCameraDistance (G4double radius) const {
141   G4double cameraDistance;
142   if (fFieldHalfAngle == 0.) {
143     cameraDistance = radius;
144   }
145   else {
146     cameraDistance = radius / std::sin (fFieldHalfAngle) - fDolly;
147   }
148   return cameraDistance;
149 }
150 
151 G4double G4ViewParameters::GetNearDistance (G4double cameraDistance,
152               G4double radius) const {
153   const G4double small = 1.e-6 * radius;
154   G4double nearDistance = cameraDistance - radius;
155   if (nearDistance < small) nearDistance = small;
156   return nearDistance;
157 }
158 
159 G4double G4ViewParameters::GetFarDistance (G4double cameraDistance,
160              G4double nearDistance,
161              G4double radius) const {
162   G4double farDistance = cameraDistance + radius;
163   if (farDistance < nearDistance) farDistance = nearDistance;
164   return farDistance;
165 }
166 
167 G4double G4ViewParameters::GetFrontHalfHeight (G4double nearDistance,
168                  G4double radius) const {
169   G4double frontHalfHeight;
170   if (fFieldHalfAngle == 0.) {
171     frontHalfHeight = radius / fZoomFactor;
172   }
173   else {
174     frontHalfHeight = nearDistance * std::tan (fFieldHalfAngle) / fZoomFactor;
175   }
176   return frontHalfHeight;
177 }
178 // Useful quantities - end snippet.
179 
180 void G4ViewParameters::AddCutawayPlane (const G4Plane3D& cutawayPlane) {
181   if (fCutawayPlanes.size () < 3 ) {
182     fCutawayPlanes.push_back (cutawayPlane);
183   }
184   else {
185     G4cerr <<
186       "ERROR: G4ViewParameters::AddCutawayPlane:"
187       "\n  A maximum of 3 cutaway planes supported." << G4endl;
188   }
189 }
190 
191 void G4ViewParameters::ChangeCutawayPlane
192 (size_t index, const G4Plane3D& cutawayPlane) {
193   if (index >= fCutawayPlanes.size()) {
194     G4cerr <<
195       "ERROR: G4ViewParameters::ChangeCutawayPlane:"
196       "\n  Plane " << index << " does not exist." << G4endl;
197   } else {
198     fCutawayPlanes[index] = cutawayPlane;
199   }
200 }
201 
202 void G4ViewParameters::SetVisibleDensity (G4double visibleDensity) {
203   const G4double reasonableMaximum = 10.0 * g / cm3;
204   if (visibleDensity < 0) {
205     G4cout << "G4ViewParameters::SetVisibleDensity: attempt to set negative "
206       "density - ignored." << G4endl;
207   }
208   else {
209     if (visibleDensity > reasonableMaximum) {
210       G4cout << "G4ViewParameters::SetVisibleDensity: density > "
211        << G4BestUnit (reasonableMaximum, "Volumic Mass")
212        << " - did you mean this?"
213        << G4endl;
214     }
215     fVisibleDensity = visibleDensity;
216   }
217 }
218 
219 G4int G4ViewParameters::SetNoOfSides (G4int nSides) {
220   const G4int nSidesMin = fDefaultVisAttributes.GetMinLineSegmentsPerCircle();
221   if (nSides < nSidesMin) {
222     nSides = nSidesMin;
223     G4cout << "G4ViewParameters::SetNoOfSides: attempt to set the"
224     "\nnumber of sides per circle < " << nSidesMin
225     << "; forced to " << nSides << G4endl;
226   }
227   fNoOfSides = nSides;
228   return fNoOfSides;
229 }
230 
231 G4int G4ViewParameters::SetNumberOfCloudPoints(G4int nPoints) {
232   const G4int nPointsMin = 100;
233   if (nPoints < nPointsMin) {
234     nPoints = nPointsMin;
235     G4cout << "G4ViewParameters::SetNumberOfCloudPoints:"
236     "\nnumber of points per cloud set to minimum " << nPoints
237     << G4endl;
238   }
239   fNumberOfCloudPoints = nPoints;
240   return fNumberOfCloudPoints;
241 }
242 
243 void G4ViewParameters::SetViewAndLights
244 (const G4Vector3D& viewpointDirection) {
245 
246   fViewpointDirection = viewpointDirection;
247 
248   // If the requested viewpoint direction is parallel to the up
249   // vector, the orientation of the view is undefined...
250   if (fViewpointDirection.unit() * fUpVector.unit() > .9999) {
251     static G4bool firstTime = true;
252     if (firstTime) {
253       firstTime = false;
254       G4cout <<
255       "WARNING: Viewpoint direction is very close to the up vector direction."
256       "\n  Change the up vector or \"/vis/viewer/set/rotationStyle freeRotation\"."
257       << G4endl;
258     }
259   }
260 
261   // Move the lights too if requested...
262   if (fLightsMoveWithCamera) {
263     G4Vector3D zprime = fViewpointDirection.unit ();
264     G4Vector3D xprime = (fUpVector.cross (zprime)).unit ();
265     G4Vector3D yprime = zprime.cross (xprime);
266     fActualLightpointDirection =
267       fRelativeLightpointDirection.x () * xprime +
268       fRelativeLightpointDirection.y () * yprime +
269       fRelativeLightpointDirection.x () * zprime;     
270   } else {
271     fActualLightpointDirection = fRelativeLightpointDirection;
272   }
273 }
274 
275 void G4ViewParameters::SetLightpointDirection
276 (const G4Vector3D& lightpointDirection) {
277   fRelativeLightpointDirection = lightpointDirection;
278   SetViewAndLights (fViewpointDirection);
279 }
280 
281 void G4ViewParameters::SetPan (G4double right, G4double up) {
282   G4Vector3D unitRight = (fUpVector.cross (fViewpointDirection)).unit();
283   G4Vector3D unitUp    = (fViewpointDirection.cross (unitRight)).unit();
284   fCurrentTargetPoint  = right * unitRight + up * unitUp;
285 }
286 
287 void G4ViewParameters::IncrementPan (G4double right, G4double up) {
288   IncrementPan (right,up, 0);
289 }
290 
291 void G4ViewParameters::IncrementPan (G4double right, G4double up, G4double distance) {
292   G4Vector3D unitRight = (fUpVector.cross (fViewpointDirection)).unit();
293   G4Vector3D unitUp    = (fViewpointDirection.cross (unitRight)).unit();
294   fCurrentTargetPoint += right * unitRight + up * unitUp + distance * fViewpointDirection;
295 }
296 
297 void G4ViewParameters::AddVisAttributesModifier
298 (const G4ModelingParameters::VisAttributesModifier& vam) {
299   // If target exists with same signifier just change vis attributes.
300   G4bool duplicateTarget = false;
301   auto i = fVisAttributesModifiers.begin();
302   for (; i < fVisAttributesModifiers.end(); ++i) {
303     if (vam.GetPVNameCopyNoPath() == (*i).GetPVNameCopyNoPath() &&
304         vam.GetVisAttributesSignifier() == (*i).GetVisAttributesSignifier()) {
305       duplicateTarget = true;
306       break;
307     }
308   }
309   if (duplicateTarget) (*i).SetVisAttributes(vam.GetVisAttributes());
310   else fVisAttributesModifiers.push_back(vam);
311 }
312 
313 G4String G4ViewParameters::CameraAndLightingCommands
314 (const G4Point3D standardTargetPoint) const
315 {
316   std::ostringstream oss;
317 
318   oss << "#\n# Camera and lights commands";
319   
320   oss << "\n/vis/viewer/set/viewpointVector "
321   << fViewpointDirection.x()
322   << ' ' << fViewpointDirection.y()
323   << ' ' << fViewpointDirection.z();
324   
325   oss << "\n/vis/viewer/set/upVector "
326   << fUpVector.x()
327   << ' ' << fUpVector.y()
328   << ' ' << fUpVector.z();
329   
330   oss << "\n/vis/viewer/set/projection ";
331     if (fFieldHalfAngle == 0.) {
332     oss
333     << "orthogonal";
334   } else {
335     oss
336     << "perspective "
337     << fFieldHalfAngle/deg
338     << " deg";
339   }
340   
341   oss << "\n/vis/viewer/zoomTo "
342   << fZoomFactor;
343   
344   oss << "\n/vis/viewer/scaleTo "
345   << fScaleFactor.x()
346   << ' ' << fScaleFactor.y()
347   << ' ' << fScaleFactor.z();
348   
349   oss << "\n/vis/viewer/set/targetPoint "
350   << G4BestUnit(standardTargetPoint+fCurrentTargetPoint,"Length")
351   << "\n# Note that if you have not set a target point, the vis system sets"
352   << "\n# a target point based on the scene - plus any panning and dollying -"
353   << "\n# so don't be alarmed by strange coordinates here.";
354   
355   oss << "\n/vis/viewer/dollyTo "
356   << G4BestUnit(fDolly,"Length");
357   
358   oss << "\n/vis/viewer/set/lightsMove ";
359   if (fLightsMoveWithCamera) {
360     oss << "camera";
361   } else {
362     oss << "object";
363   }
364   
365   oss << "\n/vis/viewer/set/lightsVector "
366   << fRelativeLightpointDirection.x()
367   << ' ' << fRelativeLightpointDirection.y()
368   << ' ' << fRelativeLightpointDirection.z();
369   
370   oss << "\n/vis/viewer/set/rotationStyle ";
371   if (fRotationStyle == constrainUpDirection) {
372     oss << "constrainUpDirection";
373   } else {
374     oss << "freeRotation";
375   }
376   
377   G4Colour c = fBackgroundColour;
378   oss << "\n/vis/viewer/set/background "
379   << c.GetRed()
380   << ' ' << c.GetGreen()
381   << ' ' << c.GetBlue()
382   << ' ' << c.GetAlpha();
383   
384   c = fDefaultVisAttributes.GetColour();
385   oss << "\n/vis/viewer/set/defaultColour "
386   << c.GetRed()
387   << ' ' << c.GetGreen()
388   << ' ' << c.GetBlue()
389   << ' ' << c.GetAlpha();
390   
391   c = fDefaultTextVisAttributes.GetColour();
392   oss << "\n/vis/viewer/set/defaultTextColour "
393   << c.GetRed()
394   << ' ' << c.GetGreen()
395   << ' ' << c.GetBlue()
396   << ' ' << c.GetAlpha();
397   
398   oss << std::endl;
399   
400   return oss.str();
401 }
402 
403 G4String G4ViewParameters::DrawingStyleCommands() const
404 {
405   std::ostringstream oss;
406   
407   oss << "#\n# Drawing style commands";
408   
409   oss << "\n/vis/viewer/set/style ";
410   switch (fDrawingStyle) {
411     case wireframe:
412     case hlr:
413       oss << "wireframe";
414       break;
415     case hsr:
416     case hlhsr:
417       oss << "surface";
418       break;
419     case cloud:
420       oss << "cloud";
421       break;
422   }
423 
424   oss << "\n/vis/viewer/set/hiddenEdge ";
425   if (fDrawingStyle == hlr || fDrawingStyle == hlhsr) {
426     oss << "true";
427   } else {
428     oss << "false";
429   }
430   
431   oss << "\n/vis/viewer/set/auxiliaryEdge ";
432   if (fAuxEdgeVisible) {
433     oss << "true";
434   } else {
435     oss << "false";
436   }
437   
438   oss << "\n/vis/viewer/set/hiddenMarker ";
439   if (fMarkerNotHidden) {
440     oss << "false";
441   } else {
442     oss << "true";
443   }
444   
445   oss << "\n/vis/viewer/set/globalLineWidthScale "
446   << fGlobalLineWidthScale;
447   
448   oss << "\n/vis/viewer/set/globalMarkerScale "
449   << fGlobalMarkerScale;
450 
451   oss << "\n/vis/viewer/set/numberOfCloudPoints "
452   << fNumberOfCloudPoints;
453 
454   oss << std::endl;
455   
456   return oss.str();
457 }
458 
459 G4String G4ViewParameters::SceneModifyingCommands() const
460 {
461   std::ostringstream oss;
462   
463   oss << "#\n# Scene-modifying commands";
464   
465   oss << "\n/vis/viewer/set/culling global ";
466   if (fCulling) {
467     oss << "true";
468   } else {
469     oss << "false";
470   }
471 
472   oss << "\n/vis/viewer/set/culling invisible ";
473   if (fCullInvisible) {
474     oss << "true";
475   } else {
476     oss << "false";
477   }
478   
479   oss << "\n/vis/viewer/set/culling density ";
480   if (fDensityCulling) {
481     oss << "true " << fVisibleDensity/(g/cm3) << " g/cm3";
482   } else {
483     oss << "false";
484   }
485   
486   oss << "\n/vis/viewer/set/culling coveredDaughters ";
487   if (fCullCovered) {
488     oss << "true";
489   } else {
490     oss << "false";
491   }
492 
493   oss << "\n/vis/viewer/colourByDensity "
494   << fCBDAlgorithmNumber << " g/cm3";
495   for (auto p: fCBDParameters) {
496     oss << ' ' << p/(g/cm3);
497   }
498 
499   oss << "\n/vis/viewer/set/sectionPlane ";
500   if (fSection) {
501     oss << "on "
502     << G4BestUnit(fSectionPlane.point(),"Length")
503     << fSectionPlane.normal().x()
504     << ' ' << fSectionPlane.normal().y()
505     << ' ' << fSectionPlane.normal().z();
506   } else {
507     oss << "off";
508   }
509   
510   oss << "\n/vis/viewer/set/cutawayMode ";
511   if (fCutawayMode == cutawayUnion) {
512     oss << "union";
513   } else {
514     oss << "intersection";
515   }
516   
517   oss << "\n/vis/viewer/clearCutawayPlanes";
518   if (fCutawayPlanes.size()) {
519     for (size_t i = 0; i < fCutawayPlanes.size(); i++) {
520       oss << "\n/vis/viewer/addCutawayPlane "
521       << G4BestUnit(fCutawayPlanes[i].point(),"Length")
522       << fCutawayPlanes[i].normal().x()
523       << ' ' << fCutawayPlanes[i].normal().y()
524       << ' ' << fCutawayPlanes[i].normal().z();
525     }
526   } else {
527     oss << "\n# No cutaway planes defined.";
528   }
529   
530   oss << "\n/vis/viewer/set/explodeFactor "
531   << fExplodeFactor
532   << ' ' << G4BestUnit(fExplodeCentre,"Length");
533   
534   oss << "\n/vis/viewer/set/lineSegmentsPerCircle "
535   << fNoOfSides;
536   
537   oss << std::endl;
538   
539   return oss.str();
540 }
541 
542 G4String G4ViewParameters::TouchableCommands() const
543 {
544   std::ostringstream oss;
545   
546   oss << "#\n# Touchable commands";
547 
548   const std::vector<G4ModelingParameters::VisAttributesModifier>& vams =
549     fVisAttributesModifiers;
550 
551   if (vams.empty()) {
552     oss
553     << "\n# None"
554     << "\n/vis/viewer/clearVisAttributesModifiers";
555     oss << std::endl;
556     return oss.str();
557   }
558 
559   oss
560   << "\n/vis/viewer/clearVisAttributesModifiers";
561 
562   G4ModelingParameters::PVNameCopyNoPath lastPath;
563   std::vector<G4ModelingParameters::VisAttributesModifier>::const_iterator
564     iModifier;
565   for (iModifier = vams.begin();
566        iModifier != vams.end();
567        ++iModifier) {
568     const G4ModelingParameters::PVNameCopyNoPath& vamPath =
569       iModifier->GetPVNameCopyNoPath();
570     if (vamPath != lastPath) {
571       lastPath = vamPath;
572       oss << "\n/vis/set/touchable";
573       G4ModelingParameters::PVNameCopyNoPathConstIterator iVAM;
574       for (iVAM = vamPath.begin();
575            iVAM != vamPath.end();
576            ++iVAM) {
577         oss << ' ' << iVAM->GetName() << ' ' << iVAM->GetCopyNo();
578       }
579     }
580     const G4VisAttributes& vamVisAtts = iModifier->GetVisAttributes();
581     const G4Colour& c = vamVisAtts.GetColour();
582     switch (iModifier->GetVisAttributesSignifier()) {
583       case G4ModelingParameters::VASVisibility:
584         oss << "\n/vis/touchable/set/visibility ";
585         if (vamVisAtts.IsVisible()) {
586           oss << "true";
587         } else {
588           oss << "false";
589         }
590         break;
591       case G4ModelingParameters::VASDaughtersInvisible:
592         oss << "\n/vis/touchable/set/daughtersInvisible ";
593         if (vamVisAtts.IsDaughtersInvisible()) {
594           oss << "true";
595         } else {
596           oss << "false";
597         }
598         break;
599       case G4ModelingParameters::VASColour:
600         oss << "\n/vis/touchable/set/colour "
601         << c.GetRed()
602         << ' ' << c.GetGreen()
603         << ' ' << c.GetBlue()
604         << ' ' << c.GetAlpha();
605         break;
606       case G4ModelingParameters::VASLineStyle:
607         oss << "\n/vis/touchable/set/lineStyle ";
608         switch (vamVisAtts.GetLineStyle()) {
609           case G4VisAttributes::unbroken:
610             oss << "unbroken";
611             break;
612           case G4VisAttributes::dashed:
613             oss << "dashed";
614             break;
615           case G4VisAttributes::dotted:
616           oss << "dotted";
617         }
618         break;
619       case G4ModelingParameters::VASLineWidth:
620         oss << "\n/vis/touchable/set/lineWidth "
621         << vamVisAtts.GetLineWidth();
622         break;
623       case G4ModelingParameters::VASForceWireframe:
624         if (vamVisAtts.IsForceDrawingStyle()) {
625           if (vamVisAtts.GetForcedDrawingStyle() == G4VisAttributes::wireframe) {
626             oss << "\n/vis/touchable/set/forceWireframe ";
627             if (vamVisAtts.IsForceDrawingStyle()) {
628               oss << "true";
629             } else {
630               oss << "false";
631             }
632           }
633         }
634         break;
635       case G4ModelingParameters::VASForceSolid:
636         if (vamVisAtts.IsForceDrawingStyle()) {
637           if (vamVisAtts.GetForcedDrawingStyle() == G4VisAttributes::solid) {
638             oss << "\n/vis/touchable/set/forceSolid ";
639             if (vamVisAtts.IsForceDrawingStyle()) {
640               oss << "true";
641             } else {
642               oss << "false";
643             }
644           }
645         }
646         break;
647       case G4ModelingParameters::VASForceCloud:
648         if (vamVisAtts.IsForceDrawingStyle()) {
649           if (vamVisAtts.GetForcedDrawingStyle() == G4VisAttributes::cloud) {
650             oss << "\n/vis/touchable/set/forceCloud ";
651             if (vamVisAtts.IsForceDrawingStyle()) {
652               oss << "true";
653             } else {
654               oss << "false";
655             }
656           }
657         }
658         break;
659       case G4ModelingParameters::VASForceAuxEdgeVisible:
660         if (vamVisAtts.IsForceAuxEdgeVisible()) {
661           oss << "\n/vis/touchable/set/forceAuxEdgeVisible ";
662           if (vamVisAtts.IsForcedAuxEdgeVisible()) {
663             oss << "true";
664           } else {
665             oss << "false";
666           }
667         }
668         break;
669       case G4ModelingParameters::VASForceLineSegmentsPerCircle:
670         oss << "\n/vis/touchable/set/lineSegmentsPerCircle "
671         << vamVisAtts.GetForcedLineSegmentsPerCircle();
672         break;
673       case G4ModelingParameters::VASForceNumberOfCloudPoints:
674         oss << "\n/vis/touchable/set/numberOfCloudPoints "
675         << vamVisAtts.GetForcedNumberOfCloudPoints();
676         break;
677     }
678   }
679   
680   oss << std::endl;
681   
682   return oss.str();
683 }
684 
685 G4String G4ViewParameters::TimeWindowCommands() const
686 {
687   std::ostringstream oss;
688 
689   oss <<  "#\n# Time window commands";
690 
691   oss
692   << "\n/vis/viewer/set/timeWindow/startTime "
693   << fStartTime/ns << " ns ";
694 
695   oss
696   << "\n/vis/viewer/set/timeWindow/endTime "
697   << fEndTime/ns << " ns ";
698 
699   oss << "\n/vis/viewer/set/timeWindow/fadeFactor "
700   << fFadeFactor;
701 
702   oss
703   << "\n/vis/viewer/set/timeWindow/displayHeadTime ";
704   if (!fDisplayHeadTime) {
705     oss << "false";
706   } else {
707     oss
708     << "true"
709     << ' ' << fDisplayHeadTimeX
710     << ' ' << fDisplayHeadTimeY
711     << ' ' << fDisplayHeadTimeSize
712     << ' ' << fDisplayHeadTimeRed
713     << ' ' << fDisplayHeadTimeGreen
714     << ' ' << fDisplayHeadTimeBlue;
715   }
716 
717   oss
718   << "\n/vis/viewer/set/timeWindow/displayLightFront ";
719   if (!fDisplayLightFront) {
720     oss << "false";
721   } else {
722     oss
723     << "true"
724     << ' ' << fDisplayLightFrontX/mm
725     << ' ' << fDisplayLightFrontY/mm
726     << ' ' << fDisplayLightFrontZ/mm
727     << " mm"
728     << ' ' << fDisplayLightFrontT/ns
729     << " ns"
730     << ' ' << fDisplayLightFrontRed
731     << ' ' << fDisplayLightFrontGreen
732     << ' ' << fDisplayLightFrontBlue;
733   }
734 
735   oss << std::endl;
736 
737   return oss.str();
738 }
739 
740 void G4ViewParameters::PrintDifferences (const G4ViewParameters& v) const {
741 
742   // Put performance-sensitive parameters first.
743   if (
744       // This first to optimise spin, etc.
745       (fViewpointDirection   != v.fViewpointDirection)   ||
746 
747       // No particular order from here on.
748       (fDrawingStyle         != v.fDrawingStyle)         ||
749       (fNumberOfCloudPoints  != v.fNumberOfCloudPoints)  ||
750       (fAuxEdgeVisible       != v.fAuxEdgeVisible)       ||
751       (fCulling              != v.fCulling)              ||
752       (fCullInvisible        != v.fCullInvisible)        ||
753       (fDensityCulling       != v.fDensityCulling)       ||
754       (fVisibleDensity       != v.fVisibleDensity)       ||
755       (fCullCovered          != v.fCullCovered)          ||
756       (fCBDAlgorithmNumber   != v.fCBDAlgorithmNumber)   ||
757       (fSection              != v.fSection)              ||
758       (fNoOfSides            != v.fNoOfSides)            ||
759       (fUpVector             != v.fUpVector)             ||
760       (fFieldHalfAngle       != v.fFieldHalfAngle)       ||
761       (fZoomFactor           != v.fZoomFactor)           ||
762       (fScaleFactor          != v.fScaleFactor)          ||
763       (fCurrentTargetPoint   != v.fCurrentTargetPoint)   ||
764       (fDolly                != v.fDolly)                ||
765       (fRelativeLightpointDirection != v.fRelativeLightpointDirection)  ||
766       (fLightsMoveWithCamera != v.fLightsMoveWithCamera) ||
767       (fDefaultVisAttributes != v.fDefaultVisAttributes) ||
768       (fDefaultTextVisAttributes != v.fDefaultTextVisAttributes) ||
769       (fDefaultMarker        != v.fDefaultMarker)        ||
770       (fGlobalMarkerScale    != v.fGlobalMarkerScale)    ||
771       (fGlobalLineWidthScale != v.fGlobalLineWidthScale) ||
772       (fMarkerNotHidden      != v.fMarkerNotHidden)      ||
773       (fWindowSizeHintX      != v.fWindowSizeHintX)      ||
774       (fWindowSizeHintY      != v.fWindowSizeHintY)      ||
775       (fXGeometryString      != v.fXGeometryString)      ||
776       (fGeometryMask         != v.fGeometryMask)         ||
777       (fAutoRefresh          != v.fAutoRefresh)          ||
778       (fBackgroundColour     != v.fBackgroundColour)     || 
779       (fPicking              != v.fPicking)              ||
780       (fRotationStyle        != v.fRotationStyle)
781       )
782     G4cout << "Difference in 1st batch." << G4endl;
783 
784   if (fCBDAlgorithmNumber > 0) {
785     if (fCBDParameters.size() != v.fCBDParameters.size()) {
786       G4cout << "Difference in number of colour by density parameters." << G4endl;
787     } else if (fCBDParameters != v.fCBDParameters) {
788       G4cout << "Difference in values of colour by density parameters." << G4endl;
789     }
790   }
791 
792   if (fSection) {
793     if (!(fSectionPlane == v.fSectionPlane))
794       G4cout << "Difference in section planes batch." << G4endl;
795   }
796 
797   if (IsCutaway()) {
798     if (fCutawayPlanes.size () != v.fCutawayPlanes.size ()) {
799       G4cout << "Difference in no of cutaway planes." << G4endl;
800     }
801     else {
802       for (size_t i = 0; i < fCutawayPlanes.size (); i++) {
803   if (!(fCutawayPlanes[i] == v.fCutawayPlanes[i]))
804     G4cout << "Difference in cutaway plane no. " << i << G4endl;
805       }
806     }
807   }
808 
809   if (IsExplode()) {
810     if (fExplodeFactor != v.fExplodeFactor)
811       G4cout << "Difference in explode factor." << G4endl;
812     if (fExplodeCentre != v.fExplodeCentre)
813       G4cout << "Difference in explode centre." << G4endl;
814   }
815 
816   if (fVisAttributesModifiers != v.fVisAttributesModifiers) {
817     G4cout << "Difference in vis attributes modifiers." << G4endl;
818   }
819 
820   if (fStartTime != v.fStartTime ||
821       fEndTime   != v.fEndTime)  {
822     G4cout << "Difference in time window." << G4endl;
823   }
824 
825   if (fFadeFactor != v.fFadeFactor) {
826     G4cout << "Difference in time window fade factor." << G4endl;
827   }
828 
829   if (fDisplayHeadTime != v.fDisplayHeadTime) {
830     G4cout << "Difference in display head time flag." << G4endl;
831   } else {
832     if (fDisplayHeadTimeX     != v.fDisplayHeadTimeX     ||
833         fDisplayHeadTimeY     != v.fDisplayHeadTimeY     ||
834         fDisplayHeadTimeSize  != v.fDisplayHeadTimeSize  ||
835         fDisplayHeadTimeRed   != v.fDisplayHeadTimeRed   ||
836         fDisplayHeadTimeGreen != v.fDisplayHeadTimeGreen ||
837         fDisplayHeadTimeBlue  != v.fDisplayHeadTimeBlue) {
838       G4cout << "Difference in display head time parameters." << G4endl;
839     }
840   }
841 
842   if (fDisplayLightFront != v.fDisplayLightFront) {
843     G4cout << "Difference in display light front flag." << G4endl;
844   } else {
845     if (fDisplayLightFrontX     != v.fDisplayLightFrontX     ||
846         fDisplayLightFrontY     != v.fDisplayLightFrontY     ||
847         fDisplayLightFrontZ     != v.fDisplayLightFrontZ     ||
848         fDisplayLightFrontT     != v.fDisplayLightFrontT     ||
849         fDisplayLightFrontRed   != v.fDisplayLightFrontRed   ||
850         fDisplayLightFrontGreen != v.fDisplayLightFrontGreen ||
851         fDisplayLightFrontBlue  != v.fDisplayLightFrontBlue) {
852       G4cout << "Difference in display light front parameters." << G4endl;
853     }
854   }
855 }
856 
857 std::ostream& operator <<
858 (std::ostream& os, const G4ViewParameters::DrawingStyle& style)
859 {
860   switch (style) {
861   case G4ViewParameters::wireframe:
862     os << "wireframe"; break;
863   case G4ViewParameters::hlr:
864     os << "hlr - hidden lines removed"; break;
865   case G4ViewParameters::hsr:
866     os << "hsr - hidden surfaces removed"; break;
867   case G4ViewParameters::hlhsr:
868     os << "hlhsr - hidden line, hidden surface removed"; break;
869   case G4ViewParameters::cloud:
870     os << "cloud - draw volume as a cloud of dots"; break;
871   default: os << "unrecognised"; break;
872   }
873   return os;
874 }
875 
876 std::ostream& operator << (std::ostream& os, const G4ViewParameters& v) {
877   os << "View parameters and options:";
878 
879   os << "\n  Drawing style: " << v.fDrawingStyle;
880 
881   os << "\n  Number of cloud points: " << v.fNumberOfCloudPoints;
882 
883   os << "\n  Auxiliary edges: ";
884   if (!v.fAuxEdgeVisible) os << "in";
885   os << "visible";
886 
887   os << "\n  Culling: ";
888   if (v.fCulling) os << "on";
889   else            os << "off";
890 
891   os << "\n  Culling invisible objects: ";
892   if (v.fCullInvisible) os << "on";
893   else                  os << "off";
894 
895   os << "\n  Density culling: ";
896   if (v.fDensityCulling) {
897     os << "on - invisible if density less than "
898        << v.fVisibleDensity / (1. * g / cm3) << " g cm^-3";
899   }
900   else os << "off";
901 
902   os << "\n  Culling daughters covered by opaque mothers: ";
903   if (v.fCullCovered) os << "on";
904   else                os << "off";
905 
906   os << "\n  Colour by density: ";
907   if (v.fCBDAlgorithmNumber <= 0) {
908     os << "inactive";
909   } else {
910     os << "Algorithm " << v.fCBDAlgorithmNumber << ", Parameters:";
911     for (auto p: v.fCBDParameters) {
912       os << ' ' << G4BestUnit(p,"Volumic Mass");
913     }
914   }
915 
916   os << "\n  Section flag: ";
917   if (v.fSection) os << "true, section/cut plane: " << v.fSectionPlane;
918   else            os << "false";
919 
920   if (v.IsCutaway()) {
921     os << "\n  Cutaway planes: ";
922     for (size_t i = 0; i < v.fCutawayPlanes.size (); i++) {
923       os << ' ' << v.fCutawayPlanes[i];
924     }
925   }
926   else {
927     os << "\n  No cutaway planes";
928   }
929 
930   os << "\n  Explode factor: " << v.fExplodeFactor
931      << " about centre: " << v.fExplodeCentre;
932 
933   os << "\n  No. of sides used in circle polygon approximation: "
934      << v.fNoOfSides;
935 
936   os << "\n  Viewpoint direction:  " << v.fViewpointDirection;
937 
938   os << "\n  Up vector:            " << v.fUpVector;
939 
940   os << "\n  Field half angle:     " << v.fFieldHalfAngle;
941 
942   os << "\n  Zoom factor:          " << v.fZoomFactor;
943 
944   os << "\n  Scale factor:         " << v.fScaleFactor;
945 
946   os << "\n  Current target point: " << v.fCurrentTargetPoint;
947 
948   os << "\n  Dolly distance:       " << v.fDolly;
949 
950   os << "\n  Light ";
951   if (v.fLightsMoveWithCamera) os << "moves";
952   else                         os << "does not move";
953   os << " with camera";
954 
955   os << "\n  Relative lightpoint direction: "
956      << v.fRelativeLightpointDirection;
957 
958   os << "\n  Actual lightpoint direction: "
959      << v.fActualLightpointDirection;
960 
961   os << "\n  Derived parameters for standard view of object of unit radius:";
962   G4ViewParameters tempVP = v;
963   tempVP.fDolly = 0.;
964   tempVP.fZoomFactor = 1.;
965   const G4double radius = 1.;
966   const G4double cameraDistance = tempVP.GetCameraDistance (radius);
967   const G4double nearDistance =
968     tempVP.GetNearDistance (cameraDistance, radius);
969   const G4double farDistance =
970     tempVP.GetFarDistance  (cameraDistance, nearDistance, radius);
971   const G4double right  = tempVP.GetFrontHalfHeight (nearDistance, radius);
972   os << "\n    Camera distance:   " << cameraDistance;
973   os << "\n    Near distance:     " << nearDistance;
974   os << "\n    Far distance:      " << farDistance;
975   os << "\n    Front half height: " << right;
976 
977   os << "\n  Default VisAttributes:\n  " << v.fDefaultVisAttributes;
978 
979   os << "\n  Default TextVisAttributes:\n  " << v.fDefaultTextVisAttributes;
980 
981   os << "\n  Default marker: " << v.fDefaultMarker;
982 
983   os << "\n  Global marker scale: " << v.fGlobalMarkerScale;
984 
985   os << "\n  Global lineWidth scale: " << v.fGlobalLineWidthScale;
986 
987   os << "\n  Marker ";
988   if (v.fMarkerNotHidden) os << "not ";
989   os << "hidden by surfaces.";
990 
991   os << "\n  Window size hint: "
992      << v.fWindowSizeHintX << 'x'<< v.fWindowSizeHintX;
993 
994   os << "\n  X geometry string: " << v.fXGeometryString;
995   os << "\n  X geometry mask: "
996      << std::showbase << std::hex << v.fGeometryMask
997      << std::noshowbase << std::dec;
998 
999   os << "\n  Auto refresh: ";
1000   if (v.fAutoRefresh) os << "true";
1001   else os << "false";
1002 
1003   os << "\n  Background colour: " << v.fBackgroundColour;
1004 
1005   os << "\n  Picking requested: ";
1006   if (v.fPicking) os << "true";
1007   else os << "false";
1008 
1009   os << "\n  Rotation style: ";
1010   switch (v.fRotationStyle) {
1011   case G4ViewParameters::constrainUpDirection:
1012     os << "constrainUpDirection (conventional HEP view)"; break;
1013   case G4ViewParameters::freeRotation:
1014     os << "freeRotation (Google-like rotation, using mouse-grab)"; break;
1015   default: os << "unrecognised"; break;
1016   }
1017 
1018   os << "\n  Vis attributes modifiers: ";
1019   const std::vector<G4ModelingParameters::VisAttributesModifier>& vams =
1020     v.fVisAttributesModifiers;
1021   if (vams.empty()) {
1022     os << "None";
1023   } else {
1024     os << vams;
1025   }
1026 
1027   os << "\n  Time window parameters:"
1028   << "\n  Start time:  " << v.fStartTime/ns << " ns"
1029   << "\n  End time:    " << v.fEndTime/ns << " ns"
1030   << "\n  Fade factor: " << v.fFadeFactor;
1031   if (!v.fDisplayHeadTime) {
1032     os << "\n  Head time display not requested.";
1033   } else {
1034     os
1035     << "\n  Head time position: "
1036     << v.fDisplayHeadTimeX << ' ' << v.fDisplayHeadTimeY
1037     << "\n  Head time size:     " << v.fDisplayHeadTimeSize
1038     << "\n  Head time colour:   " << v.fDisplayHeadTimeRed
1039     << ' ' << v.fDisplayHeadTimeGreen << ' ' << v.fDisplayHeadTimeBlue;
1040   }
1041   if (!v.fDisplayLightFront) {
1042     os << "\n  Light front display not requested.";
1043   } else {
1044     os
1045     << "\n  Light front position: "
1046     << v.fDisplayLightFrontX/mm << ' ' << v.fDisplayLightFrontY/mm
1047     << ' ' << v.fDisplayLightFrontZ/mm << " mm"
1048     << "\n  Light front time:     " << v.fDisplayLightFrontT/ns << " ns"
1049     << "\n  Light front colour:   " << v.fDisplayLightFrontRed
1050     << ' ' << v.fDisplayLightFrontGreen << ' ' << v.fDisplayLightFrontBlue;
1051   }
1052 
1053   return os;
1054 }
1055 
1056 G4bool G4ViewParameters::operator != (const G4ViewParameters& v) const {
1057 
1058   // Put performance-sensitive parameters first.
1059   if (
1060       // This first to optimise spin, etc.
1061       (fViewpointDirection   != v.fViewpointDirection)   ||
1062 
1063       // No particular order from here on.
1064       (fDrawingStyle         != v.fDrawingStyle)         ||
1065       (fNumberOfCloudPoints  != v.fNumberOfCloudPoints)  ||
1066       (fAuxEdgeVisible       != v.fAuxEdgeVisible)       ||
1067       (fCulling              != v.fCulling)              ||
1068       (fCullInvisible        != v.fCullInvisible)        ||
1069       (fDensityCulling       != v.fDensityCulling)       ||
1070       (fCullCovered          != v.fCullCovered)          ||
1071       (fCBDAlgorithmNumber   != v.fCBDAlgorithmNumber)   ||
1072       (fSection              != v.fSection)              ||
1073       (IsCutaway()           != v.IsCutaway())           ||
1074       (IsExplode()           != v.IsExplode())           ||
1075       (fNoOfSides            != v.fNoOfSides)            ||
1076       (fUpVector             != v.fUpVector)             ||
1077       (fFieldHalfAngle       != v.fFieldHalfAngle)       ||
1078       (fZoomFactor           != v.fZoomFactor)           ||
1079       (fScaleFactor          != v.fScaleFactor)          ||
1080       (fCurrentTargetPoint   != v.fCurrentTargetPoint)   ||
1081       (fDolly                != v.fDolly)                ||
1082       (fRelativeLightpointDirection != v.fRelativeLightpointDirection)  ||
1083       (fLightsMoveWithCamera != v.fLightsMoveWithCamera) ||
1084       (fDefaultVisAttributes != v.fDefaultVisAttributes) ||
1085       (fDefaultTextVisAttributes != v.fDefaultTextVisAttributes) ||
1086       (fDefaultMarker        != v.fDefaultMarker)        ||
1087       (fGlobalMarkerScale    != v.fGlobalMarkerScale)    ||
1088       (fGlobalLineWidthScale != v.fGlobalLineWidthScale) ||
1089       (fMarkerNotHidden      != v.fMarkerNotHidden)      ||
1090       (fWindowSizeHintX      != v.fWindowSizeHintX)      ||
1091       (fWindowSizeHintY      != v.fWindowSizeHintY)      ||
1092       (fXGeometryString      != v.fXGeometryString)      ||
1093       (fGeometryMask         != v.fGeometryMask)         ||
1094       (fAutoRefresh          != v.fAutoRefresh)          ||
1095       (fBackgroundColour     != v.fBackgroundColour)     ||
1096       (fPicking              != v.fPicking)              ||
1097       (fRotationStyle        != v.fRotationStyle)
1098       )
1099     return true;
1100 
1101   if (fDensityCulling &&
1102       (fVisibleDensity != v.fVisibleDensity)) return true;
1103 
1104   if (fCBDAlgorithmNumber > 0) {
1105     if (fCBDParameters.size() != v.fCBDParameters.size()) return true;
1106     else if (fCBDParameters != v.fCBDParameters) return true;
1107   }
1108 
1109   if (fSection &&
1110       (!(fSectionPlane == v.fSectionPlane))) return true;
1111 
1112   if (IsCutaway()) {
1113     if (fCutawayPlanes.size () != v.fCutawayPlanes.size ())
1114       return true;
1115     else {
1116       for (size_t i = 0; i < fCutawayPlanes.size (); i++) {
1117   if (!(fCutawayPlanes[i] == v.fCutawayPlanes[i])) return true;
1118       }
1119     }
1120   }
1121 
1122   if (IsExplode() &&
1123       ((fExplodeFactor != v.fExplodeFactor) ||
1124        (fExplodeCentre != v.fExplodeCentre))) return true;
1125 
1126   if (fVisAttributesModifiers != v.fVisAttributesModifiers) return true;
1127 
1128   if (fStartTime  != v.fStartTime ||
1129       fEndTime    != v.fEndTime   ||
1130       fFadeFactor != v.fFadeFactor) return true;
1131 
1132   if (fDisplayHeadTime != v.fDisplayHeadTime) return true;
1133   if (fDisplayHeadTime) {
1134     if (fDisplayHeadTimeX     != v.fDisplayHeadTimeX     ||
1135         fDisplayHeadTimeY     != v.fDisplayHeadTimeY     ||
1136         fDisplayHeadTimeSize  != v.fDisplayHeadTimeSize  ||
1137         fDisplayHeadTimeRed   != v.fDisplayHeadTimeRed   ||
1138         fDisplayHeadTimeGreen != v.fDisplayHeadTimeGreen ||
1139         fDisplayHeadTimeBlue  != v.fDisplayHeadTimeBlue) {
1140       return true;
1141     }
1142   }
1143 
1144   if (fDisplayLightFront != v.fDisplayLightFront) return true;
1145   if (fDisplayLightFront) {
1146     if (fDisplayLightFrontX     != v.fDisplayLightFrontX     ||
1147         fDisplayLightFrontY     != v.fDisplayLightFrontY     ||
1148         fDisplayLightFrontZ     != v.fDisplayLightFrontZ     ||
1149         fDisplayLightFrontT     != v.fDisplayLightFrontT     ||
1150         fDisplayLightFrontRed   != v.fDisplayLightFrontRed   ||
1151         fDisplayLightFrontGreen != v.fDisplayLightFrontGreen ||
1152         fDisplayLightFrontBlue  != v.fDisplayLightFrontBlue) {
1153       return true;
1154     }
1155   }
1156 
1157   return false;
1158 }
1159 
1160 void G4ViewParameters::SetXGeometryString (const G4String& geomStringArg)
1161 {
1162   G4int x = 0, y = 0;
1163   unsigned int w = 0, h = 0;
1164   G4String geomString = geomStringArg;
1165   // Parse windowSizeHintString for backwards compatibility...
1166   const G4String delimiters("xX+-");
1167   G4String::size_type i = geomString.find_first_of(delimiters);
1168   if (i == G4String::npos) {  // Does not contain "xX+-".  Assume single number
1169     std::istringstream iss(geomString);
1170     G4int size;
1171     iss >> size;
1172     if (!iss) {
1173       size = 600;
1174       G4cout << "Unrecognised windowSizeHint string: \""
1175        << geomString
1176        << "\".  Asuuming " << size << G4endl;
1177     }
1178     std::ostringstream oss;
1179     oss << size << 'x' << size;
1180     geomString = oss.str();
1181   }
1182  
1183   fGeometryMask = ParseGeometry( geomString, &x, &y, &w, &h );
1184 
1185   // Handle special case :
1186   if ((fGeometryMask & fYValue) == 0)
1187     {  // Using default
1188       y =  fWindowLocationHintY;
1189     }
1190   if ((fGeometryMask & fXValue) == 0)
1191     {  // Using default
1192       x =  fWindowLocationHintX;
1193     }
1194 
1195   // Check errors
1196   // if there is no Width and Height
1197   if ( ((fGeometryMask & fHeightValue) == 0 ) &&
1198        ((fGeometryMask & fWidthValue)  == 0 )) {
1199     h = fWindowSizeHintY;
1200     w = fWindowSizeHintX;
1201   } else  if ((fGeometryMask & fHeightValue) == 0 ) {
1202 
1203     // if there is only Width. Special case to be backward compatible
1204     // We set Width and Height the same to obtain a square windows.
1205     
1206     G4cout << "Unrecognised geometry string \""
1207            << geomString
1208            << "\".  No Height found. Using Width value instead"
1209            << G4endl;
1210     h = w;
1211   }
1212   if ( ((fGeometryMask & fXValue) == 0 ) ||
1213        ((fGeometryMask & fYValue)  == 0 )) {
1214     //Using defaults
1215     x = fWindowLocationHintX;
1216     y = fWindowLocationHintY;
1217   }
1218   // Set the string
1219   fXGeometryString = geomString;
1220   
1221   // Set values
1222   fWindowSizeHintX = w;
1223   fWindowSizeHintY = h;
1224   fWindowLocationHintX = x;
1225   fWindowLocationHintY = y;
1226 
1227   if ( ((fGeometryMask & fXValue)) &&
1228        ((fGeometryMask & fYValue))) {
1229 
1230     if ( (fGeometryMask & fXNegative) ) {
1231       fWindowLocationHintXNegative = true;
1232     } else {
1233       fWindowLocationHintXNegative = false;
1234     }
1235     if ( (fGeometryMask & fYNegative) ) {
1236     fWindowLocationHintYNegative = true;
1237     } else {
1238       fWindowLocationHintYNegative = false;
1239     }
1240   }
1241 }
1242 
1243 G4int G4ViewParameters::GetWindowAbsoluteLocationHintX (G4int sizeX ) const {
1244   if ( fWindowLocationHintXNegative ) {
1245     return  sizeX  + fWindowLocationHintX - fWindowSizeHintX;
1246   }
1247   return fWindowLocationHintX;
1248 }
1249 
1250 G4int G4ViewParameters::GetWindowAbsoluteLocationHintY (G4int sizeY ) const {
1251   if (  fWindowLocationHintYNegative ) {
1252     return  sizeY  + fWindowLocationHintY - fWindowSizeHintY;
1253   }
1254   return fWindowLocationHintY;
1255 }
1256 
1257 /* Keep from :
1258  * ftp://ftp.trolltech.com/qt/source/qt-embedded-free-3.0.6.tar.gz/qt-embedded-free-3.0.6/src/kernel/qapplication_qws.cpp
1259  *
1260  *    ParseGeometry parses strings of the form
1261  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
1262  *   width, height, xoffset, and yoffset are unsigned integers.
1263  *   Example:  "=80x24+300-49"
1264  *   The equal sign is optional.
1265  *   It returns a bitmask that indicates which of the four values
1266  *   were actually found in the string. For each value found,
1267  *   the corresponding argument is updated;  for each value
1268  *   not found, the corresponding argument is left unchanged.
1269  */
1270 
1271 int G4ViewParameters::ParseGeometry (
1272  const char *string,
1273  G4int *x,
1274  G4int *y,
1275  unsigned int *width,
1276  unsigned int *height)
1277 {
1278 
1279   G4int mask = fNoValue;
1280   char *strind;
1281   unsigned int tempWidth  = 0;
1282   unsigned int tempHeight = 0;
1283   G4int tempX = 0;
1284   G4int tempY = 0;
1285   char *nextCharacter;
1286   if ( (string == NULL) || (*string == '\0')) {
1287     return(mask);
1288   }
1289   if (*string == '=')
1290     string++;  /* ignore possible '=' at beg of geometry spec */
1291   strind = (char *)string;
1292   if (*strind != '+' && *strind != '-' && *strind != 'x') {
1293     tempWidth = ReadInteger(strind, &nextCharacter);
1294     if (strind == nextCharacter)
1295       return (0);
1296     strind = nextCharacter;
1297     mask |= fWidthValue;
1298   }
1299   if (*strind == 'x' || *strind == 'X') {
1300     strind++;
1301     tempHeight = ReadInteger(strind, &nextCharacter);
1302     if (strind == nextCharacter)
1303       return (0);
1304     strind = nextCharacter;
1305     mask |= fHeightValue;
1306   }
1307 
1308   if ((*strind == '+') || (*strind == '-')) {
1309     if (*strind == '-') {
1310       strind++;
1311       tempX = -ReadInteger(strind, &nextCharacter);
1312       if (strind == nextCharacter)
1313         return (0);
1314       strind = nextCharacter;
1315       mask |= fXNegative;
1316 
1317     }
1318     else
1319       { strind++;
1320         tempX = ReadInteger(strind, &nextCharacter);
1321         if (strind == nextCharacter)
1322           return(0);
1323         strind = nextCharacter;
1324       }
1325     mask |= fXValue;
1326     if ((*strind == '+') || (*strind == '-')) {
1327       if (*strind == '-') {
1328         strind++;
1329         tempY = -ReadInteger(strind, &nextCharacter);
1330         if (strind == nextCharacter)
1331           return(0);
1332         strind = nextCharacter;
1333         mask |= fYNegative;
1334       }
1335       else
1336         {
1337           strind++;
1338           tempY = ReadInteger(strind, &nextCharacter);
1339           if (strind == nextCharacter)
1340             return(0);
1341           strind = nextCharacter;
1342         }
1343       mask |= fYValue;
1344     }
1345   }
1346   /* If strind isn't at the end of the string the it's an invalid
1347      geometry specification. */
1348   if (*strind != '\0') return (0);
1349   if (mask & fXValue)
1350     *x = tempX;
1351   if (mask & fYValue)
1352     *y = tempY;
1353   if (mask & fWidthValue)
1354     *width = tempWidth;
1355   if (mask & fHeightValue)
1356     *height = tempHeight;
1357   return (mask);
1358 }
1359 
1360 /* Keep from :
1361  * ftp://ftp.trolltech.com/qt/source/qt-embedded-free-3.0.6.tar.gz/qt-embedded-free-3.0.6/src/kernel/qapplication_qws.cpp
1362  *
1363  */
1364 G4int G4ViewParameters::ReadInteger(char *string, char **NextString)
1365 {
1366     G4int Result = 0;
1367     G4int Sign = 1;
1368 
1369     if (*string == '+')
1370   string++;
1371     else if (*string == '-')
1372     {
1373   string++;
1374   Sign = -1;
1375     }
1376     for (; (*string >= '0') && (*string <= '9'); string++)
1377     {
1378   Result = (Result * 10) + (*string - '0');
1379     }
1380     *NextString = string;
1381     if (Sign >= 0)
1382   return (Result);
1383     else
1384   return (-Result);
1385 }
1386 
1387 G4ViewParameters* G4ViewParameters::CatmullRomCubicSplineInterpolation
1388 (const std::vector<G4ViewParameters>& views,
1389  G4int nInterpolationPoints)  // No of interpolations points per interval
1390 {
1391   // Returns a null pointer when no more to be done.  For example:
1392   // do {
1393   //   G4ViewParameters* vp =
1394   //   G4ViewParameters::CatmullRomCubicSplineInterpolation(viewVector,nInterpolationPoints);
1395   //   if (!vp) break;
1396   //     ...
1397   // } while (true);
1398 
1399   // See https://en.wikipedia.org/wiki/Cubic_Hermite_spline
1400 
1401   // Assumes equal intervals
1402 
1403   if (views.size() < 2) {
1404     G4Exception
1405     ("G4ViewParameters::CatmullRomCubicSplineInterpolation",
1406      "visman0301", JustWarning,
1407      "There must be at least two views.");
1408     return 0;
1409   }
1410 
1411   if (nInterpolationPoints < 1) {
1412     G4Exception
1413     ("G4ViewParameters::CatmullRomCubicSplineInterpolation",
1414      "visman0302", JustWarning,
1415      "Number of interpolation points cannot be zero or negative.");
1416     return 0;
1417   }
1418 
1419   const size_t nIntervals = views.size() - 1;
1420   const G4double dt = 1./nInterpolationPoints;
1421 
1422   static G4ViewParameters holdingValues;
1423   static G4double t = 0.;  // 0. <= t <= 1.
1424   static G4int iInterpolationPoint = 0;
1425   static size_t iInterval = 0;
1426 
1427 //  G4cout << "Interval " << iInterval << ", t = " << t << G4endl;
1428 
1429   // Hermite polynomials.
1430   const G4double h00 = 2.*t*t*t - 3.*t*t +1;
1431   const G4double h10 = t*t*t -2.*t*t + t;
1432   const G4double h01 = -2.*t*t*t + 3.*t*t;
1433   const G4double h11 = t*t*t - t*t;
1434 
1435   // Aliases (to simplify code)
1436   const size_t& n = nIntervals;
1437   size_t& i = iInterval;
1438   const std::vector<G4ViewParameters>& v = views;
1439 
1440   // The Catmull-Rom cubic spline prescription is as follows:
1441   // Slope at first way point is v[1] - v[0].
1442   // Slope at last way point is v[n] - v[n-1].
1443   // Otherwise slope at way point i is 0.5*(v[i+1] - v[i-1]).
1444   // Result = h00*v[i] + h10*m[i] + h01*v[i+1] + h11*m[i+1],
1445   // where m[i] amd m[i+1] are the slopes at the start and end
1446   // of the interval for the particular value.
1447   // If (n == 1), linear interpolation results.
1448   // If (n == 2), quadratic interpolation results.
1449 
1450   // Working variables
1451   G4double mi, mi1, real, x, y, z;
1452   
1453   // First, a crude interpolation of all parameters.  Then, below, a
1454   // smooth interpolation of those for which it makes sense.
1455   holdingValues = t < 0.5? v[i]: v[i+1];
1456 
1457   // Catmull-Rom cubic spline interpolation
1458 #define INTERPOLATE(param) \
1459 /* This works out the interpolated param in i'th interval */ \
1460 /* Assumes n >= 1 */ \
1461 if (i == 0) { \
1462 /* First interval */ \
1463 mi = v[1].param - v[0].param; \
1464 /* If there is only one interval, make start and end slopes equal */ \
1465 /* (This results in a linear interpolation) */ \
1466 if (n == 1) mi1 = mi; \
1467 /* else the end slope of the interval takes account of the next waypoint along */ \
1468 else mi1 = 0.5 * (v[2].param - v[0].param); \
1469 } else if (i >= n - 1) { \
1470 /* Similarly for last interval */ \
1471 mi1 = v[i+1].param - v[i].param; \
1472 /* If there is only one interval, make start and end slopes equal */ \
1473 if (n == 1) mi = mi1; \
1474 /* else the start slope of the interval takes account of the previous waypoint */ \
1475 else mi = 0.5 * (v[i+1].param - v[i-1].param); \
1476 } else { \
1477 /* Full Catmull-Rom slopes use previous AND next waypoints */ \
1478 mi  = 0.5 * (v[i+1].param - v[i-1].param); \
1479 mi1 = 0.5 * (v[i+2].param - v[i  ].param); \
1480 } \
1481 real = h00 * v[i].param + h10 * mi + h01 * v[i+1].param + h11 * mi1;
1482 
1483 #define INTERPOLATELOG(param) \
1484 if (i == 0) { \
1485 mi = std::log(v[1].param) - std::log(v[0].param); \
1486 if (n == 1) mi1 = mi; \
1487 else mi1 = 0.5 * (std::log(v[2].param) - std::log(v[0].param)); \
1488 } else if (i >= n - 1) { \
1489 mi1 = std::log(v[i+1].param) - std::log(v[i].param); \
1490 if (n == 1) mi = mi1; \
1491 else mi = 0.5 * (std::log(v[i+1].param) - std::log(v[i-1].param)); \
1492 } else { \
1493 mi  = 0.5 * (std::log(v[i+1].param) - std::log(v[i-1].param)); \
1494 mi1 = 0.5 * (std::log(v[i+2].param) - std::log(v[i  ].param)); \
1495 } \
1496 real = std::exp(h00 * std::log(v[i].param) + h10 * mi + h01 * std::log(v[i+1].param) + h11 * mi1);
1497 
1498   // Real parameters
1499   INTERPOLATE(fVisibleDensity);
1500   if (real < 0.) real = 0.;
1501   holdingValues.fVisibleDensity = real;
1502   INTERPOLATELOG(fExplodeFactor);
1503   holdingValues.fExplodeFactor = real;
1504   INTERPOLATE(fFieldHalfAngle);
1505   if (real < 0.) real = 0.;
1506   holdingValues.fFieldHalfAngle = real;
1507   INTERPOLATELOG(fZoomFactor);
1508   holdingValues.fZoomFactor = real;
1509   INTERPOLATE(fDolly);
1510   holdingValues.fDolly = real;
1511   INTERPOLATE(fGlobalMarkerScale);
1512   if (real < 0.) real = 0.;
1513   holdingValues.fGlobalMarkerScale = real;
1514   INTERPOLATE(fGlobalLineWidthScale);
1515   if (real < 0.) real = 0.;
1516   holdingValues.fGlobalLineWidthScale = real;
1517 
1518   // Unit vectors
1519 #define INTERPOLATEUNITVECTOR(vector) \
1520 INTERPOLATE(vector.x()); x = real; \
1521 INTERPOLATE(vector.y()); y = real; \
1522 INTERPOLATE(vector.z()); z = real;
1523   INTERPOLATEUNITVECTOR(fViewpointDirection);
1524   holdingValues.fViewpointDirection          = G4Vector3D(x,y,z).unit();
1525   INTERPOLATEUNITVECTOR(fUpVector);
1526   holdingValues.fUpVector                    = G4Vector3D(x,y,z).unit();
1527   INTERPOLATEUNITVECTOR(fRelativeLightpointDirection);
1528   holdingValues.fRelativeLightpointDirection = G4Vector3D(x,y,z).unit();
1529   INTERPOLATEUNITVECTOR(fActualLightpointDirection);
1530   holdingValues.fActualLightpointDirection   = G4Vector3D(x,y,z).unit();
1531 
1532   // Un-normalised vectors
1533 #define INTERPOLATEVECTOR(vector) \
1534 INTERPOLATE(vector.x()); x = real; \
1535 INTERPOLATE(vector.y()); y = real; \
1536 INTERPOLATE(vector.z()); z = real;
1537   INTERPOLATEVECTOR(fScaleFactor);
1538   holdingValues.fScaleFactor = G4Vector3D(x,y,z);
1539 
1540   // Points
1541 #define INTERPOLATEPOINT(point) \
1542 INTERPOLATE(point.x()); x = real; \
1543 INTERPOLATE(point.y()); y = real; \
1544 INTERPOLATE(point.z()); z = real;
1545   INTERPOLATEPOINT(fExplodeCentre);
1546   holdingValues.fExplodeCentre      = G4Point3D(x,y,z);
1547   INTERPOLATEPOINT(fCurrentTargetPoint);
1548   holdingValues.fCurrentTargetPoint = G4Point3D(x,y,z);
1549 
1550   // Colour
1551   G4double red, green, blue, alpha;
1552 #define INTERPOLATECOLOUR(colour) \
1553 INTERPOLATE(colour.GetRed());   red   = real; \
1554 INTERPOLATE(colour.GetGreen()); green = real; \
1555 INTERPOLATE(colour.GetBlue());  blue  = real; \
1556 INTERPOLATE(colour.GetAlpha()); alpha = real;
1557   INTERPOLATECOLOUR(fBackgroundColour);
1558   // Components are clamped to 0. <= component <= 1.
1559   holdingValues.fBackgroundColour = G4Colour(red,green,blue,alpha);
1560 
1561   // For some parameters we need to check some continuity
1562   G4bool continuous;
1563 #define CONTINUITY(quantity) \
1564   continuous = false; \
1565   /* This follows the logic of the INTERPOLATE macro above; see comments therein */ \
1566   if (i == 0) { \
1567     if (v[1].quantity == v[0].quantity) { \
1568        if (n == 1) continuous = true; \
1569        else if (v[2].quantity == v[0].quantity) \
1570        continuous = true; \
1571     } \
1572   } else if (i >= n - 1) { \
1573     if (v[i+1].quantity == v[i].quantity) { \
1574       if (n == 1) continuous = true; \
1575       else if (v[i+1].quantity == v[i-1].quantity) \
1576       continuous = true; \
1577     } \
1578   } else { \
1579     if (v[i-1].quantity == v[i].quantity && \
1580         v[i+1].quantity == v[i].quantity && \
1581         v[i+2].quantity == v[i].quantity) \
1582     continuous = true; \
1583   }
1584 
1585   G4double a, b, c, d;
1586 #define INTERPOLATEPLANE(plane) \
1587 INTERPOLATE(plane.a()); a = real; \
1588 INTERPOLATE(plane.b()); b = real; \
1589 INTERPOLATE(plane.c()); c = real; \
1590 INTERPOLATE(plane.d()); d = real;
1591 
1592   // Section plane
1593   CONTINUITY(fSection);
1594   if (continuous) {
1595     INTERPOLATEPLANE(fSectionPlane);
1596     holdingValues.fSectionPlane = G4Plane3D(a,b,c,d);
1597   }
1598 
1599   // Cutaway planes
1600   if (v[i].fCutawayPlanes.size()) {
1601     CONTINUITY(fCutawayPlanes.size());
1602     if (continuous) {
1603       for (size_t j = 0; j < v[i].fCutawayPlanes.size(); ++j) {
1604         INTERPOLATEPLANE(fCutawayPlanes[j]);
1605         holdingValues.fCutawayPlanes[j] = G4Plane3D(a,b,c,d);
1606       }
1607     }
1608   }
1609 
1610   // Vis attributes modifiers
1611   // Really, we are only interested in colour - other attributes can follow
1612   // the "crude" interpolation that is guaranteed above.
1613   static G4VisAttributes workingVA;
1614   if  (v[i].fVisAttributesModifiers.size()) {
1615     CONTINUITY(fVisAttributesModifiers.size());
1616     if (continuous) {
1617       for (size_t j = 0; j < v[i].fVisAttributesModifiers.size(); ++j) {
1618         CONTINUITY(fVisAttributesModifiers[j].GetPVNameCopyNoPath());
1619         if (continuous) {
1620           CONTINUITY(fVisAttributesModifiers[j].GetVisAttributesSignifier());
1621           if (continuous) {
1622             if (v[i].fVisAttributesModifiers[j].GetVisAttributesSignifier() ==
1623                 G4ModelingParameters::VASColour) {
1624               INTERPOLATECOLOUR(fVisAttributesModifiers[j].GetVisAttributes().GetColour());
1625               workingVA = v[i].fVisAttributesModifiers[j].GetVisAttributes();
1626               workingVA.SetColour(G4Colour(red,green,blue,alpha));
1627               holdingValues.fVisAttributesModifiers[j].SetVisAttributes(workingVA);
1628             }
1629           }
1630         }
1631       }
1632     }
1633   }
1634 
1635   // Time window parameters (for showing particles in flight)
1636   // Only two parameters are interpolated. The others are usually chosen
1637   // once and for all by the user for a given series of views - or at least,
1638   // if not, they will be interpolated by the default "crude" method above.
1639   INTERPOLATE(fStartTime)
1640   holdingValues.fStartTime = real;
1641   INTERPOLATE(fEndTime)
1642   holdingValues.fEndTime = real;
1643 
1644   // Increment counters
1645   iInterpolationPoint++;
1646   t += dt;
1647   if (iInterpolationPoint > nInterpolationPoints) {
1648     iInterpolationPoint = 1;  // Ready for next interval.
1649     t = dt;
1650     iInterval++;
1651   }
1652   if (iInterval >= nIntervals) {
1653     iInterpolationPoint = 0;  // Ready for a complete restart.
1654     t = 0.;
1655     iInterval = 0;
1656     return 0;
1657   }
1658 
1659   return &holdingValues;
1660 }
1661