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 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /visualization/management/src/G4ViewParameters.cc (Version 11.3.0) and /visualization/management/src/G4ViewParameters.cc (Version 11.2.2)


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