Index: trunk/source/geometry/solids/test/SBT/SBT.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/SBT.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/SBT.cc	(revision 1316)
@@ -0,0 +1,98 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBT (Solids Batch Test) main program
+//
+
+#include "G4RunManager.hh"
+#include "G4UImanager.hh"
+#include "G4UIterminal.hh"
+#include "G4UItcsh.hh"
+
+#include "G4InteractiveSolid.hh"
+#include "SBTMessenger.hh"
+#include "SBTvoxelMessenger.hh"
+#include "SBTVisManager.hh"
+
+/*
+MEDERNACH Emmanuel
+Aug 2000
+
+You could now run SBT with an argument script
+and exit SBT.
+*/
+
+int main(int argc,char *argv[])
+{
+        // Initialize visualization manager
+        SBTVisManager *visManager = new SBTVisManager;
+        visManager->Initialize();
+
+	// Build our "interactive" volume,
+	// a volume that is also a messenger
+	G4InteractiveSolid *interactiveSolid = new G4InteractiveSolid( "/solid/" );
+	
+	// Build our batch test messenger.
+	// A new batch test will be created by it.
+	// The test messenger gets the target solid
+	// from a solid query class G4QuerySolid, as specified in the
+	// second argument
+	SBTMessenger *testMessenger = new SBTMessenger( "/test/", (G4SolidQuery *)interactiveSolid, visManager );
+
+	//
+	// Build our voxel test messenger
+	SBTvoxelMessenger *voxelMessenger = new SBTvoxelMessenger( "/voxel/", (G4SolidQuery *)interactiveSolid, visManager );
+		
+	// Give control to interactive terminal
+  G4UIsession *session;
+  
+#ifdef G4UI_USE_TCSH
+  session = new G4UIterminal(new G4UItcsh);      
+#else
+	session = new G4UIterminal;
+#endif
+	   
+	if (argc > 1)  // when run with an argument, run each scripts and exit
+	  {
+	    G4UImanager * UI = G4UImanager::GetUIpointer();
+
+	    for (int i=1;i<argc;i++)
+	      {
+		UI->ApplyCommand("/control/execute "+G4String(argv[i]));
+	      }
+	  }
+	else
+	  {
+	    session->SessionStart();
+	  }
+	
+	// All finished...
+	delete session;
+	delete testMessenger;
+	delete voxelMessenger;
+	delete interactiveSolid;
+	return 0;
+}
Index: trunk/source/geometry/solids/test/SBT/include/G4InteractiveSolid.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/G4InteractiveSolid.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/G4InteractiveSolid.hh	(revision 1316)
@@ -0,0 +1,197 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4InteractiveSolid.hh
+//
+// A messenger that allows one to construct a solid interactively
+// (i.e. via command line)
+//
+// The solid thus created can be recovered using the G4SolidQuery
+// method GetSolid.
+//
+// Notes:
+//    * The G4UIcommand design is somewhat inflexible. It would have
+//      been much better to specify each command argument as a
+//      class of it's own (with input methods, help methods, etc.)
+//      then to create the monolithic monstrosities like G4UICmdWith****.
+//      Alas, I'm tempted to fix this, but for the sake of expediency
+//      I will cheat and use my own string interpretator. The 
+//      side effect is that interactive help is much compromised.
+//
+
+#ifndef G4InteractiveSolid_hh
+#define G4InteractiveSolid_hh
+
+#include "G4UImessenger.hh"
+#include "G4SolidQuery.hh"
+
+class G4UIdirectory;
+class G4UIcommand;
+class G4UIcmdWithPargs;
+class G4UIcmdParg;
+
+class G4InteractiveSolid : public G4UImessenger, public G4SolidQuery {
+public:
+  G4InteractiveSolid( const G4String &commandPrefix );
+  virtual ~G4InteractiveSolid();
+	
+  inline G4VSolid *GetSolid() const { return solid; }
+	
+  void SetNewValue( G4UIcommand *command, G4String newValues );
+  G4String GetCurrentValue( G4UIcommand *command );
+	
+protected:
+  void DeleteArgArray( G4UIcmdParg **array, const G4int nItem );
+  G4String ConvertArgsToString( G4UIcmdParg **array, const G4int nItem );
+	
+  G4VSolid	*solid;
+	
+  G4UIdirectory	*volumeDirectory;
+	
+  G4UIcmdParg		*boxArgs[3];
+  G4UIcmdWithPargs	*boxCmd;
+  void MakeMeABox( G4String values );
+	
+  G4UIcmdParg		*consArgs[7];
+  G4UIcmdWithPargs	*consCmd;
+  void MakeMeACons( G4String values );
+	
+  G4UIcmdParg		*orbArgs[1];
+  G4UIcmdWithPargs	*orbCmd;
+  void MakeMeAnOrb( G4String values );
+	
+  G4UIcmdParg		*paraArgs[6];
+  G4UIcmdWithPargs	*paraCmd;
+  void MakeMeAPara( G4String values );
+	
+  G4UIcmdParg		*sphereArgs[6];
+  G4UIcmdWithPargs	*sphereCmd;
+  void MakeMeASphere( G4String values );
+	
+  G4UIcmdParg		*torusArgs[5];
+  G4UIcmdWithPargs	*torusCmd;
+  void MakeMeATorus( G4String values );
+	
+  G4UIcmdParg		*trapArgs[11];
+  G4UIcmdWithPargs	*trapCmd;
+  void MakeMeATrap( G4String values );
+	
+  G4UIcmdParg		*trdArgs[5];
+  G4UIcmdWithPargs	*trdCmd;
+  void MakeMeATrd( G4String values );
+	
+  G4UIcmdParg		*tubsArgs[5];
+  G4UIcmdWithPargs	*tubsCmd;
+  void MakeMeATubs( G4String values );
+	
+  G4UIcmdParg		*ellipsoidArgs[5];
+  G4UIcmdWithPargs	*ellipsoidCmd;
+  void MakeMeAnEllipsoid( G4String values );
+	
+  G4UIcmdParg		*elConeArgs[4];
+  G4UIcmdWithPargs	*elConeCmd;
+  void MakeMeAnEllipticalCone( G4String values );
+	
+  G4UIcmdParg		*elTubeArgs[6];
+  G4UIcmdWithPargs	*elTubeCmd;
+  void MakeMeAnEllipticalTube( G4String values );
+
+  G4UIcmdParg		*extrudedArgs[8];
+  G4UIcmdWithPargs	*extrudedCmd;
+  void MakeMeAnExtrudedSolid( G4String values );
+
+  G4UIcmdParg		*hypeArgs[5];
+  G4UIcmdWithPargs	*hypeCmd;
+  void MakeMeAHype( G4String values );
+	
+  G4UIcmdParg		*polyconeArgs[5];
+  G4UIcmdWithPargs	*polyconeCmd;
+  void MakeMeAPolycone( G4String values );
+	
+  G4UIcmdParg		*polycone2Args[6];
+  G4UIcmdWithPargs	*polycone2Cmd;
+  void MakeMeAPolycone2( G4String values );
+	
+  G4UIcmdParg		*polyhedraArgs[6];
+  G4UIcmdWithPargs	*polyhedraCmd;
+  void MakeMeAPolyhedra( G4String values );
+	
+  G4UIcmdParg		*polyhedra2Args[7];
+  G4UIcmdWithPargs	*polyhedra2Cmd;
+  void MakeMeAPolyhedra2( G4String values );
+	
+  G4UIcmdParg		*tesselArgs[9];
+  G4UIcmdWithPargs	*tesselCmd;
+  void MakeMeATessellatedSolid( G4String values );
+	
+  G4UIcmdParg		*tessel2Args[8];
+  G4UIcmdWithPargs	*tessel2Cmd;
+  void MakeMeATessellatedSolid2( G4String values );
+
+  G4UIcmdParg		*tetArgs[4];
+  G4UIcmdWithPargs	*tetCmd;
+  void MakeMeATet( G4String values );
+	
+  G4UIcmdParg		*twistedBoxArgs[4];
+  G4UIcmdWithPargs	*twistedBoxCmd;
+  void MakeMeATwistedBox( G4String values );
+	
+  G4UIcmdParg		*twistedTrapArgs[5];
+  G4UIcmdWithPargs	*twistedTrapCmd;
+  void MakeMeATwistedTrap( G4String values );
+	
+  G4UIcmdParg		*twistedTrap2Args[11];
+  G4UIcmdWithPargs	*twistedTrap2Cmd;
+  void MakeMeATwistedTrap2( G4String values );
+	
+  G4UIcmdParg		*twistedTrdArgs[6];
+  G4UIcmdWithPargs	*twistedTrdCmd;
+  void MakeMeATwistedTrd( G4String values );
+	
+  G4UIcmdParg		*twistedTubsArgs[7];
+  G4UIcmdWithPargs	*twistedTubsCmd;
+  void MakeMeATwistedTubs( G4String values );
+	
+  G4UIcmdWithPargs	*dircTestCmd;
+  void MakeMeDircTest();
+
+
+  
+  typedef enum BooleanOp {
+    INTERSECTION,
+    SUBTRACTION,
+    UNION
+  } BooleanOp;
+
+  G4UIcmdWithPargs	*BooleanSolid1Cmd;
+  void MakeMeBooleanSolid1(G4String values);
+
+  /* Here add new commands and functions to create solids */
+
+};
+
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/G4SolidQuery.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/G4SolidQuery.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/G4SolidQuery.hh	(revision 1316)
@@ -0,0 +1,47 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4SolidQuery.hh
+//
+// Declaration of the pure virtual class G4SolidQuery: a class
+// that gives an inherited object a standard method in which
+// to be queried for a (pointer to a) G4VSolid
+//
+
+#ifndef G4SolidQuery_hh
+#define G4SolidQuery_hh
+
+#include "G4VSolid.hh"
+
+class G4SolidQuery {
+	public:
+	G4SolidQuery() {;}
+	virtual ~G4SolidQuery() {;}
+	
+	virtual G4VSolid *GetSolid() const = 0;
+};
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/G4UIcmdParg.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/G4UIcmdParg.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/G4UIcmdParg.hh	(revision 1316)
@@ -0,0 +1,56 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdParg.hh
+//
+// Specification of a pure virtual class of generic command
+// arguments, to be used by G4UIcmdWithPargs.
+//
+
+#ifndef G4UIcmdParg_hh
+#define G4UIcmdParg_hh
+
+#include "globals.hh"
+#include <iostream>
+
+class G4UIcmdParg {
+	public: 
+	G4UIcmdParg( const G4String &theName ) { name = theName; }
+	virtual ~G4UIcmdParg() {;}
+	
+	virtual G4String ConvertToString() = 0;
+	
+	virtual char GetTypeCode() const = 0;
+	inline G4String GetName() const { return name; }
+	
+	virtual std::istream &FetchValue( std::istream &ios ) = 0;
+	
+	protected:
+	G4String name;
+};
+
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargDouble.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargDouble.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargDouble.hh	(revision 1316)
@@ -0,0 +1,55 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdPargDouble.hh
+//
+// Specification of a double argument for G4UIcmdWithPargs
+//
+
+#ifndef G4UIcmdPargDouble_hh
+#define G4UIcmdPargDouble_hh
+
+#include "G4UIcmdParg.hh"
+
+class G4UIcmdPargDouble : public G4UIcmdParg {
+	public:
+	G4UIcmdPargDouble( const  G4String &theName, const G4double def, const G4double theUnits );
+	virtual ~G4UIcmdPargDouble() {;}
+	
+	G4String ConvertToString();
+	
+	inline G4double GetValue() const { return value; }
+	inline void SetValue( G4double newValue ) { value = newValue; }
+	
+	inline char GetTypeCode() const { return 'd'; }
+	
+	std::istream &FetchValue( std::istream &ios );
+	
+	protected:
+	G4double units, value;
+};
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargInteger.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargInteger.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargInteger.hh	(revision 1316)
@@ -0,0 +1,55 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdPargInteger.hh
+//
+// Specification of a integer argument for G4UIcmdWithPargs
+//
+
+#ifndef G4UIcmdPargInteger_hh
+#define G4UIcmdPargInteger_hh
+
+#include "G4UIcmdParg.hh"
+
+class G4UIcmdPargInteger : public G4UIcmdParg {
+	public:
+	G4UIcmdPargInteger( const  G4String &theName, const G4int def ) : G4UIcmdParg(theName) { value = def; }
+	virtual ~G4UIcmdPargInteger() {;}
+	
+	G4String ConvertToString();
+	
+	inline G4int GetValue() const { return value; }
+	inline void SetValue( G4int newValue ) { value = newValue; }
+	
+	inline char GetTypeCode() const { return 'i'; }
+	
+	std::istream &FetchValue( std::istream &ios );
+	
+	protected:
+	G4int value;
+};
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargList.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargList.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargList.hh	(revision 1316)
@@ -0,0 +1,63 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdPargList.hh
+//
+// Specification of an abstract class of generic command argument
+// that is a list with the following syntax:
+//
+//          (xxxxx,xxxxx,xxxxx,....,xxxxx)
+//
+// with no spaces and with xxxxxx as an object interpreted by
+// pure virual method FetchNextItem.
+//
+
+#ifndef G4UIcmdPargList_hh
+#define G4UIcmdPargList_hh
+
+#include "G4UIcmdParg.hh"
+
+class G4UIcmdPargList : public G4UIcmdParg {
+	public:
+	G4UIcmdPargList( const G4String &theName, G4int maxItem );
+	virtual ~G4UIcmdPargList() {;}
+	
+	virtual G4String ConvertToString();
+
+	virtual char GetTypeCode() const { return 's'; }
+	virtual std::istream &FetchValue( std::istream &ios );
+	
+	inline G4int GetNItem() const { return nItem; }
+	
+	protected:
+	virtual G4bool FetchItem( const char *string, const G4int item ) = 0;
+	virtual std::ostream &WriteItem( std::ostream &ios, const G4int item ) = 0;
+	
+	G4int	nItem, maxItem;
+};	
+
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargListDouble.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargListDouble.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/G4UIcmdPargListDouble.hh	(revision 1316)
@@ -0,0 +1,52 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdPargListDouble.hh
+//
+// Declaration of an argument consisting of
+// a list of double values for G4UIcmdWithParg
+//
+
+#ifndef G4UIcmdPargListDouble_hh
+#define G4UIcmdPargListDouble_hh
+
+#include "G4UIcmdPargList.hh"
+
+class G4UIcmdPargListDouble : public G4UIcmdPargList {
+	public:
+	G4UIcmdPargListDouble( const G4String &theName, G4int maxItem, const G4double units );
+	~G4UIcmdPargListDouble();
+	
+	inline G4double *GetValues() const { return storage; }
+	
+	protected:
+	virtual G4bool FetchItem( const char *string, const G4int item );
+	virtual std::ostream &WriteItem( std::ostream &ios, const G4int item );
+	
+	G4double units, *storage;
+};
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/G4UIcmdWithPargs.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/G4UIcmdWithPargs.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/G4UIcmdWithPargs.hh	(revision 1316)
@@ -0,0 +1,53 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdWithPargs.hh
+//
+// An extended type of G4UIcommand that accepts a run-time
+// specified list of generic argument objects.
+//
+
+#ifndef G4UIcmdWithPArgs_hh
+#define G4UIcmdWithPArgs_hh
+
+#include "G4UIcommand.hh"
+
+class G4UIcmdParg;
+
+class G4UIcmdWithPargs : public G4UIcommand {
+	public:
+	G4UIcmdWithPargs( const char *path, G4UImessenger *messenger,
+			  G4UIcmdParg **args, const int numParg );
+	virtual ~G4UIcmdWithPargs();
+	
+	G4bool GetArguments( G4String argumentString );
+	
+	protected:
+	G4UIcmdParg	**args;
+	G4int		numArgs;
+};
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/SBTMessenger.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/SBTMessenger.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/SBTMessenger.hh	(revision 1316)
@@ -0,0 +1,148 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTMessenger.hh
+//
+// Definition of the messenger for controlling test 3
+//
+#ifndef SBTMessenger_hh
+#define SBTMessenger_hh
+
+#include "G4UImessenger.hh"
+#include "globals.hh"
+#include <fstream>
+
+class SBTrun;
+class SBTVisManager;
+
+class G4VSolid;
+class G4SolidQuery;
+
+class G4UIdirectory;
+class G4UIcommand;
+class G4UIcmdWith3VectorAndUnit;
+class G4UIcmdWithAnInteger;
+class G4UIcmdWithAString;
+class G4UIcmdWithoutParameter;
+
+class SBTMessenger : public G4UImessenger
+{
+	public:
+	SBTMessenger( const G4String prefix, const G4SolidQuery *solidQuery, SBTVisManager *visManager );
+	~SBTMessenger();
+	
+	void SetNewValue( G4UIcommand *command, G4String newValues );
+	G4String GetCurrentValue( G4UIcommand *command );
+	
+	inline const G4SolidQuery *GetSolidQuery() const { return solidQuery; }
+	
+	inline SBTVisManager *GetVisManager() const { return visManager; }
+	inline void SetVisManager( SBTVisManager *theVisManager ) { visManager = theVisManager; }
+
+	public:
+	class Debugger {
+		public:
+		Debugger( const G4VSolid *aSolid, const SBTrun *aTester ) 
+					{ testSolid = aSolid; tester = aTester; }
+		virtual ~Debugger() {;}
+
+		virtual G4int DebugMe( std::ifstream &logFile, const G4int errorIndex ) = 0;
+
+		protected:
+		const G4VSolid *testSolid;
+		const SBTrun *tester;
+	};
+	
+	protected:
+	class DrawError : public SBTMessenger::Debugger {
+		public:
+		DrawError( const G4VSolid *aSolid, const SBTrun *aTester, SBTVisManager *theVisManager )
+				 : Debugger(aSolid,aTester) { visManager = theVisManager;}
+		G4int DebugMe( std::ifstream &logFile, const G4int errorIndex );
+		
+		protected:
+		SBTVisManager *visManager;
+	};
+	class DebugInside : public SBTMessenger::Debugger {
+		public:
+		DebugInside( const G4VSolid *aSolid, const SBTrun *aTester ) : Debugger(aSolid,aTester) {;}
+		G4int DebugMe( std::ifstream &logFile, const G4int errorIndex );
+	};
+	class DebugToInP : public SBTMessenger::Debugger {
+		public:
+		DebugToInP( const G4VSolid *aSolid, const SBTrun *aTester ) : Debugger(aSolid,aTester) {;}
+		G4int DebugMe( std::ifstream &logFile, const G4int errorIndex );
+	};
+	class DebugToInPV : public SBTMessenger::Debugger {
+		public:
+		DebugToInPV( const G4VSolid *aSolid, const SBTrun *aTester ) : Debugger(aSolid,aTester) {;}
+		G4int DebugMe( std::ifstream &logFile, const G4int errorIndex );
+	};
+	class DebugToOutP : public SBTMessenger::Debugger {
+		public:
+		DebugToOutP( const G4VSolid *aSolid, const SBTrun *aTester ) : Debugger(aSolid,aTester) {;}
+		G4int DebugMe( std::ifstream &logFile, const G4int errorIndex );
+	};
+	class DebugToOutPV : public SBTMessenger::Debugger  {
+		public:
+		DebugToOutPV( const G4VSolid *aSolid, const SBTrun *aTester ) : Debugger(aSolid,aTester) {;}
+		G4int DebugMe( std::ifstream &logFile, const G4int errorIndex );
+	};
+	
+	class DebugSurfNorm : public SBTMessenger::Debugger  {
+		public:
+		DebugSurfNorm( const G4VSolid *aSolid, const SBTrun *aTester ) : Debugger(aSolid,aTester) {;}
+		G4int DebugMe( std::ifstream &logFile, const G4int errorIndex );
+	};
+        void InvokeTest3();
+        void Debug( const G4int errorIndex, SBTMessenger::Debugger *debugger );
+	
+	private:
+	SBTrun		*tester;
+	const G4SolidQuery *solidQuery;
+	SBTVisManager	*visManager;
+	
+	G4String	errorFile;
+	
+	G4UIdirectory			*test3Directory;
+	G4UIcmdWith3VectorAndUnit	*targetCmd;
+	G4UIcmdWith3VectorAndUnit	*widthsCmd;
+	G4UIcmdWith3VectorAndUnit	*gridSizesCmd;
+	G4UIcmdWithAnInteger		*maxPointsCmd;
+	G4UIcmdWithAnInteger		*maxErrorsCmd;
+	G4UIcmdWithAString		*errorFileCmd;
+	G4UIcmdWithoutParameter		*runCmd;
+	G4UIcmdWithAnInteger		*drawCmd;
+	G4UIcmdWithAnInteger		*debugInsideCmd;
+	G4UIcmdWithAnInteger		*debugToInPCmd;
+	G4UIcmdWithAnInteger		*debugToInPVCmd;
+	G4UIcmdWithAnInteger		*debugToOutPCmd;
+	G4UIcmdWithAnInteger		*debugToOutPVCmd;
+	G4UIcmdWithAnInteger		*debugSurfNormCmd;
+	G4UIcmdWithoutParameter		*pauseCmd;
+};
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/SBTVisManager.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/SBTVisManager.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/SBTVisManager.hh	(revision 1316)
@@ -0,0 +1,59 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTVisManager
+//
+// Definition of visualization manager for SBT
+//
+
+#ifndef SBTVisManager_H
+#define SBTVisManager_H
+
+#include "G4VisManager.hh"
+#include "G4NullModel.hh"
+
+class SBTFakeModel : public G4NullModel {
+	public:
+	SBTFakeModel(const G4ModelingParameters* pMP) : G4NullModel(pMP) { ; }
+	~SBTFakeModel() {;}
+	
+	inline virtual void DescribeYourselfTo( G4VGraphicsScene & ) { ; }
+};
+		
+
+class SBTVisManager : public G4VisManager
+{
+	public:
+	SBTVisManager() {}
+	~SBTVisManager() {}
+	
+	G4int BuildFakeWorld() const;
+	
+	private:
+	void RegisterGraphicsSystems();
+}; 
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/SBTrun.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/SBTrun.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/SBTrun.hh	(revision 1316)
@@ -0,0 +1,142 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTrun.hh
+//
+// Definition of the batch solid test
+//
+
+#ifndef SBTrun_hh
+#define SBTrun_hh
+
+#include <iostream>
+#include "G4VSolid.hh"
+#include "G4ThreeVector.hh"
+
+
+class SBTVisManager;
+
+//
+// This is a list of points we keep track of. The definition below
+// is a little sloppy.
+//
+class SBTrunPointList {
+	public:
+	SBTrunPointList( G4int size );
+	~SBTrunPointList();
+	
+	void AddPoint( G4ThreeVector newPoint );
+	inline G4ThreeVector operator[] (G4int i ) const { return pointList[i]; }
+	
+	inline G4int NumPoints() const { return numPoints; }
+	
+	protected:
+	G4ThreeVector	*pointList;
+	G4int		numPoints;
+	G4int		maxPoints;
+};
+
+
+
+class SBTrun {
+
+	public:
+	SBTrun();
+	~SBTrun();
+	void SetDefaults();
+	
+	void RunTest( const G4VSolid *testVolume, std::ostream &logger );
+
+	G4int DrawError( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex,
+			 SBTVisManager *visManager ) const;
+	G4int DebugInside( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const;
+	G4int DebugToInP( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const;
+	G4int DebugToInPV( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const;
+	G4int DebugToOutP( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const;
+	G4int DebugToOutPV( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const;
+	G4int DebugSurfNorm( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const;
+
+	inline void SetTarget( const G4ThreeVector &newTarget ) { target = newTarget; }
+	inline G4ThreeVector GetTarget() const { return target; }
+
+	inline void SetWidths( const G4ThreeVector &newWidths ) { widths = newWidths; }
+	inline G4ThreeVector GetWidths() const { return widths; }
+	
+	inline void SetGrids( const G4ThreeVector &newGrids ) { grids = newGrids; }
+	inline G4ThreeVector GetGrids() const { return grids; }
+	
+	inline void SetMaxPoints( const G4int newMaxPoints ) { maxPoints = newMaxPoints; }
+	inline G4int GetMaxPoints() const { return maxPoints; }
+	
+	inline void SetMaxErrors( const G4int newMaxErrors ) { maxErrors = newMaxErrors; }
+	inline G4int GetMaxErrors() const { return maxErrors; }
+
+  static G4String GetCurrentSolid(void) ; 
+  static void SetCurrentSolid(G4String SolidName) ;
+
+	protected:
+	G4ThreeVector	GetRandomPoint() const;
+	G4double	GaussianRandom(const G4double cutoff) const;
+	
+	void	TestOutsidePoint( const G4VSolid *testVolume, G4int *nError,
+				  const SBTrunPointList *inside, const SBTrunPointList *outside, 
+				  const G4ThreeVector point, std::ostream &logger );
+	void	TestInsidePoint(  const G4VSolid *testVolume, G4int *nError,
+				  const SBTrunPointList *inside, const G4ThreeVector point, std::ostream &logger );
+
+	void	ReportError( G4int *nError, const G4ThreeVector p, 
+			     const G4ThreeVector v, G4double distance,
+			     const G4String comment, std::ostream &logger );
+	void 	ClearErrors();		
+	G4int 	CountErrors() const;		
+	
+	G4int	GetLoggedPV( std::istream &logger, const G4int errorIndex,
+			     G4ThreeVector &p, G4ThreeVector &v        ) const;
+	
+	protected:
+	G4ThreeVector	target,
+			widths,
+			grids;
+	G4int		maxPoints,
+			maxErrors;
+        
+			
+	
+	typedef struct sSBTrunErrorList {
+		G4String	message;
+		G4int		nUsed;
+		struct sSBTrunErrorList *next;
+	} SBTrunErrorList;
+	
+	SBTrunErrorList *errorList;
+
+        private:
+  static G4String CurrentSolid; /* Solid to be tested, used to visualize */
+    
+
+};
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/SBTvoxel.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/SBTvoxel.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/SBTvoxel.hh	(revision 1316)
@@ -0,0 +1,113 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTvoxel.hh
+//
+// Definition of a batch based voxel test
+//
+#ifndef SBTvoxel_hh
+#define SBTvoxel_hh
+
+#include "globals.hh"
+#include "G4ThreeVector.hh"
+#include "geomdefs.hh"
+#include <iostream>
+
+class G4VSolid;
+class G4VoxelLimits;
+class G4AffineTransform;
+
+class SBTVisManager;
+
+class SBTvoxel {
+	public:
+	SBTvoxel();
+	~SBTvoxel();
+	
+	void SetDefaults();
+	
+	void RunTest( const G4VSolid *testVolume, std::ostream &logger );
+	
+	void Draw( const G4VSolid *testVolume, 
+		   const G4VoxelLimits &voxel, const G4AffineTransform &transform,
+		   const G4ThreeVector *points, const G4int numPoints,
+		   const EAxis	axis, const G4double limits[2],
+	 	   SBTVisManager *visManager ) const;
+
+	void Debug( const G4VSolid *testVolume, const EAxis axis,
+		    const G4VoxelLimits &voxel, const G4AffineTransform &transform,
+		    const G4ThreeVector *point ) const;
+	
+
+
+	void SetTarget( const G4ThreeVector &newTarget ) { target = newTarget; }
+	G4ThreeVector GetTarget() const { return target; }
+
+	void SetMaxVoxels( const G4int newMaxVoxels ) { maxVoxels = newMaxVoxels; }
+	G4int GetMaxVoxels() const { return maxVoxels; }
+	
+	void SetMaxErrors( const G4int newMaxErrors ) { maxErrors = newMaxErrors; }
+	G4int GetMaxErrors() const { return maxErrors; }
+
+	inline void SetWidths( const G4ThreeVector &newWidths ) { widths = newWidths; }
+	inline G4ThreeVector GetWidths() const { return widths; }
+
+
+	protected:
+	G4ThreeVector	target,
+			widths;
+	G4int		maxVoxels,
+			maxErrors;
+	
+	G4bool TestOneVoxel( const G4VSolid *testVolume, 
+			     const G4VoxelLimits &voxel,
+			     const G4AffineTransform &transform,
+			     const G4ThreeVector inside[], const G4int numInside,
+			     std::ostream &logger ) const;
+
+	void GetInsidePoints( const G4VSolid *testVolume,
+			      G4ThreeVector inside[], G4int *numInside,
+			      const G4int numPoints,
+			      const G4int numAttempts ) const;
+
+	G4ThreeVector GetRandomPoint() const;
+
+	G4double GaussianRandom(const G4double cutoff) const;
+
+	G4bool GetRandomLimit( G4double x[2], const G4double range ) const;
+
+	G4VoxelLimits *NewRandomVoxel( const G4ThreeVector &theWidths ) const;
+	
+	void DumpVoxel( const G4VoxelLimits &voxel, std::ostream &logger ) const;
+	
+	void DumpTransform( const G4AffineTransform &transform, std::ostream &logger ) const;
+	
+	void MakeVoxelTestPoints( const G4VoxelLimits &voxel,
+				  const EAxis axis, const G4double value,
+				  G4ThreeVector testPoints[9] ) const;
+};
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/include/SBTvoxelMessenger.hh
===================================================================
--- trunk/source/geometry/solids/test/SBT/include/SBTvoxelMessenger.hh	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/include/SBTvoxelMessenger.hh	(revision 1316)
@@ -0,0 +1,106 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTvoxelMessenger.hh
+//
+// Definition of the UI messenger for SBTvoxel
+//
+
+#ifndef SBTvoxelMessenger_hh
+#define SBTvoxelMessenger_hh
+
+#include "G4UImessenger.hh"
+#include "SBTvoxel.hh"
+#include "G4RotationMatrix.hh"
+#include <fstream>
+
+class G4VSolid;
+class G4SolidQuery;
+
+class G4AffineTransform;
+class G4VoxelLimits;
+
+class G4UIdirectory;
+class G4UIcommand;
+class G4UIcmdWith3VectorAndUnit;
+class G4UIcmdWithAnInteger;
+class G4UIcmdWithAString;
+class G4UIcmdWithoutParameter;
+class G4UIcmdWith3Vector;
+
+class G4UIcmdWithPargs;
+class G4UIcmdParg;
+
+class SBTvoxelMessenger : public G4UImessenger {
+	public:
+	SBTvoxelMessenger( const G4String prefix, const G4SolidQuery *solidQuery, SBTVisManager *visManager );
+	~SBTvoxelMessenger();
+	
+	void SetNewValue( G4UIcommand *command, G4String newValues );
+	G4String GetCurrentValue( G4UIcommand *command );
+	
+	inline const G4SolidQuery *GetSolidQuery() const { return solidQuery; }
+
+        void InvokeTest();
+	void Draw();
+	void Debug();
+
+	private:
+	SBTvoxel		tester;
+	const G4SolidQuery 	*solidQuery;
+	SBTVisManager	*visManager;
+	
+	G4VoxelLimits		*voxel;
+	G4ThreeVector		*translate;
+	G4RotationMatrix	*rotate;
+	G4ThreeVector		*point;
+	G4double		limits[2];
+	EAxis			axis;
+	
+	G4String		errorFile;
+	
+	G4UIdirectory		*voxelDirectory;
+	G4UIcmdWith3VectorAndUnit	*targetCmd;
+	G4UIcmdWith3VectorAndUnit	*widthsCmd;
+	G4UIcmdWithAnInteger		*maxVoxelsCmd;
+	G4UIcmdWithAnInteger		*maxErrorsCmd;
+	G4UIcmdWithAString		*errorFileCmd;
+	G4UIcmdWithoutParameter		*runCmd;
+	
+	G4UIdirectory			*pictDirectory;
+	G4UIcmdParg			*pictVoxelArgs[6];
+	G4UIcmdWithPargs		*pictVoxelCmd;
+	G4UIcmdWith3Vector		*pictTranCmd;
+	G4UIcmdParg			*pictRotArgs[4];
+	G4UIcmdWithPargs		*pictRotCmd;
+	G4UIcmdWith3Vector	        *pictPointCmd;
+	G4UIcmdParg			*pictLimitArgs[3];
+	G4UIcmdWithPargs		*pictLimitCmd;
+	G4UIcmdWithoutParameter		*pictDrawCmd;
+	G4UIcmdWithoutParameter		*pictDebugCmd;
+};
+
+#endif
Index: trunk/source/geometry/solids/test/SBT/src/G4InteractiveSolid.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/G4InteractiveSolid.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/G4InteractiveSolid.cc	(revision 1316)
@@ -0,0 +1,1608 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4InteractiveSolid.cc
+//
+// Implementation of a messenger for constructing solids interactively
+//
+
+#include "SBTrun.hh"
+
+#include "G4InteractiveSolid.hh"
+#include "G4UIdirectory.hh"
+#include "G4UIcmdWithPargs.hh"
+#include "G4UIcmdPargDouble.hh"
+#include "G4UIcmdPargInteger.hh"
+#include "G4UIcmdPargListDouble.hh"
+
+#include "G4Box.hh"
+#include "G4Cons.hh"
+#include "G4Orb.hh"
+#include "G4Para.hh"
+#include "G4Sphere.hh"
+#include "G4Torus.hh"
+#include "G4Trap.hh"
+#include "G4Trd.hh"
+#include "G4Tubs.hh"
+#include "G4Ellipsoid.hh"
+#include "G4EllipticalCone.hh"
+#include "G4EllipticalTube.hh"
+#include "G4ExtrudedSolid.hh"
+#include "G4Hype.hh"
+#include "G4Polycone.hh"
+#include "G4Polyhedra.hh"
+#include "G4TessellatedSolid.hh"
+#include "G4TriangularFacet.hh"
+#include "G4QuadrangularFacet.hh"
+#include "G4Tet.hh"
+#include "G4TwistedBox.hh"
+#include "G4TwistedTrap.hh"
+#include "G4TwistedTrd.hh"
+#include "G4TwistedTubs.hh"
+
+#include "G4IntersectionSolid.hh"
+#include "G4SubtractionSolid.hh"
+#include "G4UnionSolid.hh"
+
+//
+// Constructor
+//
+G4InteractiveSolid::G4InteractiveSolid( const G4String &prefix )
+{
+	//
+	// Hmmm... well, how about a reasonable default?
+	//
+	solid = new G4Box( "InteractiveBox", 1.0*m, 1.0*m, 1.0*m );
+	
+	//
+	// Declare messenger directory
+	//
+	volumeDirectory = new G4UIdirectory( prefix );
+	volumeDirectory->SetGuidance( "Solid construction using parameters from the command line" );
+
+
+	//
+	// Declare G4Box
+	//
+	boxArgs[0] = new G4UIcmdPargDouble( "dx", 1.0, m );
+	boxArgs[1] = new G4UIcmdPargDouble( "dy", 1.0, m );
+	boxArgs[2] = new G4UIcmdPargDouble( "dz", 1.0, m );
+	G4String boxPath = prefix+"G4Box";
+	boxCmd = new G4UIcmdWithPargs( boxPath, this, boxArgs, 3 );
+	boxCmd->SetGuidance( "Declare a G4Box solid" );
+
+	//
+	// Declare G4Cons
+	//
+	consArgs[0] = new G4UIcmdPargDouble( "rmin1", 1.0, m );
+	consArgs[1] = new G4UIcmdPargDouble( "rmax1", 1.0, m );
+	consArgs[2] = new G4UIcmdPargDouble( "rmin2", 1.0, m );
+	consArgs[3] = new G4UIcmdPargDouble( "rmax2", 1.0, m );
+	consArgs[4] = new G4UIcmdPargDouble( "dz",    1.0, m );
+	consArgs[5] = new G4UIcmdPargDouble( "startPhi",  1.0, deg );
+	consArgs[6] = new G4UIcmdPargDouble( "deltaPhi",  1.0, deg );
+	G4String consPath = prefix+"G4Cons";
+	consCmd = new G4UIcmdWithPargs( consPath, this, consArgs, 7 );
+	consCmd->SetGuidance( "Declare a G4Cons solid" );
+
+	//
+	// Declare G4Orb
+	//
+	orbArgs[0] = new G4UIcmdPargDouble( "r", 1.0, m );
+	G4String orbPath = prefix+"G4Orb";
+	orbCmd = new G4UIcmdWithPargs( orbPath, this, orbArgs, 1 );
+	orbCmd->SetGuidance( "Declare a G4Orb solid" );
+
+	//
+	// Declare G4Para
+	//
+	paraArgs[0] = new G4UIcmdPargDouble( "dx", 1.0, m );
+	paraArgs[1] = new G4UIcmdPargDouble( "dy", 1.0, m );
+	paraArgs[2] = new G4UIcmdPargDouble( "dz", 1.0, m );
+	paraArgs[3] = new G4UIcmdPargDouble( "alpha", 90, deg );
+	paraArgs[4] = new G4UIcmdPargDouble( "theta", 90, deg );
+	paraArgs[5] = new G4UIcmdPargDouble( "phi", 90, deg );
+	G4String paraPath = prefix+"G4Para";
+	paraCmd = new G4UIcmdWithPargs( paraPath, this, paraArgs, 6 );
+	paraCmd->SetGuidance( "Declare a G4Para solid" );
+
+	//
+	// Declare G4Sphere
+	//
+	sphereArgs[0] = new G4UIcmdPargDouble( "rmin", 1.0, m );
+	sphereArgs[1] = new G4UIcmdPargDouble( "rmax", 1.0, m );
+	sphereArgs[2] = new G4UIcmdPargDouble( "startPhi", 1.0, deg );
+	sphereArgs[3] = new G4UIcmdPargDouble( "deltaPhi", 1.0, deg );
+	sphereArgs[4] = new G4UIcmdPargDouble( "startTheta",  1.0, deg );
+	sphereArgs[5] = new G4UIcmdPargDouble( "deltaTheta",  1.0, deg );
+	G4String spherePath = prefix+"G4Sphere";
+	sphereCmd = new G4UIcmdWithPargs( spherePath, this, sphereArgs, 6 );
+	sphereCmd->SetGuidance( "Declare a G4Sphere solid" );
+
+	//
+	// Declare G4Torus
+	//
+	torusArgs[0] = new G4UIcmdPargDouble( "rmin", 1.0, m );
+	torusArgs[1] = new G4UIcmdPargDouble( "rmax", 1.0, m );
+	torusArgs[2] = new G4UIcmdPargDouble( "rtorus", 1.0, m );
+	torusArgs[3] = new G4UIcmdPargDouble( "startPhi",  1.0, deg );
+	torusArgs[4] = new G4UIcmdPargDouble( "deltaPhi",  1.0, deg );
+	G4String torusPath = prefix+"G4Torus";
+	torusCmd = new G4UIcmdWithPargs( torusPath, this, torusArgs, 5 );
+	torusCmd->SetGuidance( "Declare a G4Torus solid" );
+
+	//
+	// Declare G4Trap
+	//
+	trapArgs[ 0] = new G4UIcmdPargDouble( "dz",    1.0, m );
+	trapArgs[ 1] = new G4UIcmdPargDouble( "theta",  90, deg );
+	trapArgs[ 2] = new G4UIcmdPargDouble( "phi",   1.0, m );
+	trapArgs[ 3] = new G4UIcmdPargDouble( "dy1",   1.0, m );
+	trapArgs[ 4] = new G4UIcmdPargDouble( "dx1",   1.0, m );
+	trapArgs[ 5] = new G4UIcmdPargDouble( "dx2",   1.0, m );
+	trapArgs[ 6] = new G4UIcmdPargDouble( "alpha1", 90, deg );
+	trapArgs[ 7] = new G4UIcmdPargDouble( "dy2",   1.0, m );
+	trapArgs[ 8] = new G4UIcmdPargDouble( "dx3",   1.0, m );
+	trapArgs[ 9] = new G4UIcmdPargDouble( "dx4",   1.0, m );
+	trapArgs[10] = new G4UIcmdPargDouble( "alpha2", 90, deg );
+	G4String trapPath = prefix+"G4Trap";
+	trapCmd = new G4UIcmdWithPargs( trapPath, this, trapArgs, 11 );
+	trapCmd->SetGuidance( "Declare a G4Trap solid" );
+
+	//
+	// Declare G4Trd
+	//
+	trdArgs[0] = new G4UIcmdPargDouble( "dx1", 1.0, m );
+	trdArgs[1] = new G4UIcmdPargDouble( "dx2", 1.0, m );
+	trdArgs[2] = new G4UIcmdPargDouble( "dy1", 1.0, m );
+	trdArgs[3] = new G4UIcmdPargDouble( "dy2", 1.0, m );
+	trdArgs[4] = new G4UIcmdPargDouble( "dz",  1.0, m );
+	G4String trdPath = prefix+"G4Trd";
+	trdCmd = new G4UIcmdWithPargs( trdPath, this, trdArgs, 5 );
+	trdCmd->SetGuidance( "Declare a G4Trd solid" );
+
+	//
+	// Declare G4Tubs
+	//
+	tubsArgs[0] = new G4UIcmdPargDouble( "rmin", 1.0, m );
+	tubsArgs[1] = new G4UIcmdPargDouble( "rmax", 1.0, m );
+	tubsArgs[2] = new G4UIcmdPargDouble( "dz",   1.0, m );
+	tubsArgs[3] = new G4UIcmdPargDouble( "startPhi",  1.0, deg );
+	tubsArgs[4] = new G4UIcmdPargDouble( "deltaPhi",  1.0, deg );
+	G4String tubsPath = prefix+"G4Tubs";
+	tubsCmd = new G4UIcmdWithPargs( tubsPath, this, tubsArgs, 5 );
+	tubsCmd->SetGuidance( "Declare a G4Tubs solid" );
+
+	//
+	// Declare G4Ellipsoid
+	//
+	ellipsoidArgs[0] = new G4UIcmdPargDouble( "dx", 1.0, m );
+	ellipsoidArgs[1] = new G4UIcmdPargDouble( "dy", 1.0, m );
+	ellipsoidArgs[2] = new G4UIcmdPargDouble( "dz", 1.0, m );
+	ellipsoidArgs[3] = new G4UIcmdPargDouble( "zBottomCut", 0, m );
+	ellipsoidArgs[4] = new G4UIcmdPargDouble( "zTopCut", 0, m );
+	G4String ellipsoidPath = prefix+"G4Ellipsoid";
+	ellipsoidCmd = new G4UIcmdWithPargs( ellipsoidPath, this, ellipsoidArgs, 5 );
+	ellipsoidCmd->SetGuidance( "Declare a G4Ellipsoid solid" );
+
+	//
+	// Declare G4EllipticalCone
+	//
+	elConeArgs[0] = new G4UIcmdPargDouble( "dx", 1.0, 1 );
+	elConeArgs[1] = new G4UIcmdPargDouble( "dy", 1.0, 1 );
+	elConeArgs[2] = new G4UIcmdPargDouble( "dz", 1.0, m );
+	elConeArgs[3] = new G4UIcmdPargDouble( "zTopCut", 1.0, m );
+	G4String elConePath = prefix+"G4EllipticalCone";
+	elConeCmd = new G4UIcmdWithPargs( elConePath, this, elConeArgs, 4 );
+	elConeCmd->SetGuidance( "Declare a G4EllipticalCone solid" );
+
+	//
+	// Declare G4EllipticalTube
+	//
+	elTubeArgs[0] = new G4UIcmdPargDouble( "dx", 1.0, m );
+	elTubeArgs[1] = new G4UIcmdPargDouble( "dy", 1.0, m );
+	elTubeArgs[2] = new G4UIcmdPargDouble( "dz", 1.0, m );
+	G4String elTubePath = prefix+"G4EllipticalTube";
+	elTubeCmd = new G4UIcmdWithPargs( elTubePath, this, elTubeArgs, 3 );
+	elTubeCmd->SetGuidance( "Declare a G4EllipticalTube solid" );
+
+	//
+	// Declare G4ExtrudedSolid
+	//
+	extrudedArgs[0] = new G4UIcmdPargInteger( "numPoints", 8 );
+	extrudedArgs[1] = new G4UIcmdPargListDouble( "pgonx", 100, m );
+	extrudedArgs[2] = new G4UIcmdPargListDouble( "pgony", 100, m );
+	extrudedArgs[3] = new G4UIcmdPargInteger( "numSides", 8 );
+	extrudedArgs[4] = new G4UIcmdPargListDouble(     "z", 100, m );
+	extrudedArgs[5] = new G4UIcmdPargListDouble(  "offx", 100, m );
+	extrudedArgs[6] = new G4UIcmdPargListDouble(  "offy", 100, m );
+	extrudedArgs[7] = new G4UIcmdPargListDouble( "scale", 100, 1 );
+	G4String extrudedPath = prefix+"G4ExtrudedSolid";
+	extrudedCmd = new G4UIcmdWithPargs( extrudedPath, this, extrudedArgs, 8 );
+	extrudedCmd->SetGuidance( "Declare a G4ExtrudedSolid solid" );
+	
+	//
+	// Declare G4Hype
+	//
+	hypeArgs[0] = new G4UIcmdPargDouble( "innerRadius", 1.0, m );
+	hypeArgs[1] = new G4UIcmdPargDouble( "outerRadius", 1.0, m );
+	hypeArgs[2] = new G4UIcmdPargDouble( "innerStereo", 1.0, rad );
+	hypeArgs[3] = new G4UIcmdPargDouble( "outerStereo", 1.0, rad );
+	hypeArgs[4] = new G4UIcmdPargDouble( "dz",  1.0, m );
+	G4String hypePath = prefix+"G4Hype";
+	hypeCmd = new G4UIcmdWithPargs( hypePath, this, hypeArgs, 5 );
+	hypeCmd->SetGuidance( "Declare a G4Hype solid" );
+	
+	//
+	// Declare G4Polycone
+	//
+	polyconeArgs[0] = new G4UIcmdPargDouble( "phiStart", 0, deg );
+	polyconeArgs[1] = new G4UIcmdPargDouble( "phiTotal", 0, deg );
+	polyconeArgs[2] = new G4UIcmdPargInteger( "numRZ", 1 );
+	polyconeArgs[3] = new G4UIcmdPargListDouble( "r", 100, m );
+	polyconeArgs[4] = new G4UIcmdPargListDouble( "z", 100, m );
+	G4String polyconePath = prefix+"G4Polycone";
+	polyconeCmd = new G4UIcmdWithPargs( polyconePath, this, polyconeArgs, 5 );
+	polyconeCmd->SetGuidance( "Declare a G4Polycone solid" );
+	
+	//
+	// Declare G4Polycone2
+	//
+	polycone2Args[0] = new G4UIcmdPargDouble( "phiStart", 0, deg );
+	polycone2Args[1] = new G4UIcmdPargDouble( "phiTotal", 0, deg );
+	polycone2Args[2] = new G4UIcmdPargInteger( "numRZ", 1 );
+	polycone2Args[3] = new G4UIcmdPargListDouble( "z", 100, m );
+	polycone2Args[4] = new G4UIcmdPargListDouble( "rin", 100, m );
+	polycone2Args[5] = new G4UIcmdPargListDouble( "rout", 100, m );
+	G4String polycone2Path = prefix+"G4Polycone2";
+	polycone2Cmd = new G4UIcmdWithPargs( polycone2Path, this, polycone2Args, 6 );
+	polycone2Cmd->SetGuidance( "Declare a G4Polycone solid (PCON style)" );
+	
+	//
+	// Declare G4Polyhedra
+	//
+	polyhedraArgs[0] = new G4UIcmdPargDouble( "phiStart", 0, deg );
+	polyhedraArgs[1] = new G4UIcmdPargDouble( "phiTotal", 0, deg );
+	polyhedraArgs[2] = new G4UIcmdPargInteger( "numSides", 8 );
+	polyhedraArgs[3] = new G4UIcmdPargInteger( "numRZ", 1 );
+	polyhedraArgs[4] = new G4UIcmdPargListDouble( "r", 100, m );
+	polyhedraArgs[5] = new G4UIcmdPargListDouble( "z", 100, m );
+	G4String polyhedraPath = prefix+"G4Polyhedra";
+	polyhedraCmd = new G4UIcmdWithPargs( polyhedraPath, this, polyhedraArgs, 6 );
+	polyhedraCmd->SetGuidance( "Declare a G4Polyhedra solid" );
+	
+	//
+	// Declare G4Polyhedra2
+	//
+	polyhedra2Args[0] = new G4UIcmdPargDouble( "phiStart", 0, deg );
+	polyhedra2Args[1] = new G4UIcmdPargDouble( "phiTotal", 0, deg );
+	polyhedra2Args[2] = new G4UIcmdPargInteger( "numSides", 8 );
+	polyhedra2Args[3] = new G4UIcmdPargInteger( "numRZ", 1 );
+	polyhedra2Args[4] = new G4UIcmdPargListDouble( "z", 100, m );
+	polyhedra2Args[5] = new G4UIcmdPargListDouble( "rin", 100, m );
+	polyhedra2Args[6] = new G4UIcmdPargListDouble( "rout", 100, m );
+	G4String polyhedra2Path = prefix+"G4Polyhedra2";
+	polyhedra2Cmd = new G4UIcmdWithPargs( polyhedra2Path, this, polyhedra2Args, 7 );
+	polyhedra2Cmd->SetGuidance( "Declare a G4Polyhedra solid (PGON style)" );
+	
+	//
+	// Declare G4TessellatedSolid
+	//
+	tesselArgs[0] = new G4UIcmdPargInteger("num3", 8 );
+	tesselArgs[1] = new G4UIcmdPargListDouble("p1in3", 100, m );
+	tesselArgs[2] = new G4UIcmdPargListDouble("p2in3", 100, m );
+	tesselArgs[3] = new G4UIcmdPargListDouble("p3in3", 100, m );
+	tesselArgs[4] = new G4UIcmdPargInteger("num4", 8 );
+	tesselArgs[5] = new G4UIcmdPargListDouble("p1in4", 100, m );
+	tesselArgs[6] = new G4UIcmdPargListDouble("p2in4", 100, m );
+	tesselArgs[7] = new G4UIcmdPargListDouble("p3in4", 100, m );
+	tesselArgs[8] = new G4UIcmdPargListDouble("p4in4", 100, m );
+	G4String tesselPath = prefix+"G4TessellatedSolid";
+	tesselCmd = new G4UIcmdWithPargs( tesselPath, this, tesselArgs, 9 );
+	tesselCmd->SetGuidance( "Declare a G4TessellatedSolid solid" );
+	
+	//
+	// Declare G4TessellatedSolid2
+	//
+	tessel2Args[0] = new G4UIcmdPargInteger( "numPoints", 8 );
+	tessel2Args[1] = new G4UIcmdPargListDouble( "pgonx", 100, m );
+	tessel2Args[2] = new G4UIcmdPargListDouble( "pgony", 100, m );
+	tessel2Args[3] = new G4UIcmdPargInteger( "numSides", 8 );
+	tessel2Args[4] = new G4UIcmdPargListDouble(     "z", 100, m );
+	tessel2Args[5] = new G4UIcmdPargListDouble(  "offx", 100, m );
+	tessel2Args[6] = new G4UIcmdPargListDouble(  "offy", 100, m );
+	tessel2Args[7] = new G4UIcmdPargListDouble( "scale", 100, 1 );
+	G4String tessel2Path = prefix+"G4TessellatedSolid2";
+	tessel2Cmd = new G4UIcmdWithPargs( tessel2Path, this, tessel2Args, 8 );
+	tessel2Cmd->SetGuidance( "Declare a G4TessellatedSolid solid as an extruded solid" );
+	
+	//
+	// Declare G4Tet
+	//
+	tetArgs[0] = new G4UIcmdPargListDouble( "p1", 3, m );
+	tetArgs[1] = new G4UIcmdPargListDouble( "p2", 3, m );
+	tetArgs[2] = new G4UIcmdPargListDouble( "p3", 3, m );
+	tetArgs[3] = new G4UIcmdPargListDouble( "p4", 3, m );
+	G4String tetPath = prefix+"G4Tet";
+	tetCmd = new G4UIcmdWithPargs( tetPath, this, tetArgs, 4 );
+	tetCmd->SetGuidance( "Declare a G4Tet solid" );
+	
+	//
+	// Declare G4TwistedBox
+	//
+	twistedBoxArgs[0] = new G4UIcmdPargDouble( "phi", 0.0, deg );
+	twistedBoxArgs[1] = new G4UIcmdPargDouble( "dx",  1.0, m );
+	twistedBoxArgs[2] = new G4UIcmdPargDouble( "dy",  1.0, m );
+	twistedBoxArgs[3] = new G4UIcmdPargDouble( "dz",  1.0, m );
+	G4String twistedBoxPath = prefix+"G4TwistedBox";
+	twistedBoxCmd = new G4UIcmdWithPargs( twistedBoxPath, this, twistedBoxArgs, 4 );
+	twistedBoxCmd->SetGuidance( "Declare a G4TwistedBox solid" );
+
+	//
+	// Declare regular G4TwistedTrap
+        // 
+	//
+	twistedTrapArgs[0] = new G4UIcmdPargDouble( "phi", 0.0, deg );
+	twistedTrapArgs[1] = new G4UIcmdPargDouble( "dx1", 1.0, m );
+	twistedTrapArgs[2] = new G4UIcmdPargDouble( "dx2", 1.0, m );
+	twistedTrapArgs[3] = new G4UIcmdPargDouble( "dy",  1.0, m );
+	twistedTrapArgs[4] = new G4UIcmdPargDouble( "dz",  1.0, m );
+	G4String twistedTrapPath = prefix+"G4TwistedTrap";
+	twistedTrapCmd = new G4UIcmdWithPargs( twistedTrapPath, this, twistedTrapArgs, 5 );
+	twistedTrapCmd->SetGuidance( "Declare a regular G4TwistedTrap solid" );
+        
+
+	//
+	// Declare general G4TwistedTrap
+	//
+	twistedTrap2Args[ 0] = new G4UIcmdPargDouble( "phi",   0.0, deg );
+	twistedTrap2Args[ 1] = new G4UIcmdPargDouble( "dz",    1.0, m );
+	twistedTrap2Args[ 2] = new G4UIcmdPargDouble( "theta", 0.0, deg );
+	twistedTrap2Args[ 3] = new G4UIcmdPargDouble( "phi",   1.0, deg );
+	twistedTrap2Args[ 4] = new G4UIcmdPargDouble( "dy1",   1.0, m );
+	twistedTrap2Args[ 5] = new G4UIcmdPargDouble( "dx1",   1.0, m );
+	twistedTrap2Args[ 6] = new G4UIcmdPargDouble( "dx2",   1.0, m );
+	twistedTrap2Args[ 7] = new G4UIcmdPargDouble( "dy2",   1.0, m );
+	twistedTrap2Args[ 8] = new G4UIcmdPargDouble( "dx3",   1.0, m );
+	twistedTrap2Args[ 9] = new G4UIcmdPargDouble( "dx4",   1.0, m );
+	twistedTrap2Args[10] = new G4UIcmdPargDouble( "alpha", 0.0, deg );
+	G4String twistedTrap2Path = prefix+"G4TwistedTrap2";
+	twistedTrap2Cmd = new G4UIcmdWithPargs( twistedTrap2Path, this, twistedTrap2Args, 11 );
+	twistedTrap2Cmd->SetGuidance( "Declare a general G4TwistedTrap solid" );
+
+	//
+	// Declare G4TwistedTrd
+        // 
+	//
+	twistedTrdArgs[0] = new G4UIcmdPargDouble( "dx1", 1.0, m );
+	twistedTrdArgs[1] = new G4UIcmdPargDouble( "dx2", 1.0, m );
+	twistedTrdArgs[2] = new G4UIcmdPargDouble( "dy1",  1.0, m );
+	twistedTrdArgs[3] = new G4UIcmdPargDouble( "dy2",  1.0, m );
+	twistedTrdArgs[4] = new G4UIcmdPargDouble( "dz",  1.0, m );
+	twistedTrdArgs[5] = new G4UIcmdPargDouble( "phi", 0.0, deg );
+	G4String twistedTrdPath = prefix+"G4TwistedTrd";
+	twistedTrdCmd = new G4UIcmdWithPargs( twistedTrdPath, this, twistedTrdArgs, 6 );
+	twistedTrdCmd->SetGuidance( "Declare a regular G4TwistedTrd solid" );
+        
+
+	//
+	// Declare G4TwistedTubs
+	//
+	twistedTubsArgs[0] = new G4UIcmdPargDouble( "phi", 0.0, deg );
+	twistedTubsArgs[1] = new G4UIcmdPargDouble( "rmin", 1.0, m );
+	twistedTubsArgs[2] = new G4UIcmdPargDouble( "rmax", 1.0, m );
+	twistedTubsArgs[3] = new G4UIcmdPargDouble( "zneg", 1.0, m );
+	twistedTubsArgs[4] = new G4UIcmdPargDouble( "zpos", 1.0, m );
+	twistedTubsArgs[5] = new G4UIcmdPargInteger( "nseg", 1 );
+	twistedTubsArgs[6] = new G4UIcmdPargDouble( "totphi", 360.0, deg );
+	G4String twistedTubsPath = prefix+"G4TwistedTubs";
+	twistedTubsCmd = new G4UIcmdWithPargs( twistedTubsPath, this, twistedTubsArgs, 7 );
+	twistedTubsCmd->SetGuidance( "Declare a G4TwistedTubs solid" );
+
+	//
+	// Declare DircTest
+	//
+	G4String dircTestPath = prefix+"DircTest";
+	dircTestCmd = new G4UIcmdWithPargs( dircTestPath, this, 0, 0 );
+	dircTestCmd->SetGuidance( "Declare a DircTest solid" );
+
+	//
+	// Declare BooleanSolid1
+	//
+	G4String BooleanSolid1Path = prefix+"BooleanSolid";
+	BooleanSolid1Cmd = new G4UIcmdWithPargs( BooleanSolid1Path, this, 0, 0 );
+	BooleanSolid1Cmd->SetGuidance( "Declare a Boolean solid #1" );
+}
+
+
+//
+// Destructor
+//
+G4InteractiveSolid::~G4InteractiveSolid()
+{
+	if (solid) delete solid;
+	
+	delete boxCmd;
+	DeleteArgArray( boxArgs,       sizeof(      boxArgs)/sizeof(G4UIcmdParg**) );
+
+	delete consCmd;
+	DeleteArgArray( consArgs,      sizeof(     consArgs)/sizeof(G4UIcmdParg**) );
+
+	delete orbCmd;
+	DeleteArgArray( orbArgs,       sizeof(      orbArgs)/sizeof(G4UIcmdParg**) );
+
+	delete paraCmd;
+	DeleteArgArray( paraArgs,      sizeof(     paraArgs)/sizeof(G4UIcmdParg**) );
+
+	delete sphereCmd;
+	DeleteArgArray( sphereArgs,    sizeof(   sphereArgs)/sizeof(G4UIcmdParg**) );
+
+	delete torusCmd;
+	DeleteArgArray( torusArgs,     sizeof(    torusArgs)/sizeof(G4UIcmdParg**) );
+
+	delete trapCmd;
+	DeleteArgArray( trapArgs,      sizeof(     trapArgs)/sizeof(G4UIcmdParg**) );
+
+	delete trdCmd;
+	DeleteArgArray( trdArgs,       sizeof(      trdArgs)/sizeof(G4UIcmdParg**) );
+
+	delete tubsCmd;
+	DeleteArgArray( tubsArgs,      sizeof(     tubsArgs)/sizeof(G4UIcmdParg**) );
+
+	delete ellipsoidCmd;
+	DeleteArgArray( ellipsoidArgs, sizeof(ellipsoidArgs)/sizeof(G4UIcmdParg**) );
+
+	delete elConeCmd;
+	DeleteArgArray( elConeArgs,    sizeof(   elConeArgs)/sizeof(G4UIcmdParg**) );
+
+	delete elTubeCmd;
+	DeleteArgArray( elTubeArgs,    sizeof(   elTubeArgs)/sizeof(G4UIcmdParg**) );
+
+	delete extrudedCmd;
+	DeleteArgArray( extrudedArgs,  sizeof( extrudedArgs)/sizeof(G4UIcmdParg**) );
+
+	delete hypeCmd;
+	DeleteArgArray( hypeArgs,      sizeof(     hypeArgs)/sizeof(G4UIcmdParg**) );
+
+	delete polyconeCmd;
+	DeleteArgArray( polyconeArgs,  sizeof( polyconeArgs)/sizeof(G4UIcmdParg**) );
+
+	delete polyhedraCmd;
+	DeleteArgArray( polyhedraArgs, sizeof(polyhedraArgs)/sizeof(G4UIcmdParg**) );
+
+	delete tesselCmd;
+	DeleteArgArray( tesselArgs,    sizeof(   tesselArgs)/sizeof(G4UIcmdParg**) );
+
+	delete tessel2Cmd;
+	DeleteArgArray( tessel2Args,   sizeof(  tessel2Args)/sizeof(G4UIcmdParg**) );
+
+	delete tetCmd;
+	DeleteArgArray( tetArgs,       sizeof(      tetArgs)/sizeof(G4UIcmdParg**) );
+
+	delete twistedBoxCmd;
+	DeleteArgArray( twistedBoxArgs,   sizeof(   twistedBoxArgs)/sizeof(G4UIcmdParg**) );
+
+	delete twistedTrapCmd;
+	DeleteArgArray( twistedTrapArgs,  sizeof(  twistedTrapArgs)/sizeof(G4UIcmdParg**) );
+
+	delete twistedTrap2Cmd;
+	DeleteArgArray( twistedTrap2Args, sizeof( twistedTrap2Args)/sizeof(G4UIcmdParg**) );
+
+	delete twistedTrdCmd;
+	DeleteArgArray( twistedTrdArgs,  sizeof(  twistedTrdArgs)/sizeof(G4UIcmdParg**) );
+
+	delete twistedTubsCmd;
+	DeleteArgArray( twistedTubsArgs, sizeof( twistedTubsArgs)/sizeof(G4UIcmdParg**) );
+}
+
+
+//
+// DeleteArgArray
+//
+void G4InteractiveSolid::DeleteArgArray( G4UIcmdParg **array, const G4int nItem )
+{
+	G4UIcmdParg **togo = array;
+	while( togo < array+nItem ) {
+		delete *togo;
+		togo++;
+	}
+}
+
+
+//
+// MakeMeABox
+//
+void G4InteractiveSolid::MakeMeABox( G4String values )
+{
+	if (boxCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble *dxArg = (G4UIcmdPargDouble *)boxArgs[0],
+				  *dyArg = (G4UIcmdPargDouble *)boxArgs[1],
+				  *dzArg = (G4UIcmdPargDouble *)boxArgs[2];
+		
+		solid = new G4Box( "interactiveBox", dxArg->GetValue(),
+					   	     dyArg->GetValue(),
+					  	     dzArg->GetValue() );
+	}
+	else
+		G4cerr << "G4Box not created" << G4endl;
+}
+
+
+//
+// MakeMeACons
+//
+void G4InteractiveSolid::MakeMeACons( G4String values )
+{
+	if (consCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble **dArg = (G4UIcmdPargDouble **)consArgs;
+		
+		solid = new G4Cons( "interactiveCons", dArg[0]->GetValue(),
+						       dArg[1]->GetValue(),
+						       dArg[2]->GetValue(),
+						       dArg[3]->GetValue(),
+						       dArg[4]->GetValue(),
+						       dArg[5]->GetValue(),
+						       dArg[6]->GetValue() );
+	}
+	else
+		G4cerr << "G4Cons not created" << G4endl;
+}
+
+
+//
+// MakeMeAnOrb
+//
+void G4InteractiveSolid::MakeMeAnOrb( G4String values )
+{
+	if (orbCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble **dArg = (G4UIcmdPargDouble **)orbArgs;
+		
+		solid = new G4Orb( "interactiveOrb", dArg[0]->GetValue());
+	}
+	else
+		G4cerr << "G4Orb not created" << G4endl;
+}
+
+
+//
+// MakeMeAPara
+//
+void G4InteractiveSolid::MakeMeAPara( G4String values )
+{
+	if (paraCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble *dxArg = (G4UIcmdPargDouble *)paraArgs[0],
+				  *dyArg = (G4UIcmdPargDouble *)paraArgs[1],
+				  *dzArg = (G4UIcmdPargDouble *)paraArgs[2],
+				  *alphaArg = (G4UIcmdPargDouble *)paraArgs[3],
+				  *thetaArg = (G4UIcmdPargDouble *)paraArgs[4],
+				  *phiArg   = (G4UIcmdPargDouble *)paraArgs[5];
+		
+		solid = new G4Para( "interactivePara", dxArg->GetValue(),
+					    	       dyArg->GetValue(),
+					  	       dzArg->GetValue(),
+					  	       alphaArg->GetValue(),
+					  	       thetaArg->GetValue(),
+					  	       phiArg->GetValue()    );
+	}
+	else
+		G4cerr << "G4Para not created" << G4endl;
+}
+
+
+//
+// MakeMeASphere
+//
+void G4InteractiveSolid::MakeMeASphere( G4String values )
+{
+	if (sphereCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble **dArg = (G4UIcmdPargDouble **)sphereArgs;
+		
+		solid = new G4Sphere( "interactiveSphere", dArg[0]->GetValue(),
+						           dArg[1]->GetValue(),
+						           dArg[2]->GetValue(),
+						           dArg[3]->GetValue(),
+						           dArg[4]->GetValue(),
+						           dArg[5]->GetValue() );
+	}
+	else
+		G4cerr << "G4Sphere not created" << G4endl;
+}
+
+
+//
+// MakeMeATorus
+//
+void G4InteractiveSolid::MakeMeATorus( G4String values )
+{
+	if (torusCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble **dArg = (G4UIcmdPargDouble **)torusArgs;
+		
+		solid = new G4Torus( "interactiveTorus", dArg[0]->GetValue(),
+						         dArg[1]->GetValue(),
+						         dArg[2]->GetValue(),
+						         dArg[3]->GetValue(),
+						         dArg[4]->GetValue() );
+	}
+	else
+		G4cerr << "G4Torus not created" << G4endl;
+}
+
+
+//
+// MakeMeATrap
+//
+void G4InteractiveSolid::MakeMeATrap( G4String values )
+{
+	if (trapCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble **dArg = (G4UIcmdPargDouble **)trapArgs;
+		
+		solid = new G4Trap( "interactiveTrap", dArg[0]->GetValue(),
+						       dArg[1]->GetValue(),
+						       dArg[2]->GetValue(),
+						       dArg[3]->GetValue(),
+						       dArg[4]->GetValue(),
+						       dArg[5]->GetValue(),
+						       dArg[6]->GetValue(),
+						       dArg[7]->GetValue(),
+						       dArg[8]->GetValue(),
+						       dArg[9]->GetValue(),
+						       dArg[10]->GetValue() );
+	}
+	else
+		G4cerr << "G4Trap not created" << G4endl;
+}
+
+
+//
+// MakeMeATrd
+//
+void G4InteractiveSolid::MakeMeATrd( G4String values )
+{
+	if (trdCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble *dx1Arg = (G4UIcmdPargDouble *)trdArgs[0],
+				  *dx2Arg = (G4UIcmdPargDouble *)trdArgs[1],
+				  *dy1Arg = (G4UIcmdPargDouble *)trdArgs[2],
+				  *dy2Arg = (G4UIcmdPargDouble *)trdArgs[3],
+				  *dzArg  = (G4UIcmdPargDouble *)trdArgs[4];
+		
+		solid = new G4Trd( "interactiveTrd", dx1Arg->GetValue(),
+					   	     dx2Arg->GetValue(),
+					  	     dy1Arg->GetValue(),
+					  	     dy2Arg->GetValue(),
+					  	      dzArg->GetValue() );
+	}
+	else
+		G4cerr << "G4Trd not created" << G4endl;
+}
+
+
+//
+// MakeMeATubs
+//
+void G4InteractiveSolid::MakeMeATubs( G4String values )
+{
+	if (tubsCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble **dArg = (G4UIcmdPargDouble **)tubsArgs;
+		
+		solid = new G4Tubs( "interactiveTubs", dArg[0]->GetValue(),
+						       dArg[1]->GetValue(),
+						       dArg[2]->GetValue(),
+						       dArg[3]->GetValue(),
+						       dArg[4]->GetValue() );
+	}
+	else
+		G4cerr << "G4Tubs not created" << G4endl;
+}
+
+
+//
+// MakeMeAnEllipsoid
+//
+void G4InteractiveSolid::MakeMeAnEllipsoid( G4String values )
+{
+	if (ellipsoidCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble *dxArg = (G4UIcmdPargDouble *)ellipsoidArgs[0],
+				  *dyArg = (G4UIcmdPargDouble *)ellipsoidArgs[1],
+				  *dzArg = (G4UIcmdPargDouble *)ellipsoidArgs[2],
+                                  *pzBottomCutArg = (G4UIcmdPargDouble *)ellipsoidArgs[3],
+                                  *pzTopCutArg = (G4UIcmdPargDouble *)ellipsoidArgs[4];
+		
+		solid = new G4Ellipsoid( "interactiveEllipsoid", 
+                                         dxArg->GetValue(),
+					 dyArg->GetValue(),
+					 dzArg->GetValue(),
+                                         pzBottomCutArg->GetValue(),
+                                         pzTopCutArg->GetValue() );
+	}
+	else
+		G4cerr << "G4Ellipsoid not created" << G4endl;
+}
+
+
+//
+// MakeMeAnEllipticalTube
+//
+void G4InteractiveSolid::MakeMeAnEllipticalCone( G4String values )
+{
+	if (elConeCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble *dxArg = (G4UIcmdPargDouble *)elConeArgs[0],
+				  *dyArg = (G4UIcmdPargDouble *)elConeArgs[1],
+				  *dzArg = (G4UIcmdPargDouble *)elConeArgs[2],
+                                  *pzTopCutArg = (G4UIcmdPargDouble *)elConeArgs[3];
+                                  
+                G4cout << "Making G4EllipticalCone: " 
+                       <<  dxArg->GetValue() << " "
+                       <<  dyArg->GetValue() << " "
+                       <<  dzArg->GetValue() << " "
+                       <<  pzTopCutArg->GetValue() << G4endl;                            
+		
+		solid = new G4EllipticalCone( "interactiveEllipticalCone", 
+                                              dxArg->GetValue(),
+					      dyArg->GetValue(),
+					      dzArg->GetValue(),
+                                              pzTopCutArg->GetValue() );
+	}
+	else
+		G4cerr << "G4EllipticalCone not created" << G4endl;
+}
+
+//
+// MakeMeAnEllipticalTube
+//
+void G4InteractiveSolid::MakeMeAnEllipticalTube( G4String values )
+{
+	if (elTubeCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble *dxArg = (G4UIcmdPargDouble *)elTubeArgs[0],
+				  *dyArg = (G4UIcmdPargDouble *)elTubeArgs[1],
+				  *dzArg = (G4UIcmdPargDouble *)elTubeArgs[2];
+		
+		solid = new G4EllipticalTube( "interactiveEllipticalTube", 
+                                              dxArg->GetValue(),
+					      dyArg->GetValue(),
+					      dzArg->GetValue() );
+	}
+	else
+		G4cerr << "G4EllipticalTube not created" << G4endl;
+}
+
+//
+// MakeMeAnExtrudedSolid
+//
+void G4InteractiveSolid::MakeMeAnExtrudedSolid( G4String values )
+{
+	if (extrudedCmd->GetArguments( values )) {
+		delete solid;
+                
+		G4UIcmdPargInteger *numPointsArg = (G4UIcmdPargInteger*)extrudedArgs[0];
+                G4UIcmdPargListDouble  *pgonxArg = (G4UIcmdPargListDouble *)extrudedArgs[1],
+				       *pgonyArg = (G4UIcmdPargListDouble *)extrudedArgs[2];
+                                  
+                                  
+		G4UIcmdPargInteger  *numSidesArg = (G4UIcmdPargInteger*)extrudedArgs[3];
+                G4UIcmdPargListDouble      *zArg = (G4UIcmdPargListDouble *)extrudedArgs[4],
+				        *offxArg = (G4UIcmdPargListDouble *)extrudedArgs[5],
+				        *offyArg = (G4UIcmdPargListDouble *)extrudedArgs[6],
+				       *scaleArg = (G4UIcmdPargListDouble *)extrudedArgs[7];
+                
+                std::vector<G4TwoVector> polygon;
+                for ( G4int i=0; i<numPointsArg->GetValue(); ++i ) {
+                  polygon.push_back(G4TwoVector(pgonxArg->GetValues()[i], pgonyArg->GetValues()[i]));
+                }   
+		
+                std::vector<G4ExtrudedSolid::ZSection> zsections;
+                for ( G4int i=0; i<numSidesArg->GetValue(); ++i ) {
+                  zsections.push_back(G4ExtrudedSolid::ZSection(
+                                        zArg->GetValues()[i],
+                                        G4TwoVector(offxArg->GetValues()[i], offyArg->GetValues()[i]),
+                                        scaleArg->GetValues()[i]));
+                }
+                
+                solid = new G4ExtrudedSolid("interactiveExtrudedSolid", polygon, zsections);                                        
+	}
+	else
+		G4cerr << "G4ExtrudedSolid not created" << G4endl;
+}
+
+//
+// MakeMeAHype
+//
+void G4InteractiveSolid::MakeMeAHype( G4String values )
+{
+	if (hypeCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble **dArg = (G4UIcmdPargDouble **)hypeArgs;
+		
+		solid = new G4Hype( "interactiveHype", dArg[0]->GetValue(),
+						       dArg[1]->GetValue(),
+						       dArg[2]->GetValue(),
+						       dArg[3]->GetValue(),
+						       dArg[4]->GetValue()  );
+                G4cout << *solid << G4endl;                                                       
+	}
+	else
+		G4cerr << "G4Hype not created" << G4endl;
+}
+
+
+//
+// MakeMeAPolycone
+//
+void G4InteractiveSolid::MakeMeAPolycone( G4String values )
+{
+	if (polyconeCmd->GetArguments( values )) {
+		G4UIcmdPargDouble	*phiStartArg = (G4UIcmdPargDouble	*)polyconeArgs[0];
+		G4UIcmdPargDouble	*phiTotalArg = (G4UIcmdPargDouble	*)polyconeArgs[1];
+		G4UIcmdPargInteger	*numRZArg    = (G4UIcmdPargInteger	*)polyconeArgs[2];
+		G4UIcmdPargListDouble	*rArg        = (G4UIcmdPargListDouble	*)polyconeArgs[3];
+		G4UIcmdPargListDouble	*zArg        = (G4UIcmdPargListDouble	*)polyconeArgs[4];
+				  
+		//
+		// Check consistency
+		//
+		G4int numRZ = numRZArg->GetValue();
+		if (numRZ != rArg->GetNItem() ||
+		    numRZ != zArg->GetNItem()    ) {
+		    	G4cerr << "numRZ inconsistent among polycone arguments" << G4endl;
+			G4cerr << "G4Polycone not created" << G4endl;
+			return;
+		}
+		
+		delete solid;
+		solid = new G4Polycone( "interactivePolycone", 
+					phiStartArg->GetValue(),
+					phiTotalArg->GetValue(),
+					numRZ,
+					rArg->GetValues(),
+					zArg->GetValues() );
+	}
+	else
+		G4cerr << "G4Polycone not created" << G4endl;
+}
+
+
+//
+// MakeMeAPolycone2
+//
+void G4InteractiveSolid::MakeMeAPolycone2( G4String values )
+{
+	if (polycone2Cmd->GetArguments( values )) {
+		G4UIcmdPargDouble	*phiStartArg = (G4UIcmdPargDouble	*)polycone2Args[0];
+		G4UIcmdPargDouble	*phiTotalArg = (G4UIcmdPargDouble	*)polycone2Args[1];
+		G4UIcmdPargInteger	*numRZArg    = (G4UIcmdPargInteger	*)polycone2Args[2];
+		G4UIcmdPargListDouble	*zArg        = (G4UIcmdPargListDouble	*)polycone2Args[3];
+		G4UIcmdPargListDouble	*rInArg      = (G4UIcmdPargListDouble	*)polycone2Args[4];
+		G4UIcmdPargListDouble	*rOutArg     = (G4UIcmdPargListDouble	*)polycone2Args[5];
+				  
+		//
+		// Check consistency
+		//
+		G4int numRZ = numRZArg->GetValue();
+		if (numRZ != zArg->GetNItem() ||
+		    numRZ != rInArg->GetNItem() ||
+		    numRZ != rOutArg->GetNItem()    ) {
+		    	G4cerr << "numRZ inconsistent among polycone arguments" << G4endl;
+			G4cerr << "G4Polycone not created" << G4endl;
+			return;
+		}
+		
+		delete solid;
+		solid = new G4Polycone( "interactivePolycone", 
+					phiStartArg->GetValue(),
+					phiTotalArg->GetValue(),
+					numRZ,
+					zArg->GetValues(),
+					rInArg->GetValues(),
+					rOutArg->GetValues() );
+	}
+	else
+		G4cerr << "G4Polycone not created" << G4endl;
+}
+
+
+//
+// MakeMeAPolyhedra
+//
+void G4InteractiveSolid::MakeMeAPolyhedra( G4String values )
+{
+	if (polyhedraCmd->GetArguments( values )) {
+		G4UIcmdPargDouble	*phiStartArg = (G4UIcmdPargDouble	*)polyhedraArgs[0];
+		G4UIcmdPargDouble	*phiTotalArg = (G4UIcmdPargDouble	*)polyhedraArgs[1];
+		G4UIcmdPargInteger	*numSidesArg = (G4UIcmdPargInteger	*)polyhedraArgs[2];
+		G4UIcmdPargInteger	*numRZArg    = (G4UIcmdPargInteger	*)polyhedraArgs[3];
+		G4UIcmdPargListDouble	*rArg        = (G4UIcmdPargListDouble	*)polyhedraArgs[4];
+		G4UIcmdPargListDouble	*zArg        = (G4UIcmdPargListDouble	*)polyhedraArgs[5];
+				  
+		//
+		// Check consistency
+		//
+		G4int numRZ = numRZArg->GetValue();
+		if (numRZ != rArg->GetNItem() ||
+		    numRZ != zArg->GetNItem()    ) {
+		    	G4cerr << "numRZ inconsistent among polyhedra arguments" << G4endl;
+			G4cerr << "G4Polyhedra not created" << G4endl;
+			return;
+		}
+		
+		delete solid;
+		solid = new G4Polyhedra( "interactivePolyhedra", 
+					phiStartArg->GetValue(),
+					phiTotalArg->GetValue(),
+					numSidesArg->GetValue(),
+					numRZ,
+					rArg->GetValues(),
+					zArg->GetValues() );
+	}
+	else
+		G4cerr << "G4Polyhedra not created" << G4endl;
+}
+
+
+//
+// MakeMeAPolyhedra2
+//
+void G4InteractiveSolid::MakeMeAPolyhedra2( G4String values )
+{
+	if (polyhedra2Cmd->GetArguments( values )) {
+		G4UIcmdPargDouble	*phiStartArg = (G4UIcmdPargDouble	*)polyhedra2Args[0];
+		G4UIcmdPargDouble	*phiTotalArg = (G4UIcmdPargDouble	*)polyhedra2Args[1];
+		G4UIcmdPargInteger	*numSidesArg = (G4UIcmdPargInteger	*)polyhedra2Args[2];
+		G4UIcmdPargInteger	*numRZArg    = (G4UIcmdPargInteger	*)polyhedra2Args[3];
+		G4UIcmdPargListDouble	*zArg        = (G4UIcmdPargListDouble	*)polyhedra2Args[4];
+		G4UIcmdPargListDouble	*rinArg      = (G4UIcmdPargListDouble	*)polyhedra2Args[5];
+		G4UIcmdPargListDouble	*routArg     = (G4UIcmdPargListDouble	*)polyhedra2Args[6];
+				  
+		//
+		// Check consistency
+		//
+		G4int numRZ = numRZArg->GetValue();
+		if (numRZ != zArg->GetNItem() ||
+		    numRZ != rinArg->GetNItem()  ||
+		    numRZ != routArg->GetNItem()    ) {
+		    	G4cerr << "numRZ inconsistent among polyhedra arguments" << G4endl;
+			G4cerr << "G4Polyhedra not created" << G4endl;
+			return;
+		}
+		
+		delete solid;
+		solid = new G4Polyhedra( "interactivePolyhedra", 
+					phiStartArg->GetValue(),
+					phiTotalArg->GetValue(),
+					numSidesArg->GetValue(),
+					numRZ,
+					zArg->GetValues(),
+					rinArg->GetValues(),
+					routArg->GetValues() );
+	}
+	else
+		G4cerr << "G4Polyhedra not created" << G4endl;
+}
+
+
+//
+// MakeMeATessellatedSolid
+//
+void G4InteractiveSolid::MakeMeATessellatedSolid( G4String values )
+{
+	if (tesselCmd->GetArguments( values )) {
+
+		G4UIcmdPargInteger *num3Arg = (G4UIcmdPargInteger*)tesselArgs[0];
+		G4UIcmdPargListDouble *p1in3Arg = (G4UIcmdPargListDouble   *)tesselArgs[1],
+		                      *p2in3Arg = (G4UIcmdPargListDouble   *)tesselArgs[2],
+	 	                      *p3in3Arg = (G4UIcmdPargListDouble   *)tesselArgs[3];
+                
+		G4UIcmdPargInteger *num4Arg = (G4UIcmdPargInteger*)tesselArgs[4];
+		G4UIcmdPargListDouble *p1in4Arg = (G4UIcmdPargListDouble   *)tesselArgs[5],
+		                      *p2in4Arg = (G4UIcmdPargListDouble   *)tesselArgs[6],
+		                      *p3in4Arg = (G4UIcmdPargListDouble   *)tesselArgs[7],
+		                      *p4in4Arg = (G4UIcmdPargListDouble   *)tesselArgs[8];
+				  
+		//
+		// Check consistency
+		//
+		G4int num3 = num3Arg->GetValue();
+		G4int nump1in3 = p1in3Arg->GetNItem();
+		G4int nump2in3 = p2in3Arg->GetNItem();
+		G4int nump3in3 = p3in3Arg->GetNItem();
+		if ( nump1in3 != 3*num3 || nump2in3 != 3*num3 || nump3in3 != 3*num3 ) {
+		    	G4cerr << "Wrong number of points coordinates among triangular tessel arguments" << G4endl;
+			G4cerr << "G4TessellatedSolid not created" << G4endl;
+			return;
+		}
+		G4int num4 = num4Arg->GetValue();
+		G4int nump1in4 = p1in4Arg->GetNItem();
+		G4int nump2in4 = p2in4Arg->GetNItem();
+		G4int nump3in4 = p3in4Arg->GetNItem();
+		G4int nump4in4 = p4in4Arg->GetNItem();
+		if ( nump1in4 != 3*num4 || nump2in4 != 3*num4 || nump3in4 != 3*num4 || nump4in4 != 3*num4) {
+		    	G4cerr << "Wrong number of points coordinates among quadrangular tessel arguments" << G4endl;
+			G4cerr << "G4TessellatedSolid not created" << G4endl;
+			return;
+		}
+		
+		delete solid;
+                                   
+		G4TessellatedSolid* tessel 
+                  = new G4TessellatedSolid( "interactiveTessellatedSolid");
+                  
+                for ( G4int i=0; i<num3; ++i) {
+                  G4ThreeVector p1(p1in3Arg->GetValues()[3*i+0], p1in3Arg->GetValues()[3*i+1], p1in3Arg->GetValues()[3*i+2]);
+                  G4ThreeVector p2(p2in3Arg->GetValues()[3*i+0], p2in3Arg->GetValues()[3*i+1], p2in3Arg->GetValues()[3*i+2]);
+                  G4ThreeVector p3(p3in3Arg->GetValues()[3*i+0], p3in3Arg->GetValues()[3*i+1], p3in3Arg->GetValues()[3*i+2]);
+                  tessel->AddFacet(new G4TriangularFacet(p1, p2, p3, ABSOLUTE));
+                }  
+                
+                for ( G4int i=0; i<num4; ++i) {
+                  G4ThreeVector p1(p1in4Arg->GetValues()[3*i+0], p1in4Arg->GetValues()[3*i+1], p1in4Arg->GetValues()[3*i+2]);
+                  G4ThreeVector p2(p2in4Arg->GetValues()[3*i+0], p2in4Arg->GetValues()[3*i+1], p2in4Arg->GetValues()[3*i+2]);
+                  G4ThreeVector p3(p3in4Arg->GetValues()[3*i+0], p3in4Arg->GetValues()[3*i+1], p3in4Arg->GetValues()[3*i+2]);
+                  G4ThreeVector p4(p4in4Arg->GetValues()[3*i+0], p4in4Arg->GetValues()[3*i+1], p4in4Arg->GetValues()[3*i+2]);
+                  tessel->AddFacet(new G4QuadrangularFacet(p1, p2, p3, p4, ABSOLUTE));
+                }
+                tessel->SetSolidClosed(true);
+                G4cout << *tessel << G4endl;
+                solid = tessel;  
+               
+	}
+	else
+		G4cerr << "G4TessellatedSolid not created" << G4endl;
+}
+
+//
+// MakeMeAnTessellatedSolid2
+//
+void G4InteractiveSolid::MakeMeATessellatedSolid2( G4String values )
+{
+	if (tessel2Cmd->GetArguments( values )) {
+		delete solid;
+                
+		G4UIcmdPargInteger *numPointsArg = (G4UIcmdPargInteger*)tessel2Args[0];
+                G4UIcmdPargListDouble  *pgonxArg = (G4UIcmdPargListDouble *)tessel2Args[1],
+				       *pgonyArg = (G4UIcmdPargListDouble *)tessel2Args[2];
+                                  
+                                  
+		G4UIcmdPargInteger  *numSidesArg = (G4UIcmdPargInteger*)tessel2Args[3];
+                G4UIcmdPargListDouble      *zArg = (G4UIcmdPargListDouble *)tessel2Args[4],
+				        *offxArg = (G4UIcmdPargListDouble *)tessel2Args[5],
+				        *offyArg = (G4UIcmdPargListDouble *)tessel2Args[6],
+				       *scaleArg = (G4UIcmdPargListDouble *)tessel2Args[7];
+                
+                std::vector<G4TwoVector> polygon;
+                for ( G4int i=0; i<numPointsArg->GetValue(); ++i ) {
+                  polygon.push_back(G4TwoVector(pgonxArg->GetValues()[i], pgonyArg->GetValues()[i]));
+                }   
+		
+                std::vector<G4ExtrudedSolid::ZSection> zsections;
+                for ( G4int i=0; i<numSidesArg->GetValue(); ++i ) {
+                  zsections.push_back(G4ExtrudedSolid::ZSection(
+                                        zArg->GetValues()[i],
+                                        G4TwoVector(offxArg->GetValues()[i], offyArg->GetValues()[i]),
+                                        scaleArg->GetValues()[i]));
+                }
+                
+                G4ExtrudedSolid* xtru
+                  = new G4ExtrudedSolid("interactiveTessellatedSolid", polygon, zsections); 
+                solid = new G4TessellatedSolid(*xtru);
+                delete xtru;
+                                                       
+	}
+	else
+		G4cerr << "G4TessellatedSolid not created" << G4endl;
+}
+
+
+//
+// MakeMeATet
+//
+void G4InteractiveSolid::MakeMeATet( G4String values )
+{
+	if (tetCmd->GetArguments( values )) {
+		G4UIcmdPargListDouble	*p1Arg = (G4UIcmdPargListDouble   *)tetArgs[0];
+		G4UIcmdPargListDouble	*p2Arg = (G4UIcmdPargListDouble   *)tetArgs[1];
+		G4UIcmdPargListDouble	*p3Arg = (G4UIcmdPargListDouble   *)tetArgs[2];
+		G4UIcmdPargListDouble	*p4Arg = (G4UIcmdPargListDouble   *)tetArgs[3];
+				  
+		//
+		// Check consistency
+		//
+		G4int numCoor1 = p1Arg->GetNItem();
+		G4int numCoor2 = p2Arg->GetNItem();
+		G4int numCoor3 = p3Arg->GetNItem();
+		G4int numCoor4 = p4Arg->GetNItem();
+		if (numCoor1 != 3 || numCoor2 != 3 || numCoor3 != 3 || numCoor4 != 3 ) {
+		    	G4cerr << "Wrong number of points coordinates among tet arguments" << G4endl;
+			G4cerr << "G4Tet not created" << G4endl;
+			return;
+		}
+		
+		delete solid;
+                G4ThreeVector p1(p1Arg->GetValues()[0], p1Arg->GetValues()[1], p1Arg->GetValues()[2]);
+                G4ThreeVector p2(p2Arg->GetValues()[0], p2Arg->GetValues()[1], p2Arg->GetValues()[2]);
+                G4ThreeVector p3(p3Arg->GetValues()[0], p3Arg->GetValues()[1], p3Arg->GetValues()[2]);
+                G4ThreeVector p4(p4Arg->GetValues()[0], p4Arg->GetValues()[1], p4Arg->GetValues()[2]);
+                                   
+		solid = new G4Tet( "interactiveTet", p1, p2, p3, p4 );
+	}
+	else
+		G4cerr << "G4Tet not created" << G4endl;
+}
+
+
+//
+// MakeMeABox
+//
+void G4InteractiveSolid::MakeMeATwistedBox( G4String values )
+{
+	if (twistedBoxCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble *phiArg = (G4UIcmdPargDouble *)twistedBoxArgs[0],
+                                  *dxArg = (G4UIcmdPargDouble *)twistedBoxArgs[1],
+				  *dyArg = (G4UIcmdPargDouble *)twistedBoxArgs[2],
+				  *dzArg = (G4UIcmdPargDouble *)twistedBoxArgs[3];
+		
+		solid = new G4TwistedBox( "interactiveTwistedBox", 
+                                          phiArg->GetValue(),
+                                          dxArg->GetValue(),
+					  dyArg->GetValue(),
+					  dzArg->GetValue() );
+                                          
+                G4cout << *solid << G4endl;                                          
+	}
+	else
+		G4cerr << "G4TwistedBox not created" << G4endl;
+}
+
+//
+// MakeMeATwistedTrap
+//
+void G4InteractiveSolid::MakeMeATwistedTrap( G4String values )
+{
+	if (twistedTrapCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble *phiArg = (G4UIcmdPargDouble *)twistedTrapArgs[0],
+				  *dx1Arg = (G4UIcmdPargDouble *)twistedTrapArgs[1],
+				  *dx2Arg = (G4UIcmdPargDouble *)twistedTrapArgs[2],
+				  *dyArg  = (G4UIcmdPargDouble *)twistedTrapArgs[3],
+				  *dzArg  = (G4UIcmdPargDouble *)twistedTrapArgs[4];
+		
+		solid = new G4TwistedTrap( "interactiveTwistedTrap", 
+                                           phiArg->GetValue(),
+                                           dx1Arg->GetValue(),
+					   dx2Arg->GetValue(),
+					   dyArg->GetValue(),
+					   dzArg->GetValue() );
+	}
+	else
+		G4cerr << "G4TwistedTrap not created" << G4endl;
+}
+
+
+//
+// MakeMeATwistedTrap
+//
+void G4InteractiveSolid::MakeMeATwistedTrap2( G4String values )
+{
+	if (twistedTrap2Cmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble **dArg = (G4UIcmdPargDouble **)twistedTrap2Args;
+		
+		solid = new G4TwistedTrap( "interactiveTwistedTrap2", 
+                                           dArg[0]->GetValue(),
+					   dArg[1]->GetValue(),
+					   dArg[2]->GetValue(),
+					   dArg[3]->GetValue(),
+					   dArg[4]->GetValue(),
+					   dArg[5]->GetValue(),
+					   dArg[6]->GetValue(),
+					   dArg[7]->GetValue(),
+					   dArg[8]->GetValue(),
+					   dArg[9]->GetValue(),
+					   dArg[10]->GetValue() );
+	}
+	else
+		G4cerr << "G4TwistedTrap2 not created" << G4endl;
+}
+
+//
+// MakeMeATwistedTrd
+//
+void G4InteractiveSolid::MakeMeATwistedTrd( G4String values )
+{
+	if (twistedTrdCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble *dx1Arg = (G4UIcmdPargDouble *)twistedTrdArgs[0],
+				  *dx2Arg = (G4UIcmdPargDouble *)twistedTrdArgs[1],
+				  *dy1Arg = (G4UIcmdPargDouble *)twistedTrdArgs[2],
+				  *dy2Arg = (G4UIcmdPargDouble *)twistedTrdArgs[3],
+				  *dzArg  = (G4UIcmdPargDouble *)twistedTrdArgs[4],
+		                  *phiArg = (G4UIcmdPargDouble *)twistedTrdArgs[5];
+				  
+		solid = new G4TwistedTrd( "interactiveTwistedTrd", 
+                                           dx1Arg->GetValue(),
+					   dx2Arg->GetValue(),
+					   dy1Arg->GetValue(),
+					   dy2Arg->GetValue(),
+					   dzArg->GetValue(),
+                                           phiArg->GetValue() );
+	} 
+	else
+		G4cerr << "G4TwistedTrd not created" << G4endl;
+}
+
+
+//
+// MakeMeATwistedTubs
+//
+void G4InteractiveSolid::MakeMeATwistedTubs( G4String values )
+{
+	if (twistedTubsCmd->GetArguments( values )) {
+		delete solid;
+		
+		G4UIcmdPargDouble  *phiArg    = (G4UIcmdPargDouble  *)twistedTubsArgs[0];
+		G4UIcmdPargDouble  *rminArg   = (G4UIcmdPargDouble  *)twistedTubsArgs[1];
+		G4UIcmdPargDouble  *rmaxArg   = (G4UIcmdPargDouble  *)twistedTubsArgs[2];
+		G4UIcmdPargDouble  *znegArg   = (G4UIcmdPargDouble  *)twistedTubsArgs[3];
+		G4UIcmdPargDouble  *zposArg   = (G4UIcmdPargDouble  *)twistedTubsArgs[4];
+		G4UIcmdPargInteger *nsegArg   = (G4UIcmdPargInteger *)twistedTubsArgs[5];
+		G4UIcmdPargDouble  *totphiArg = (G4UIcmdPargDouble  *)twistedTubsArgs[6];
+		
+		solid = new G4TwistedTubs( "interactiveTwistedTubs", 
+                                           phiArg->GetValue(),
+					   rminArg->GetValue(),
+					   rmaxArg->GetValue(),
+					   znegArg->GetValue(),
+					   zposArg->GetValue(),
+                                           nsegArg->GetValue(),
+                                           totphiArg->GetValue() );
+                                           
+                G4cout << *solid << G4endl;                                           
+	}
+	else
+		G4cerr << "G4TwistedTubs not created" << G4endl;
+}
+
+
+//
+// MakeMeDircTest
+//
+void G4InteractiveSolid::MakeMeDircTest()
+{
+	delete solid;
+
+	G4Tubs *outside = new G4Tubs( "OuterFrame",	// name (arbitrary) 
+				      1.0*m, 		// inner radius
+				      1.1*m, 		// outer radius
+				      0.01*m, 		// half-thickness in z
+				      -15*deg, 		// start angle
+				      30*deg );		// total angle
+				      
+	G4Box *cutout = new G4Box( "Cutout", 	// name (arbitrary)
+				   0.02*m,	// half-width (x)
+				   0.25*m,	// half-height (y)
+				   0.01001*m );	// half-thickness (z)
+				   
+	G4Transform3D tran = G4Translate3D( 1.03*m, 0.0, 0.0 );
+	
+	solid = new G4SubtractionSolid( "drcExample", outside, cutout, tran );
+}
+
+//
+// BooleanSolid1Test
+//
+void G4InteractiveSolid::MakeMeBooleanSolid1(G4String)
+{
+  /*
+    G4IntersectionSolid.hh  G4SubtractionSolid.hh  G4UnionSolid.hh
+    all CSGs : Box Tubs Sphere Cons Torus
+    So: Boolean type operation and 2 CSG Objects with parameters for each (..)
+    plus a transformation to apply to the second solid
+   */
+	delete solid;
+	BooleanOp OperationType;
+
+	//OperationType = INTERSECTION;
+	OperationType = SUBTRACTION;
+		
+	/*
+	G4Tubs *outside = new G4Tubs( "OuterFrame",	// name (arbitrary) 
+				      1.0*m, 		// inner radius
+				      1.1*m, 		// outer radius
+				      0.50*m, 		// half-thickness in z
+				      0*deg, 		// start angle
+				      180*deg );		// total angle
+	*/
+	/*
+	G4Torus *outside = new G4Torus( "interactiveTorus",
+					0.2*m,
+				        0.8*m,
+				        1.4*m,
+				        0*deg,
+				        360*deg );
+	*/
+	
+	G4Cons *outside = new G4Cons( "OuterFrame",
+				      0.6*m, // pRmin1
+				      1.0*m, // pRmax1
+				      0.2*m, // pRmin2
+				      0.8*m, // pRmax2
+				      0.2*m,
+				      0*deg,
+				      180*deg );
+		
+	/* Dirctest Box cutout
+	G4Box *cutout = new G4Box( "Cutout", 	// name (arbitrary)
+				   0.02*m,	// half-width (x)
+				   0.25*m,	// half-height (y)
+				   0.01001*m );	// half-thickness (z)
+	*/
+	
+	/*
+	G4Tubs *cutout = new G4Tubs("AnotherTubs",
+				    1.0*m,
+				    1.1*m,
+				    0.50*m,
+				    0*deg,
+				    180*deg
+				    );
+	*/
+
+	
+	 G4Cons *cutout = new G4Cons( "OuterFrame",
+				      0.6*m, // pRmin1
+				      1.0*m, // pRmax1
+				      0.2*m, // pRmin2
+				      0.8*m, // pRmax2
+				      0.2*m,
+				      0*deg,
+				      180*deg );
+	
+	/*
+	G4Torus *cutout = new G4Torus( "interactiveTorus",
+					0.2*m,
+				        0.8*m,
+				        1.4*m,
+				        0*deg,
+				        360*deg );
+
+	*/
+	
+	
+	G4RotationMatrix rm;
+	rm.rotateY(pi/4.0);
+
+	G4Transform3D tran = G4Transform3D(rm,G4ThreeVector(0.0,0.0,0.0));
+	
+	/* G4Transform3D tran = G4Translate3D( 1.03*m, 0.0, 0.0 ); */
+
+	switch (OperationType) {
+	case INTERSECTION:
+	  solid = new G4IntersectionSolid( "drcExample", outside, cutout, tran );
+	  break;	
+	case SUBTRACTION:
+	  solid = new G4SubtractionSolid( "drcExample", outside, cutout, tran );
+	  break;	
+	case UNION:
+	  solid = new G4UnionSolid( "drcExample", outside, cutout, tran );
+	  break;	
+	}
+	
+}
+
+
+// G4VPhysicalVolume* ExN03DetectorConstruction::MakeMeDircTest()
+  
+//
+// SetNewValue
+//
+// Invoked by the UI when the user enters a command
+//
+void G4InteractiveSolid::SetNewValue( G4UIcommand *command, G4String newValues )
+{
+  /*
+    We want to retrieve the current solid
+    So we keep the current solid command
+   */
+
+
+  G4String CurrentSolid = command->GetCommandPath() + " " + newValues ;
+
+  SBTrun::SetCurrentSolid (CurrentSolid);
+
+	if (command == boxCmd) 
+		MakeMeABox( newValues );
+	else if (command == consCmd) 
+		MakeMeACons( newValues );
+	else if (command == orbCmd) 
+		MakeMeAnOrb( newValues );
+	else if (command == paraCmd) 
+		MakeMeAPara( newValues );
+	else if (command == sphereCmd) 
+		MakeMeASphere( newValues );
+	else if (command == torusCmd) 
+		MakeMeATorus( newValues );
+	else if (command == trapCmd) 
+		MakeMeATrap( newValues );
+	else if (command == trdCmd) 
+		MakeMeATrd( newValues );
+	else if (command == tubsCmd) 
+		MakeMeATubs( newValues );
+	else if (command == ellipsoidCmd) 
+		MakeMeAnEllipsoid( newValues );
+	else if (command == elConeCmd) 
+		MakeMeAnEllipticalCone( newValues );
+	else if (command == elTubeCmd) 
+		MakeMeAnEllipticalTube( newValues );
+	else if (command == extrudedCmd) 
+		MakeMeAnExtrudedSolid( newValues );
+	else if (command == hypeCmd) 
+		MakeMeAHype( newValues );
+	else if (command == polyconeCmd) 
+		MakeMeAPolycone( newValues );
+	else if (command == polycone2Cmd) 
+		MakeMeAPolycone2( newValues );
+	else if (command == polyhedraCmd) 
+		MakeMeAPolyhedra( newValues );
+	else if (command == polyhedra2Cmd) 
+		MakeMeAPolyhedra2( newValues );
+	else if (command == tesselCmd) 
+		MakeMeATessellatedSolid( newValues );
+	else if (command == tessel2Cmd) 
+		MakeMeATessellatedSolid2( newValues );
+	else if (command == tetCmd) 
+		MakeMeATet( newValues );
+	else if (command == twistedBoxCmd) 
+		MakeMeATwistedBox( newValues );
+	else if (command == twistedTrapCmd) 
+		MakeMeATwistedTrap( newValues );
+	else if (command == twistedTrap2Cmd) 
+		MakeMeATwistedTrap2( newValues );
+	else if (command == twistedTrdCmd) 
+		MakeMeATwistedTrd( newValues );
+	else if (command == dircTestCmd) 
+		MakeMeDircTest();
+	else if (command == twistedTubsCmd) 
+		MakeMeATwistedTubs( newValues );
+	else if (command == BooleanSolid1Cmd) 
+		MakeMeBooleanSolid1(newValues);
+
+	/* Here to add new boolean solids */
+
+	else
+		G4Exception( "Unrecognized command" );
+}
+
+
+//
+// GetCurrentValue
+//
+G4String G4InteractiveSolid::GetCurrentValue( G4UIcommand *command )
+{
+	if (command == boxCmd) 
+		return ConvertArgsToString( 	   boxArgs, sizeof(	 boxArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == consCmd)
+		return ConvertArgsToString( 	  consArgs, sizeof(	consArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == orbCmd)
+		return ConvertArgsToString( 	   orbArgs, sizeof(      orbArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == paraCmd)
+		return ConvertArgsToString( 	  paraArgs, sizeof(	paraArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == sphereCmd)
+		return ConvertArgsToString( 	sphereArgs, sizeof(   sphereArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == torusCmd)
+		return ConvertArgsToString( 	 torusArgs, sizeof(    torusArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == trapCmd)
+		return ConvertArgsToString( 	  trapArgs, sizeof(	trapArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == trdCmd)
+		return ConvertArgsToString( 	   trdArgs, sizeof(	 trdArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == tubsCmd)
+		return ConvertArgsToString( 	  tubsArgs, sizeof(	tubsArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == ellipsoidCmd)
+		return ConvertArgsToString(  ellipsoidArgs, sizeof( ellipsoidArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == elConeCmd)
+		return ConvertArgsToString(     elConeArgs, sizeof(    elConeArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == elTubeCmd)
+		return ConvertArgsToString(     elTubeArgs, sizeof(    elTubeArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == extrudedCmd)
+		return ConvertArgsToString(   extrudedArgs, sizeof(  extrudedArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == hypeCmd)
+		return ConvertArgsToString( 	  hypeArgs, sizeof(	hypeArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == polyconeCmd)
+		return ConvertArgsToString(   polyconeArgs, sizeof( polyconeArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == polycone2Cmd)
+		return ConvertArgsToString(  polycone2Args, sizeof(polycone2Args)/sizeof(G4UIcmdParg**) );
+	else if (command == polyhedraCmd)
+		return ConvertArgsToString(  polyhedraArgs, sizeof(polyhedraArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == polyhedra2Cmd)
+		return ConvertArgsToString(  polyhedra2Args, sizeof(polyhedra2Args)/sizeof(G4UIcmdParg**) );
+	else if (command == tesselCmd)
+		return ConvertArgsToString(     tesselArgs, sizeof(    tesselArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == tessel2Cmd)
+		return ConvertArgsToString(    tessel2Args, sizeof(   tessel2Args)/sizeof(G4UIcmdParg**) );
+	else if (command == tetCmd)
+		return ConvertArgsToString(        tetArgs, sizeof(       tetArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == twistedBoxCmd) 
+		return ConvertArgsToString( twistedBoxArgs, sizeof(  twistedBoxArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == twistedTrapCmd)
+		return ConvertArgsToString(twistedTrapArgs, sizeof( twistedTrapArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == twistedTrap2Cmd)
+		return ConvertArgsToString(twistedTrap2Args,sizeof(twistedTrap2Args)/sizeof(G4UIcmdParg**) );
+	else if (command == twistedTrdCmd)
+		return ConvertArgsToString( twistedTrdArgs, sizeof(  twistedTrdArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == twistedTubsCmd)
+		return ConvertArgsToString(twistedTubsArgs, sizeof( twistedTubsArgs)/sizeof(G4UIcmdParg**) );
+	else if (command == dircTestCmd)
+		return "";
+	
+	G4Exception( "Unrecognized command" );
+	return "foo!";
+}
+
+
+//
+// ConvertArgsToString
+//
+G4String G4InteractiveSolid::ConvertArgsToString( G4UIcmdParg **array, const G4int nItem )
+{
+	G4String answer = "(";
+	
+	G4UIcmdParg **togo = array;
+	while( togo < array+nItem ) {
+		if (togo > array) answer += ",";
+		answer += (*togo)->ConvertToString();
+		togo++;
+	}
+	
+	return answer + ")";
+}
+
+
Index: trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargDouble.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargDouble.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargDouble.cc	(revision 1316)
@@ -0,0 +1,73 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdPargDouble.cc
+//
+// Implementation of a double argument for G4UIcmdWithPargs
+//
+
+#include "G4UIcmdPargDouble.hh"
+
+#include <sstream>
+
+//
+// Constructor
+//
+G4UIcmdPargDouble::G4UIcmdPargDouble( const G4String &theName, 
+				      const G4double def, const G4double theUnits )
+			: G4UIcmdParg( theName ) 
+{
+	value = def;
+	units = theUnits;
+}
+
+
+//
+// Fetch argument value from input stream
+//
+std::istream &G4UIcmdPargDouble::FetchValue( std::istream &istr )
+{
+	G4double newValue;
+	istr >> newValue;
+	
+	if (istr) value = newValue*units;
+	
+	return istr;
+}
+
+
+//
+// ConvertToString
+//
+G4String G4UIcmdPargDouble::ConvertToString()
+{
+	std::ostringstream os;
+	
+	os << value << '\0';
+	
+	G4String answer = os.str();
+	return answer;
+}
Index: trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargInteger.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargInteger.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargInteger.cc	(revision 1316)
@@ -0,0 +1,61 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdPargInteger.cc
+//
+// Implementation of an integer argument for G4UIcmdWithPargs
+//
+
+#include "G4UIcmdPargInteger.hh"
+
+#include <sstream>
+
+//
+// Fetch argument value from input stream
+//
+std::istream &G4UIcmdPargInteger::FetchValue( std::istream &istr )
+{
+	G4int newValue;
+	istr >> newValue;
+	
+	if (istr) value = newValue;
+	
+	return istr;
+}
+
+
+//
+// ConvertToString
+//
+G4String G4UIcmdPargInteger::ConvertToString()
+{
+	std::ostringstream os;
+	
+	os << value << '\0';
+	
+	G4String answer = os.str();
+	return answer;
+}
Index: trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargList.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargList.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargList.cc	(revision 1316)
@@ -0,0 +1,202 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdPargList.cc
+//
+// Implementation of a (generic) list argument for G4UIcmdWithPargs
+//
+
+#include "G4UIcmdPargList.hh"
+
+#include <sstream>
+#include <iomanip>
+
+//
+// Constructor
+//
+G4UIcmdPargList::G4UIcmdPargList( const  G4String &theName, G4int theMaxItem ) 
+		: G4UIcmdParg( theName )
+{
+	nItem = 0;
+	maxItem = theMaxItem;
+}
+
+
+//
+// Fetch argument value from input stream
+//
+std::istream &G4UIcmdPargList::FetchValue( std::istream &istr )
+{
+	//
+	// Because of limitations of G4UIcommand, we must avoid
+	// requiring any spaces.
+	//
+	// Require '(' to be the leading character, and read in
+	// character strings until ',' or ')' are found. If the
+	// latter is found, input is terminated.
+	//
+	// In actual usage, we expect leading blanks to be removed
+	// before this method is invoked,
+	// but there is no need to assume that.
+	//
+	// Notice that blank items are allowed. It is up to decendent
+	// classes to decide what to do in this case. To allow an
+	// empty list (i.e. no items, nItem==0), the special symbol
+	// "-" is reserved.
+	//
+	char buffer[256];	// Buffer for each item
+	char a;			// Single character input
+	
+	//
+	// Remove leading blanks
+	//
+	do {
+		istr.get(a);
+		if (istr.fail()) return istr;
+	} while( a == ' ' );
+	
+	//
+	// Check for empty list ( '-', followed by EOF or blank)
+	//
+	if (a == '-') {
+		istr.get(a);
+		if (istr.fail() || a == ' ') {
+			nItem = 0;
+			return istr;
+		}
+	}
+		
+	
+	//
+	// Otherwise: Insist argument begin with a '('
+	//
+	if (a != '(') {
+		G4cerr << "Listed argument must begin with '(' or consist of only '-'" << G4endl;
+		istr.clear(std::ios::failbit|istr.rdstate());	// Is there a better way to do this???
+		return istr;
+	}
+
+	//
+	// Loop over items in argument
+	//
+	G4int nItemFetched = 0;
+	do {
+		//
+		// Next item
+		//
+		char *b = buffer;
+		for(;;) {
+			//
+			// Next character
+			//
+			istr.get(*b);
+			if (istr.fail()) return istr;
+			
+			//
+			// Check for delimiter
+			//
+			if (*b == ',' || *b == ')') {
+				a = *b;		// Remember 
+				*b = '\0';
+				break;
+			}
+			
+			//
+			// Go to next character
+			//
+			if (++b > buffer+255) {
+				G4cerr << "Listed argument item must be less than 255 characters" << G4endl;
+				istr.clear(std::ios::failbit|istr.rdstate());
+				return istr;
+			}
+		} 
+		
+		//
+		// Interpret
+		//
+		if (nItemFetched >= maxItem) {
+			G4cerr << "Maximum of " << maxItem << " items exceeded in listed argument" << G4endl;
+			istr.clear(std::ios::failbit|istr.rdstate());
+			return istr;
+		}
+		
+		if (!FetchItem( buffer, nItemFetched++ )) {
+			istr.clear(std::ios::failbit|istr.rdstate());
+			return istr;
+		}
+	} while( a == ',' );
+	
+	//
+	// Set nItem only on success
+	//
+	nItem = nItemFetched;
+	
+	return istr;
+}
+
+
+//
+// ConvertToString
+//
+G4String G4UIcmdPargList::ConvertToString()
+{
+	//
+	// Empty case
+	//
+	if (nItem == 0) return "-";
+	
+	//
+	// Allocate a buffer, big enough to hold all items plus
+	// a command and '()'. Each item is allowed to take 255 
+	// characters.
+	//
+	// buffSize = 255*nItem+4;
+	
+	std::ostringstream os;
+	
+	//
+	// Write out everything in turn
+	//
+	os << '(';
+	
+	G4int item;
+	for( item=0; item<nItem; item++) {
+		if (item) os << ',';
+		if (!WriteItem(os,item)) return "(error)";
+	}
+	
+	os << ')';
+	
+	//
+	// Convert to G4String
+	//
+	G4String answer = os.str();
+		
+	//
+	// Return G4String
+	//
+	return answer;
+}
Index: trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargListDouble.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargListDouble.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/G4UIcmdPargListDouble.cc	(revision 1316)
@@ -0,0 +1,85 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdPargListDouble.cc
+//
+// Implementation of an argument consisting of
+// a list of double values for G4UIcmdWithParg
+//
+
+#include "G4UIcmdPargListDouble.hh"
+
+#include <sstream>
+
+//
+// Constructor
+//
+G4UIcmdPargListDouble::G4UIcmdPargListDouble( const G4String &theName, G4int theMaxItem, 
+					      const G4double theUnits )
+			: G4UIcmdPargList( theName, theMaxItem )
+{
+	units = theUnits;
+	//
+	// Allocate memory for maximum number of items
+	//
+	storage = new G4double [theMaxItem];
+}
+
+
+//
+// Destructor
+//
+G4UIcmdPargListDouble::~G4UIcmdPargListDouble()
+{
+	delete [] storage;
+}
+
+
+//
+// FetchItem
+//
+G4bool G4UIcmdPargListDouble::FetchItem( const char *string, const G4int item )
+{
+	std::istringstream is( string );
+	is >> storage[item];
+	if (is.fail()) {
+		G4cerr << "Error interpreting '" << string << "' as a double value" << G4endl;
+		return false;
+	}
+	storage[item] *= units;
+	
+	return true;
+}
+
+
+//
+// WriteItem
+//
+std::ostream &G4UIcmdPargListDouble::WriteItem( std::ostream &ios, const G4int item )
+{
+	ios << storage[item];
+	return ios;
+}
Index: trunk/source/geometry/solids/test/SBT/src/G4UIcmdWithPargs.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/G4UIcmdWithPargs.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/G4UIcmdWithPargs.cc	(revision 1316)
@@ -0,0 +1,86 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// G4UIcmdWithPargs.cc
+//
+// Implementation of a G4UIcommand with generic arguments
+//
+
+#include "G4UIcmdWithPargs.hh"
+#include "G4UIcmdParg.hh"
+
+#include <sstream>
+
+//
+// Constructor
+//
+G4UIcmdWithPargs::G4UIcmdWithPargs( const char *path, G4UImessenger *theMessenger,
+			  	    G4UIcmdParg **theArgs, const int theNumParg )
+		: G4UIcommand( path, theMessenger )
+{
+	args = theArgs;
+	numArgs = theNumParg;
+	
+	G4UIcmdParg **thisArg;
+	G4int index;
+	for( index=0, thisArg=args; index < numArgs; index++, thisArg++ ) {
+		//
+		// Boy, sure looks like a memory leak, but it isn't.
+		// See G4UIcommand::~G4UIcommand
+		//
+		G4UIparameter *param = new G4UIparameter( (*thisArg)->GetTypeCode() );
+		param->SetParameterName( (*thisArg)->GetName() );
+		param->SetOmittable(false);
+		SetParameter( param );
+	}
+}
+
+
+//
+// Destructor
+//
+G4UIcmdWithPargs::~G4UIcmdWithPargs() {;}
+
+
+//
+// GetArguments
+//
+// Unlike the standard G4UIcommand, the values are returned in the
+// in the array of arguments given to the constructor
+//
+G4bool G4UIcmdWithPargs::GetArguments( G4String argumentString )
+{
+	const char *buff = argumentString;
+	std::istringstream is( buff );
+	
+	G4UIcmdParg **thisArg = args;
+	while( thisArg < args + numArgs ) {
+		(*thisArg++)->FetchValue(is);
+		if (is.fail()) return false;
+	}
+	
+	return true;
+}
Index: trunk/source/geometry/solids/test/SBT/src/SBTMessenger.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/SBTMessenger.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/SBTMessenger.cc	(revision 1316)
@@ -0,0 +1,411 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTMessenger.cc
+//
+// Implementation of the messenger for controlling test 3
+//
+
+#include "SBTMessenger.hh"
+#include "SBTrun.hh"
+#include "SBTVisManager.hh"
+#include "G4SolidQuery.hh"
+
+#include "G4ios.hh"
+#include "G4UIdirectory.hh"
+#include "G4UIcommand.hh"
+#include "G4UIcmdWith3VectorAndUnit.hh"
+#include "G4UIcmdWithAnInteger.hh"
+#include "G4UIcmdWithAString.hh"
+#include "G4UIcmdWithoutParameter.hh"
+
+#include <fstream>
+
+//
+// Constructor
+//
+SBTMessenger::SBTMessenger( const G4String prefix, const G4SolidQuery *theSolidQuery, SBTVisManager *theVisManager )
+{
+	//
+	// Store solid query
+	//
+	solidQuery = theSolidQuery;
+	
+	//
+	// Store visualization manager
+	//
+	visManager = theVisManager;
+
+	//
+	// Defaults (of locally stored values)
+	//
+	errorFile = "sbt.log";
+	
+	//
+	// Create tester
+	//
+	tester = new SBTrun();
+	
+	//
+	// Declare directory
+	//
+	test3Directory = new G4UIdirectory( prefix );
+	test3Directory->SetGuidance( "Controls for CSG batch test" );
+	
+	//
+	// Target command
+	//
+	G4String com = prefix+"target";
+	targetCmd = new G4UIcmdWith3VectorAndUnit( com, this );
+	targetCmd->SetGuidance( "Center of distribution of random points" );
+	targetCmd->SetParameterName( "X", "Y", "Z", true, true );
+	
+	//
+	// Widths command
+	//
+	com = prefix+"widths";
+	widthsCmd = new G4UIcmdWith3VectorAndUnit( com, this );
+	widthsCmd->SetGuidance( "Widths of distribution of random points" );
+	widthsCmd->SetParameterName( "Dx", "Dy", "Dz", true, true );
+	
+	//
+	// Grid Size command
+	//
+	com = prefix+"gridSizes";
+	gridSizesCmd = new G4UIcmdWith3VectorAndUnit( com, this );
+	gridSizesCmd->SetGuidance( "Grid size, or zero for no grid" );
+	gridSizesCmd->SetParameterName( "Dx", "Dy", "Dz", true, true );
+	
+	//
+	// Max Points command
+	//
+	com = prefix+"maxPoints";
+	maxPointsCmd = new G4UIcmdWithAnInteger( com, this );
+	maxPointsCmd->SetGuidance( "Maximum number of points before test ends" );
+
+	//
+	// Max Errors command
+	//	
+	com = prefix+"maxErrors";
+	maxErrorsCmd = new G4UIcmdWithAnInteger( com, this );
+	maxErrorsCmd->SetGuidance( "Maximum number of errors before test ends" );
+	
+	//
+	// Error filename command
+	//
+	com = prefix+"errorFileName";
+	errorFileCmd = new G4UIcmdWithAString( com, this );
+	errorFileCmd->SetGuidance( "Filename in which to send error listings" );
+	
+	//
+	// Run command
+	//
+	com = prefix+"run";
+	runCmd = new G4UIcmdWithoutParameter( com, this );
+	runCmd->SetGuidance( "Execute test 3" );
+	
+	//
+	// Debug commands
+	//
+	com = prefix+"draw";
+	drawCmd = new G4UIcmdWithAnInteger( com, this );
+	drawCmd->SetGuidance( "Draw error listed in log file" );
+	
+	com = prefix+"debugInside";
+	debugInsideCmd = new G4UIcmdWithAnInteger( com, this );
+	debugInsideCmd->SetGuidance( "Call G4VSolid::Inside for error listed in log file" );
+	
+	com = prefix+"debugToInP";
+	debugToInPCmd = new G4UIcmdWithAnInteger( com, this );
+	debugToInPCmd->SetGuidance( "Call G4VSolid::DistanceToIn(p) for error listed in log file" );
+	
+	com = prefix+"debugToInPV";
+	debugToInPVCmd = new G4UIcmdWithAnInteger( com, this );
+	debugToInPVCmd->SetGuidance( "Call G4VSolid::DistanceToIn(p,v) for error listed in log file" );
+	
+	com = prefix+"debugToOutP";
+	debugToOutPCmd = new G4UIcmdWithAnInteger( com, this );
+	debugToOutPCmd->SetGuidance( "Call G4VSolid::DistanceToOut(p) for error listed in log file" );
+	
+	com = prefix+"debugToOutPV";
+	debugToOutPVCmd = new G4UIcmdWithAnInteger( com, this );
+	debugToOutPVCmd->SetGuidance( "Call G4VSolid::DistanceToOut(p,v) for error listed in log file" );
+
+	com = prefix+"debugSurfNorm";
+	debugSurfNormCmd = new G4UIcmdWithAnInteger( com, this );
+	debugSurfNormCmd->SetGuidance( "Call G4VSolid::SurfaceNormal(p) for error listed in log file" );
+
+	//
+	// Pause command
+	//
+	com = prefix+"pause";
+	pauseCmd = new G4UIcmdWithoutParameter( com, this );
+	pauseCmd->SetGuidance( " Wait for a key " );
+	
+}
+
+
+//
+// Destructor
+//
+SBTMessenger::~SBTMessenger()
+{
+	delete targetCmd;
+	delete widthsCmd;
+	delete gridSizesCmd;
+	delete maxPointsCmd;
+	delete maxErrorsCmd;
+	delete errorFileCmd;
+	delete test3Directory;
+}
+
+
+//
+// InvokeTest3
+//
+// Run test 3
+//
+void SBTMessenger::InvokeTest3()
+{
+	//
+	// Is there a Solid to test?
+	//
+	G4VSolid *testSolid = solidQuery->GetSolid();
+	if (testSolid == 0) {
+		G4cerr << "Please initialize geometry before running test 3" << G4endl;
+		G4cerr << "Test 3 ABORTED" << G4endl;
+		return;
+	}
+
+	//
+	// Open output file
+	//
+	std::ofstream logFile( errorFile );
+	
+	//
+	// Run the test
+	//
+	tester->RunTest( testSolid, logFile );
+}
+
+
+//
+// Debug
+//
+// Run an event that should (approximately) duplicate the conditions
+// of one of the bugs discovered in a previous test3 run and stored
+// in a log file
+//
+void SBTMessenger::Debug( const G4int errorIndex,  SBTMessenger::Debugger *debugger )
+{
+	//
+	// Is there a Solid to test?
+	//
+	// If I was really clever (I'm not) I would also check
+	// to make sure we have the same solid type and even the
+	// same solid parameters.
+	//
+	G4VSolid *testSolid = solidQuery->GetSolid();
+	if (testSolid == 0) {
+		G4cerr << "Please initialize geometry before debugging/drawing" << G4endl;
+		return;
+	}
+
+	//
+	// Open output file
+	//
+	std::ifstream logFile( errorFile );
+	if (!logFile) {
+		G4cerr << "Cannot open input file " << errorFile << G4endl;
+		return;
+	}
+	
+	//
+	// Debug
+	//
+	if (debugger->DebugMe( logFile, errorIndex )) {
+		G4cerr << "Error reading index " << errorIndex << " from input file " << errorFile << G4endl;
+	}
+}
+
+
+//
+// DebugMe (various classes)
+//
+G4int SBTMessenger::DrawError::DebugMe( std::ifstream &logFile, const G4int errorIndex )
+{
+	if (visManager) {
+		//
+		// Make sure we're kosher
+		//
+		if (visManager->BuildFakeWorld()) return 2;
+		
+		return tester->DrawError( testSolid, logFile, errorIndex, visManager );
+	}
+	
+	
+	G4cerr << "Visualization is not available in this executable" << G4endl;
+	return 1;
+}
+
+G4int SBTMessenger::DebugInside::DebugMe( std::ifstream &logFile, const G4int errorIndex )
+{
+	return tester->DebugInside( testSolid, logFile, errorIndex );
+}
+
+G4int SBTMessenger::DebugToInP::DebugMe( std::ifstream &logFile, const G4int errorIndex )
+{
+	return tester->DebugToInP( testSolid, logFile, errorIndex );
+}
+
+G4int SBTMessenger::DebugToInPV::DebugMe( std::ifstream &logFile, const G4int errorIndex )
+{
+	return tester->DebugToInPV( testSolid, logFile, errorIndex );
+}
+
+G4int SBTMessenger::DebugToOutP::DebugMe( std::ifstream &logFile, const G4int errorIndex )
+{
+	return tester->DebugToOutP( testSolid, logFile, errorIndex );
+}
+
+G4int SBTMessenger::DebugToOutPV::DebugMe( std::ifstream &logFile, const G4int errorIndex )
+{
+	return tester->DebugToOutPV( testSolid, logFile, errorIndex );
+}
+
+G4int SBTMessenger::DebugSurfNorm::DebugMe( std::ifstream &logFile, const G4int errorIndex )
+{
+	return tester->DebugSurfNorm( testSolid, logFile, errorIndex );
+}
+
+//
+// SetNewValue
+//
+// Call by the UI when user requests a change
+//
+void SBTMessenger::SetNewValue( G4UIcommand *command, G4String newValues )
+{
+	if (command == targetCmd) {
+		tester->SetTarget( targetCmd->GetNew3VectorValue( newValues ) );
+	}
+	else if (command == widthsCmd) {
+		tester->SetWidths( widthsCmd->GetNew3VectorValue( newValues ) );
+	}
+	else if (command == gridSizesCmd) {
+		tester->SetGrids( gridSizesCmd->GetNew3VectorValue( newValues ) );
+	}
+	else if (command == maxPointsCmd) {
+		tester->SetMaxPoints( maxPointsCmd->GetNewIntValue( newValues ) );
+	}
+	else if (command == maxErrorsCmd) {
+		tester->SetMaxErrors( maxErrorsCmd->GetNewIntValue( newValues ) );
+	}
+	else if (command == errorFileCmd) {
+		errorFile = newValues;
+	}
+	else if (command == runCmd) {
+		InvokeTest3();
+	}
+	else if (command == drawCmd) {
+		SBTMessenger::DrawError debugger( solidQuery->GetSolid(), tester, visManager );
+		Debug( drawCmd->GetNewIntValue( newValues ), &debugger );
+	}
+	else if (command == debugInsideCmd) {
+		SBTMessenger::DebugInside debugger( solidQuery->GetSolid(), tester );
+		Debug( debugInsideCmd->GetNewIntValue( newValues ), &debugger );
+	}
+	else if (command == debugToInPCmd) {
+		SBTMessenger::DebugToInP debugger( solidQuery->GetSolid(), tester );
+		Debug( debugToInPCmd->GetNewIntValue( newValues ), &debugger );
+	}
+	else if (command == debugToInPVCmd) {
+		SBTMessenger::DebugToInPV debugger( solidQuery->GetSolid(), tester );
+		Debug( debugToInPVCmd->GetNewIntValue( newValues ), &debugger );
+	}
+	else if (command == debugToOutPCmd) {
+		SBTMessenger::DebugToOutP debugger( solidQuery->GetSolid(), tester );
+		Debug( debugToOutPCmd->GetNewIntValue( newValues ), &debugger );
+	}
+	else if (command == debugToOutPVCmd) {
+		SBTMessenger::DebugToOutPV debugger( solidQuery->GetSolid(), tester );
+		Debug( debugToOutPVCmd->GetNewIntValue( newValues ), &debugger );
+	}
+	else if (command == debugSurfNormCmd) {
+		SBTMessenger::DebugSurfNorm debugger( solidQuery->GetSolid(), tester );
+		Debug( debugSurfNormCmd->GetNewIntValue( newValues ), &debugger );
+	}
+	else if (command == pauseCmd) {
+	  char c;
+	  
+	  G4cout << "Press ENTER to continue..." << std::flush ;
+	  G4cin.get(c);
+	}
+	else {
+		G4Exception( "Unrecognized command" );
+	}
+}
+
+
+//
+// GetCurrentValue
+//
+G4String SBTMessenger::GetCurrentValue( G4UIcommand *command )
+{
+	if (command == targetCmd) {
+		return targetCmd->ConvertToString( tester->GetTarget(), "m" );
+	}
+	else if (command == widthsCmd) {
+		return widthsCmd->ConvertToString( tester->GetWidths(), "m" );
+	}
+	else if (command == gridSizesCmd) {
+		return gridSizesCmd->ConvertToString( tester->GetGrids(), "m" );
+	}
+	else if (command == maxPointsCmd) {
+		return maxPointsCmd->ConvertToString( tester->GetMaxPoints() );
+	}
+	else if (command == maxErrorsCmd) {
+		return maxErrorsCmd->ConvertToString( tester->GetMaxErrors() );
+	}
+	else if (command == errorFileCmd) {
+		return errorFile;
+	}
+	else if (command == runCmd) {
+		return "";
+	}
+	else if (command == drawCmd ||
+		 command == debugInsideCmd ||
+		 command == debugToInPCmd ||
+		 command == debugToInPVCmd ||
+		 command == debugToOutPCmd ||
+		 command == debugToOutPVCmd  ||
+		 command == debugSurfNormCmd    ) {
+		return "";
+	}
+	
+	G4Exception( "Unrecognized command" );
+	return "foo!";
+}
+	
Index: trunk/source/geometry/solids/test/SBT/src/SBTVisManager.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/SBTVisManager.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/SBTVisManager.cc	(revision 1316)
@@ -0,0 +1,177 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTVisManager
+//
+// Implementation of visualization manager for SBT
+//
+
+#include "SBTVisManager.hh"
+#include "G4ModelingParameters.hh"
+#include "G4BoundingSphereScene.hh"
+
+//
+// The following is borrowed from GEANT4's example "N02"
+//
+// Supported drivers...
+ 
+// Not needing external packages or libraries...
+#include "G4ASCIITree.hh"
+#include "G4DAWNFILE.hh"
+#include "G4HepRepFile.hh"
+#include "G4HepRep.hh"
+#include "G4RayTracer.hh"
+#include "G4VRML1File.hh"
+#include "G4VRML2File.hh"
+
+#ifdef G4VIS_USE_DAWN
+#include "G4FukuiRenderer.hh"
+#endif
+ 
+#ifdef G4VIS_USE_OPENGLX
+#include "G4OpenGLImmediateX.hh"
+#include "G4OpenGLStoredX.hh"
+#endif
+ 
+#ifdef G4VIS_USE_OPENGLWIN32
+#include "G4OpenGLImmediateWin32.hh"
+#include "G4OpenGLStoredWin32.hh"
+#endif
+ 
+#ifdef G4VIS_USE_OPENGLXM
+#include "G4OpenGLImmediateXm.hh"
+#include "G4OpenGLStoredXm.hh"
+#endif
+ 
+#ifdef G4VIS_USE_OIX
+#include "G4OpenInventorX.hh"
+#endif
+
+#ifdef G4VIS_USE_OIWIN32
+#include "G4OpenInventorWin32.hh"
+#endif
+
+
+#ifdef G4VIS_USE_VRML
+#include "G4VRML1.hh"
+#include "G4VRML2.hh"
+#endif
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void SBTVisManager::RegisterGraphicsSystems () {
+
+  // Graphics Systems not needing external packages or libraries...
+  RegisterGraphicsSystem (new G4ASCIITree);
+  RegisterGraphicsSystem (new G4DAWNFILE);
+  RegisterGraphicsSystem (new G4HepRepFile);
+  RegisterGraphicsSystem (new G4HepRep);
+  RegisterGraphicsSystem (new G4RayTracer);
+  RegisterGraphicsSystem (new G4VRML1File);
+  RegisterGraphicsSystem (new G4VRML2File);
+
+#ifdef G4VIS_USE_DAWN
+  RegisterGraphicsSystem (new G4FukuiRenderer);
+#endif
+
+#ifdef G4VIS_USE_OPENGLX
+  RegisterGraphicsSystem (new G4OpenGLImmediateX);
+  RegisterGraphicsSystem (new G4OpenGLStoredX);
+#endif
+ 
+#ifdef G4VIS_USE_OPENGLWIN32
+  RegisterGraphicsSystem (new G4OpenGLImmediateWin32);
+  RegisterGraphicsSystem (new G4OpenGLStoredWin32);
+#endif
+ 
+#ifdef G4VIS_USE_OPENGLXM
+  RegisterGraphicsSystem (new G4OpenGLImmediateXm);
+  RegisterGraphicsSystem (new G4OpenGLStoredXm);
+#endif
+ 
+#ifdef G4VIS_USE_OIX
+  RegisterGraphicsSystem (new G4OpenInventorX);
+#endif
+ 
+#ifdef G4VIS_USE_OIWIN32
+  RegisterGraphicsSystem (new G4OpenInventorWin32);
+#endif
+ 
+#ifdef G4VIS_USE_VRML
+  RegisterGraphicsSystem (new G4VRML1);
+  RegisterGraphicsSystem (new G4VRML2);
+#endif
+ 
+  if (fVerbose > 0) {
+    G4cout <<
+      "\nYou have successfully chosen to use the following graphics systems."
+         << G4endl;
+    PrintAvailableGraphicsSystems ();
+  }
+}
+
+
+
+//
+// BuildFakeWorld
+//
+// It is a little troubling how difficult it is to get visualization
+// working if one doesn't build geometry in the standard manner
+// (i.e. have a valid setting at 
+//    G4TransportationManager::GetTransportationManager ()
+//      -> GetNavigatorForTracking () -> GetWorldVolume ();   )
+//
+//
+// Why is this so? Why shouldn't one be able to use visualization
+// in cases like SBT?
+//
+G4int SBTVisManager::BuildFakeWorld() const
+{
+        //
+        // These are probably leaks...
+        //
+        G4ModelingParameters::DrawingStyle style = G4ModelingParameters::wf;
+        G4ModelingParameters *model = new G4ModelingParameters
+                                            (0,      // No default vis attributes.
+                                             style,  // Wireframe
+                                             true,   // Global culling.
+                                             true,   // Cull invisible volumes.
+                                             false,  // Density culling.
+                                             0.,     // Density (not relevant if density culling false).
+                                             true,   // Cull daughters of opaque mothers.
+                                             24);    // No of sides (not relevant for this operation).
+        SBTFakeModel *fakeModel = new SBTFakeModel(model);
+
+        G4Scene *currentScene = GetCurrentScene();
+
+        if (!currentScene) {
+                G4cerr << "Please create a view first" << G4endl;
+                return 1;
+        }
+        
+        currentScene->AddRunDurationModel( (G4VModel *)fakeModel );
+        return 0;
+}
Index: trunk/source/geometry/solids/test/SBT/src/SBTrun.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/SBTrun.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/SBTrun.cc	(revision 1316)
@@ -0,0 +1,959 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTrun
+//
+// Implementation of the batch solid test
+//
+#include "SBTrun.hh"
+
+#include "Randomize.hh"
+#include "G4VSolid.hh"
+
+#include "SBTVisManager.hh"
+#include "G4Polyline.hh"
+#include "G4Circle.hh"
+#include "G4Color.hh"
+#include "G4VisAttributes.hh"
+#include "G4GeometryTolerance.hh"
+#include "G4SolidStore.hh"
+
+#include <iomanip>
+#include <sstream>
+#include <time.h>
+
+#define DEBUG 0
+
+//
+// Constructor
+//
+SBTrun::SBTrun()
+{
+  //
+  // Defaults
+  //
+  SetDefaults();
+
+  //
+  // Zero error list
+  //
+  errorList = 0;
+  CurrentSolid = "";
+}
+
+
+//
+// Destructor
+//
+SBTrun::~SBTrun()
+{
+  ClearErrors();
+}
+
+
+//
+// SetDefaults
+//
+// Set defaults values
+//
+void SBTrun::SetDefaults()
+{
+  target = G4ThreeVector( 0, 0, 0 );
+  widths = G4ThreeVector( 1*m, 1*m, 1*m );
+  grids  = G4ThreeVector( 0, 0, 0 );
+
+  maxPoints = 10000;
+  maxErrors = 100;
+}
+
+
+//
+// GetRandomPoint
+//
+// Return a random point in three dimensions using the current
+// specs 
+//
+G4ThreeVector SBTrun::GetRandomPoint() const {
+  G4double dx = widths.x()*GaussianRandom(10*m/widths.x()),
+    dy = widths.y()*GaussianRandom(10*m/widths.y()),
+    dz = widths.z()*GaussianRandom(10*m/widths.z());
+
+
+  if (grids.x() > 0) dx = grids.x()*G4int( dx/grids.x()+1 );
+  if (grids.y() > 0) dy = grids.y()*G4int( dy/grids.y()+1 );
+  if (grids.z() > 0) dz = grids.z()*G4int( dz/grids.z()+1 );
+
+  G4ThreeVector randvec( dx, dy, dz );
+
+  return target + randvec;
+}
+
+
+//
+// GaussianRandom
+//
+// Return Gaussian random number of unit width
+//
+// A classic, slow, but remarkably effective algorithm. Certainly good
+// enough for our purposes.
+//
+G4double SBTrun::GaussianRandom(const G4double cutoff) const {
+  if (cutoff <= 0) G4Exception( "Illegal cutoff" );
+
+  G4double answer;
+  do {
+    answer = -3.0;
+    for( G4int j = 0; j < 6; j++ ) answer += G4UniformRand();
+    answer *= std::sqrt(2.0);
+  } while( std::fabs(answer) > cutoff );
+
+  return(answer);
+}
+
+
+//
+// RunTest
+//
+// Do your stuff!
+//
+void SBTrun::RunTest( const G4VSolid *testVolume, std::ostream &logger )
+{
+  //
+  // Clear error list
+  //
+    
+  ClearErrors();
+
+	  //
+	  // Output test parameters
+	  //
+  time_t now = time(0);
+  time(&now);
+  G4String dateTime(ctime(&now));
+
+  {
+    /* 
+       MEDERNACH Emmanuel
+       aug 2000
+	       
+       We try to retrieve the solid being tested 
+       to write in the log file
+    */
+
+    G4SolidStore* SolidStore = G4SolidStore::GetInstance();
+    G4cout << ((*SolidStore)[0])->GetName() << G4endl ;
+  }
+
+
+  logger << "% SBT logged output " << dateTime;
+  logger << "% " << CurrentSolid << G4endl;
+  logger << "% target =    " << target << G4endl;
+  logger << "% widths =    " << widths << G4endl;
+  logger << "% grids  =    " << grids  << G4endl;
+  logger << "% maxPoints = " << maxPoints << G4endl;
+  logger << "% maxErrors = " << maxErrors << G4endl;
+
+	  //
+	  // Setup lists
+	  //
+  SBTrunPointList inside(100);
+  SBTrunPointList outside(100);
+  SBTrunPointList surface(100);
+
+  //
+  // Set iostream precision to 20 digits
+  //
+  logger << std::setprecision(20);
+
+  //
+  // Set clock
+  //
+  // clock_t start = clock();
+
+  //
+  // Loop over points
+  //
+  G4int nIn = 0, nOut = 0, nSurf = 0;
+
+  G4int nPoint = 0;
+  G4int nError = 0;
+
+  std::setprecision(20);
+
+  for(;;) {
+    //
+    // Generate a random point
+    //
+    G4ThreeVector	point = GetRandomPoint();
+
+#if DEBUG
+    G4cerr << std::setprecision(32);
+    G4cerr << "Current point is : " << point* (1/cm) << G4endl ;
+#endif
+		  //
+		  // Catagorize, test, and store
+		  //
+    EInside catagory = testVolume->Inside( point );
+
+
+    switch( catagory ) {
+    case kOutside:
+      //G4cerr << "kOutside " << G4endl;
+      
+      nOut++;
+      TestOutsidePoint( testVolume, &nError, &inside, &outside, point, logger );
+      outside.AddPoint( point );
+      break;
+
+    case kInside:
+      //G4cerr << "kInside " << G4endl;
+      
+      nIn++;
+      TestInsidePoint( testVolume, &nError, &outside, point, logger );
+      inside.AddPoint( point );
+      break;
+
+    case kSurface:
+      //G4cerr << "kSurface " << G4endl;
+      
+      nSurf++;
+      //			TestSurfacePoint( testVolume, &nError, point, logger );
+      surface.AddPoint( point );
+      break;
+    }
+
+    //
+    // Return early if we have accumulated enough errors
+    //
+    if (nError >= maxErrors) {
+      logger << "% End of test (maximum number errors) ";
+      break;
+    }
+
+    if (++nPoint >= maxPoints) {
+      logger << "% End of test (maximum number points) ";
+      break;
+    }
+
+  }
+
+  time(&now);
+  G4String dateTime2(ctime(&now));
+  logger << dateTime2;
+
+  logger << "% Statistics: points=" << nPoint << " errors=" << CountErrors()
+	 << " errors reported=" << nError << G4endl;
+
+  logger << "%             inside=" << nIn << " outside=" << nOut
+	 << " surface=" << nSurf << G4endl;
+  logger << "%             cpu time=" << clock()/CLOCKS_PER_SEC << G4endl;
+
+  logger << "%(End of file)" << G4endl;
+}
+
+
+//
+// DrawError
+//
+// Recover previously logged error and display it
+//
+G4int SBTrun::DrawError( const G4VSolid *testVolume, std::istream &logger, 
+			 const G4int errorIndex, SBTVisManager *visManager ) const
+{
+  G4ThreeVector p, v;
+
+  // Now required for drawing
+  G4Transform3D  objectTransformation; 
+
+  //
+  // This draws the target solid
+  //
+  G4VisAttributes redStuff( G4Color(1,0,0) );
+  visManager->Draw( *testVolume, redStuff, objectTransformation );
+
+  if ( errorIndex > 0 ) {
+
+    //
+    // Recover information from log file
+    //
+    G4int error = GetLoggedPV( logger, errorIndex, p, v );
+    if (error) return error;
+
+    G4cout << "DrawError:  p=" << p << ",  v=" << v << G4endl; 
+
+    //
+    // Draw away
+    //
+    // visManager->ClearView();
+
+    //
+    // This draws the trajectory
+    //    
+    G4VisAttributes blueStuff( G4Color(0,0,1) );
+
+    G4Polyline polyline;
+    polyline.push_back( p );
+    polyline.push_back( p + 4*v*m );
+    polyline.SetVisAttributes( blueStuff );
+    visManager->Draw( polyline, objectTransformation);
+
+    //
+    // This draws the initial point p
+    //
+    G4Circle circle(p);
+    circle.SetWorldSize( 5*cm );
+    circle.SetVisAttributes( blueStuff );
+    visManager->Draw( circle, objectTransformation);
+  }
+
+  // visManager->Show();
+
+  return 0;
+}
+
+
+//
+// DebugInside
+//
+// Recover previously logged error and invoke G4VSolid::Inside
+//
+G4int SBTrun::DebugInside( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const
+{	
+  G4ThreeVector p, v;
+
+  //
+  // Recover information from log file
+  //
+  G4int error = GetLoggedPV( logger, errorIndex, p, v );
+  if (error) return error;
+
+  //
+  // Call
+  //
+  G4cout << "testVolume->Inside(p): " << testVolume->Inside( p ) << G4endl; 
+  return 0;
+}
+
+
+//
+// DebugToInP
+//
+// Recover previously logged error and invoke G4VSolid::DistanceToIn(p)
+//
+G4int SBTrun::DebugToInP( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const
+{	
+  G4ThreeVector p, v;
+
+  //
+  // Recover information from log file
+  //
+  G4int error = GetLoggedPV( logger, errorIndex, p, v );
+  if (error) return error;
+
+  //
+  // Call
+  //
+  G4cout << "testVolume->DistanceToIn(p): " <<  testVolume->DistanceToIn( p ) << G4endl; 
+  return 0;
+}
+
+
+//
+// DebugToInPV
+//
+// Recover previously logged error and invoke G4VSolid::DistanceToIn(p,v)
+//
+G4int SBTrun::DebugToInPV( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const
+{	
+  G4ThreeVector p, v;
+
+  //
+  // Recover information from log file
+  //
+  G4int error = GetLoggedPV( logger, errorIndex, p, v );
+  if (error) return error;
+
+  //
+  // Call
+  //
+  G4double answer = testVolume->DistanceToIn( p, v );
+  G4cout << "testVolume->DistanceToIn(p,v): " << answer << G4endl; 
+
+  p += answer*v;
+
+  G4cout << "testVolume->Inside(p+=answer*v):" <<  p << " " << testVolume->Inside(p) << G4endl;
+  return 0;
+}
+
+
+//
+// DebugToOutP
+//
+// Recover previously logged error and invoke G4VSolid::DistanceToOut(p)
+//
+G4int SBTrun::DebugToOutP( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const
+{	
+  G4ThreeVector p, v;
+
+  //
+  // Recover information from log file
+  //
+  G4int error = GetLoggedPV( logger, errorIndex, p, v );
+  if (error) return error;
+
+  //
+  // Call
+  //
+  G4cout << "testVolume->DistanceToOut(p): " << testVolume->DistanceToOut( p ) << G4endl; 
+  return 0;
+}
+
+
+//
+// DebugToOutPV
+//
+// Recover previously logged error and invoke G4VSolid::DistanceToOut(p,v)
+//
+G4int SBTrun::DebugToOutPV( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const
+{	
+  G4ThreeVector p, v;
+
+  //
+  // Recover information from log file
+  //
+  G4int error = GetLoggedPV( logger, errorIndex, p, v );
+  if (error) return error;
+
+  //
+  // Call
+  //
+  G4bool validNorm;
+  G4ThreeVector norm;
+  G4double answer = testVolume->DistanceToOut( p, v );
+  G4cout << "testVolume->DistanceToOut( p, v ): " << answer << " validNorm: " << validNorm << G4endl; 
+
+  p += answer*v;
+  G4cout << "testVolume->Inside(p += answer*v): " << testVolume->Inside(p) << G4endl; 
+
+  return 0;
+}
+
+//
+// DebugSurfNorm
+//
+// Recover previously logged error and invoke G4VSolid::SurfaceNormal(p)
+//
+G4int SBTrun::DebugSurfNorm( const G4VSolid *testVolume, std::istream &logger, const G4int errorIndex ) const
+{	
+  G4ThreeVector p, v;
+
+  //
+  // Recover information from log file
+  //
+  G4int error = GetLoggedPV( logger, errorIndex, p, v );
+  if (error) return error;
+
+  //
+  // Call
+  //
+  G4ThreeVector norm = testVolume->SurfaceNormal(p);
+  G4cout << "testVolume->SurfaceNormal(p): " << norm << G4endl; 
+
+  G4double answer = norm.dot(v);
+  G4cout << "norm.dot(v): " << answer << G4endl; 
+
+  return 0;
+}
+
+//
+// --------------------------------------
+// Tests
+//
+
+//
+// TestOutsidePoint
+//
+void SBTrun::TestOutsidePoint( const G4VSolid *testVolume, G4int *nError,
+			       const SBTrunPointList *inside, const SBTrunPointList *outside,
+			       const G4ThreeVector point, std::ostream &logger )
+{
+  G4int i, n = inside->NumPoints();
+  
+  G4double safeDistance = testVolume->DistanceToIn( point );
+
+  if (safeDistance <= 0.0) {
+    ReportError( nError, point, 0, safeDistance,"T0: DistanceToIn(p) <= 0", logger );
+    return;
+  }
+
+  for( i=0; i < n; i++ ) {
+    G4ThreeVector vr = (*inside)[i] - point;
+    G4ThreeVector v = vr.unit();
+
+    G4double dist = testVolume->DistanceToIn( point, v );
+    if (dist <= 0) {
+      ReportError( nError, point, v, safeDistance, "T0: DistanceToIn(p,v) <= 0", logger );
+      continue;
+    }
+    if (dist == kInfinity) {
+      ReportError( nError, point, v, safeDistance, "T0: DistanceToIn(p,v) == kInfinity", logger );
+      continue;
+    }
+    if (dist < safeDistance-1E-10) {
+      ReportError( nError, point, v, safeDistance, "T0: DistanceToIn(p,v) < DistanceToIn(p)", logger );
+      continue;
+    }
+
+    G4ThreeVector p = point + dist*v;
+
+    EInside insideOrNot = testVolume->Inside( p );
+    if (insideOrNot == kOutside) {
+      ReportError( nError, point, v, safeDistance, "T0: DistanceToIn(p,v) undershoots", logger );
+      continue;
+    }
+    if (insideOrNot == kInside) {
+      ReportError( nError, point, v, safeDistance, "TO: DistanceToIn(p,v) overshoots", logger );
+      continue;
+    }
+
+    dist = testVolume->DistanceToIn( p );
+
+    //if (dist != 0) {
+    if (dist > G4GeometryTolerance::GetInstance()->GetSurfaceTolerance()) {
+      ReportError( nError, p, v, safeDistance, "T02: DistanceToIn(p) should be zero", logger );
+      // logger << "Dist != 0 : " << dist << endl;
+      continue;
+    }
+
+    dist = testVolume->DistanceToOut( p );
+    //if (dist != 0) {
+    if (dist > G4GeometryTolerance::GetInstance()->GetSurfaceTolerance()) {
+      ReportError( nError, p, v, safeDistance, "T02: DistanceToOut(p) should be zero", logger );
+      continue;
+    }
+
+    dist = testVolume->DistanceToIn( p, v );
+    safeDistance = testVolume->DistanceToIn( p );
+    //
+    // Beware! We might expect dist to be precisely zero, but this may not
+    // be true at corners due to roundoff of the calculation of p = point + dist*v.
+    // It should, however, *not* be infinity.
+    //
+    if (dist == kInfinity) {
+      ReportError( nError, p, v, safeDistance, "T02: DistanceToIn(p,v) == kInfinity", logger );
+      continue;
+    }	
+
+    G4bool validNorm;
+    G4ThreeVector norm;
+
+    dist = testVolume->DistanceToOut( p, v, true, &validNorm, &norm );
+    if (dist == 0) continue;
+
+    if (dist == kInfinity) {
+      ReportError( nError, p, v, safeDistance, "T02: DistanceToOut(p,v) == kInfinity", logger );
+      continue;
+    }
+    else if (dist < 0) {
+      ReportError( nError, p, v, safeDistance, "T02: DistanceToOut(p,v) < 0", logger );
+      continue;
+    }
+
+    if (validNorm) {
+      if (norm.dot(v) < 0) {
+	ReportError( nError, p, v, safeDistance, "T02: Outgoing normal incorrect", logger );
+	continue;
+      }
+    }
+
+    G4ThreeVector norm1 = testVolume->SurfaceNormal( p );
+    if (norm1.dot(v) > 0) {
+      ReportError( nError, p, v, safeDistance, "T02: Ingoing surfaceNormal is incorrect", logger );
+    }
+
+
+    G4ThreeVector p2 = p + v*dist;
+
+    insideOrNot = testVolume->Inside(p2);
+    if (insideOrNot == kInside) {
+      ReportError( nError, p, v, safeDistance, "T02: DistanceToOut(p,v) undershoots", logger );
+      continue;
+    }
+    if (insideOrNot == kOutside) {
+      ReportError( nError, p, v, safeDistance, "TO2: DistanceToOut(p,v) overshoots", logger );
+      continue;
+    }
+
+    G4ThreeVector norm2 = testVolume->SurfaceNormal( p2 );
+    if (norm2.dot(v) < 0) {
+      if (testVolume->DistanceToIn(p2,v) != 0)
+	ReportError( nError, p2, v, safeDistance, "T02: Outgoing surfaceNormal is incorrect", logger );
+    }
+    if (validNorm) {
+      if (norm.dot(norm2) < 0.0) {
+	ReportError( nError, p2, v, safeDistance, "T02: SurfaceNormal and DistanceToOut disagree on normal", logger );
+      }
+    }
+
+    if (validNorm) {
+      dist = testVolume->DistanceToIn(p2,v);
+      if (dist == 0) {
+	//
+	// We may have grazed a corner, which is a problem of design.
+	// Check distance out
+	//
+	if (testVolume->DistanceToOut(p2,v) != 0) {
+	  ReportError( nError, p, v, safeDistance, "TO2: DistanceToOut incorrectly returns validNorm==true (line of sight)(c)", logger );
+	  continue;
+	}
+      }
+      else if (dist != kInfinity) {
+	ReportError( nError, p, v, safeDistance, "TO2: DistanceToOut incorrectly returns validNorm==true (line of sight)", logger );
+	continue;
+      }
+
+      G4int j;
+      for( j=0; j < n; j++ ) {
+	G4ThreeVector p2top = (*inside)[j] - p2;
+
+	if (p2top.dot(norm) > 0) {
+	  ReportError( nError, p, v,safeDistance, 
+		       "T02: DistanceToOut incorrectly returns validNorm==true (horizon)", logger );
+	  continue;
+	}
+      }
+    } // if valid normal
+  } // Loop over inside points
+
+  n = outside->NumPoints();
+
+  for( i=0; i < n; i++ ) {
+    G4ThreeVector vr = (*outside)[i] - point;
+    if (vr.mag2() < DBL_MIN) continue;
+
+    G4ThreeVector v = vr.unit();
+
+#if DEBUG    
+    G4cerr << std::setprecision(32);
+    G4cerr << "point = " << point << G4endl ;
+    G4cerr << "v = " << v << G4endl ;
+#endif
+    
+    G4double dist = testVolume->DistanceToIn( point, v );
+
+#if DEBUG
+    G4cerr << "finished ..\n";
+#endif    
+
+    if (dist <= 0) {
+      ReportError( nError, point, v, safeDistance, "T03: DistanceToIn(p,v) <= 0", logger );
+      continue;
+    }
+    if (dist == kInfinity) {
+      //G4cout << "dist == kInfinity" << G4endl ;
+      continue;
+    }
+    if (dist < safeDistance-1E-10) {
+      ReportError( nError, point, v, safeDistance, "T03: DistanceToIn(p,v) < DistanceToIn(p)", logger );
+      continue;
+    }
+    G4ThreeVector p = point + dist*v;
+
+    EInside insideOrNot = testVolume->Inside( p );
+    if (insideOrNot == kOutside) {
+      ReportError( nError, point, v, safeDistance, "T03: DistanceToIn(p,v) undershoots", logger );
+      continue;
+    }
+    if (insideOrNot == kInside) {
+      ReportError( nError, point, v, safeDistance, "TO3: DistanceToIn(p,v) overshoots", logger );
+      continue;
+    }
+  } // Loop over outside points
+}
+
+//
+// TestInsidePoint
+//
+void SBTrun::TestInsidePoint( const G4VSolid *testVolume, G4int *nError,
+			      const SBTrunPointList *outside, const G4ThreeVector point, std::ostream &logger )
+{
+  G4int i, n = outside->NumPoints();
+
+  G4double safeDistance = testVolume->DistanceToOut( point );
+  if (safeDistance <= 0.0) {
+    ReportError( nError, point, 0, safeDistance, "TI: DistanceToOut(p) <= 0", logger );
+    return;
+  }
+
+  G4VisExtent visExtent(testVolume->GetExtent());
+  if (point.x() < visExtent.GetXmin() ||
+      point.x() > visExtent.GetXmax() || 
+      point.y() < visExtent.GetYmin() || 
+      point.y() > visExtent.GetYmax() || 
+      point.z() < visExtent.GetZmin() || 
+      point.z() > visExtent.GetZmax() ) {
+    ReportError( nError, point, 0, safeDistance, "TI: Point is outside G4VisExtent", logger );
+  } 
+
+  for( i=0; i < n; i++ ) {
+    G4ThreeVector vr = (*outside)[i] - point;
+    G4ThreeVector v = vr.unit();
+
+    G4bool validNorm;
+    G4ThreeVector norm;
+
+    G4double dist = testVolume->DistanceToOut( point, v, true, &validNorm, &norm );
+    G4double NormalDist ;
+
+    NormalDist = testVolume->DistanceToOut( point );
+
+    if (dist <= 0) {
+      ReportError( nError, point, v, safeDistance, "TI: DistanceToOut(p,v) <= 0  Normal Dist = ", logger );
+      continue;
+    }
+    if (dist == kInfinity) {
+      ReportError( nError, point, v, safeDistance, "TI: DistanceToOut(p,v) == kInfinity", logger );
+      continue;
+    }
+    if (dist < safeDistance-1E-10) {
+      ReportError( nError, point, v, safeDistance, "TI: DistanceToOut(p,v) < DistanceToIn(p)", logger );
+      continue;
+    }
+
+    if (validNorm) {
+      if (norm.dot(v) < 0) {
+	ReportError( nError, point, v, safeDistance, "TI: Outgoing normal incorrect", logger );
+	continue;
+      }
+    }
+
+    G4ThreeVector p = point + v*dist;
+
+    EInside insideOrNot = testVolume->Inside(p);
+    if (insideOrNot == kInside) {
+      ReportError( nError, point, v, safeDistance, "TI: DistanceToOut(p,v) undershoots", logger );
+      continue;
+    }
+    if (insideOrNot == kOutside) {
+      ReportError( nError, point, v, safeDistance, "TI: DistanceToOut(p,v) overshoots", logger );
+      continue;
+    }
+
+    G4ThreeVector norm1 = testVolume->SurfaceNormal( p );
+    if (norm1.dot(v) < 0) {
+      if (testVolume->DistanceToIn(p,v) != 0)
+	ReportError( nError, p, v, safeDistance, "TI: SurfaceNormal is incorrect", logger );
+    }
+  }
+}
+
+
+//
+// ReportError
+//
+// Report the specified error message, but only if it has not been reported a zillion
+// times already.
+//
+void SBTrun::ReportError( G4int *nError, const G4ThreeVector p, 
+			  const G4ThreeVector v, G4double distance,
+			  const G4String comment, std::ostream &logger )
+{
+  //
+  // Have we encountered this error message before?
+  //
+  SBTrunErrorList *last=0, *errors = errorList;
+  while( errors ) {
+    //
+    // Note: below is an expensive comparison. This could be replaced with something
+    // faster if we really wanted, like a hash. But is it worth the trouble? Nah.
+    //
+    if (errors->message == comment) {
+      //
+      // Yup. Increment count, and return now if the count is too high
+      //
+      if ( ++errors->nUsed > 5 ) return;
+      break;
+    }
+    last = errors;
+    errors = errors->next;
+  }
+
+  if (errors == 0) {
+    //
+    // New error: add it the end of our list
+    //
+    errors = new SBTrunErrorList;
+    errors->message = comment;
+    errors->nUsed = 1;
+    errors->next = 0;
+    if (errorList) 
+      last->next = errors;
+    else
+      errorList = errors;
+  }
+
+  //
+  // Output the message
+  //	
+  logger << "% " << comment;
+  if (errors->nUsed == 5) logger << " (any further such errors suppressed)";
+  logger << " DistanceToIn = " << distance ; 
+  logger << G4endl;
+
+  logger << ++(*nError) << " " << p.x() << " " << p.y() << " " << p.z() 
+	 << " " << v.x() << " " << v.y() << " " << v.z() << G4endl;
+}
+
+
+//
+// ClearErrors
+//
+// Reset list of errors (and clear memory)
+//
+void SBTrun::ClearErrors()
+{
+  SBTrunErrorList *here, *next;
+
+  here = errorList;
+  while( here ) {
+    next = here->next;
+    delete here;
+    here = next;
+  }
+  errorList = 0;
+}
+
+//
+// CountErrors
+//
+// Count up all errors
+//
+G4int SBTrun::CountErrors() const
+{
+  SBTrunErrorList *here;
+  G4int answer = 0;
+
+  here = errorList;
+  while( here ) {
+    answer += here->nUsed;
+    here = here->next;
+  }
+
+  return answer;
+}
+
+
+//
+// GetLoggedPV
+//
+// Get the p and v vectors stored in a test3 log file
+//
+G4int SBTrun::GetLoggedPV( std::istream &logger, const G4int errorIndex,
+			   G4ThreeVector &p, G4ThreeVector &v        ) const
+{
+  //
+  // Search for the requested error index, skipping comments along the way
+  //
+  for(;;) {
+    while( logger.peek() == '%' ) logger.ignore( 99999, '\n' );
+
+    if (logger.peek() == EOF) return 1;
+
+    G4int thisIndex;
+
+    logger >> thisIndex;
+    if (thisIndex == errorIndex) break;
+
+    logger.ignore( 99999, '\n' );
+  }
+
+  //
+  // Extract the vectors
+  //
+  // We should probably have some error checking here...
+  //
+  G4double x, y, z;
+
+  logger >> x >> y >> z;
+  p = G4ThreeVector(x*mm,y*mm,z*mm);
+
+  logger >> x >> y >> z;
+  v = G4ThreeVector(x*mm,y*mm,z*mm);
+
+  return 0;
+}
+
+G4String SBTrun::CurrentSolid = "" ;
+
+G4String SBTrun::GetCurrentSolid(void) 
+{
+  return CurrentSolid; 
+}
+
+void SBTrun::SetCurrentSolid(G4String SolidName)
+{
+  CurrentSolid = SolidName;
+}
+
+//
+// --------------------------------------
+// SBTrunPointList stuff
+//
+
+SBTrunPointList::SBTrunPointList( G4int size )
+{
+  pointList = new G4ThreeVector[size];
+  maxPoints = size;
+  numPoints = 0;
+}
+
+SBTrunPointList::~SBTrunPointList()
+{
+  delete [] pointList;
+}
+
+void SBTrunPointList::AddPoint( G4ThreeVector newPoint )
+{
+  if (numPoints < maxPoints) {
+    //
+    // Since we still have space, append the point on the
+    // end of the list
+    //
+    pointList[numPoints] = newPoint;
+    numPoints++;
+  }
+  else {
+    //
+    // Our list is filled up, so replace a random
+    // entry
+    //
+    G4int	irand = (G4int)((G4UniformRand()*( (G4double)maxPoints )));
+    pointList[irand] = newPoint;
+  }
+}
+
+
+
Index: trunk/source/geometry/solids/test/SBT/src/SBTvoxel.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/SBTvoxel.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/SBTvoxel.cc	(revision 1316)
@@ -0,0 +1,705 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTvoxel.cc
+//
+// Implementation of a batch based voxel test
+//
+
+#include "globals.hh"
+#include "Randomize.hh"
+
+#include "SBTvoxel.hh"
+
+#include "SBTVisManager.hh"
+#include "G4Polyline.hh"
+#include "G4Circle.hh"
+#include "G4Color.hh"
+#include "G4VisAttributes.hh"
+
+#include "G4VSolid.hh"
+#include "G4VoxelLimits.hh"
+#include "G4AffineTransform.hh"
+#include "G4GeometryTolerance.hh"
+#include <iomanip>
+#include <sstream>
+
+#include <time.h>
+
+//
+// Constructor
+//
+SBTvoxel::SBTvoxel()
+{
+  SetDefaults();
+}
+
+
+//
+// Destructor
+//
+SBTvoxel::~SBTvoxel() {;}
+
+
+//
+// SetDefaults
+//
+// Set default values for test parameters
+//
+void SBTvoxel::SetDefaults()
+{
+  target = G4ThreeVector( 0, 0, 0 );
+  widths = G4ThreeVector( 1*m, 1*m, 1*m );
+  
+  maxVoxels = 100;
+  maxErrors = 20;
+}
+
+
+
+//
+// Debug
+//
+// Invoke the CalculateExtent method of the target volume.
+// This can be particularly useful for debugging.
+//
+void SBTvoxel::Debug( const G4VSolid *testVolume, const EAxis axis,
+          const G4VoxelLimits &voxel, const G4AffineTransform &transform,
+          const G4ThreeVector *point ) const
+{
+  G4double min, max;
+  
+  if (testVolume->CalculateExtent( axis, voxel, transform, min, max ))
+    G4cout << "Solid is intersected with: " << min << " " << max << G4endl;
+  else
+    G4cout << "Voxel misses solid" << G4endl;
+
+  if (point) testVolume->Inside( *point );
+}
+
+
+//
+// Draw
+//
+// Draw a test shape and a voxel with arbitrary limits, using
+// an arbitrary tranformation, and with any number of optional
+// markers
+//
+void SBTvoxel::Draw( const G4VSolid *testVolume, 
+         const G4VoxelLimits &voxel, const G4AffineTransform &transform,
+         const G4ThreeVector *points, const G4int numPoints,
+         const EAxis  axis, const G4double limits[2],
+          SBTVisManager *visManager ) const
+{
+  //
+  // Get inverse transform
+  //
+  G4AffineTransform inverseTransform = transform.Inverse();
+
+  //
+  // Prepare visualization
+  //
+        // visManager->ClearView();
+
+  //
+  // Draw voxel as a box.
+  //
+        G4VisAttributes blueStuff( G4Color(0,0,1) );
+        G4VisAttributes yuckStuff( G4Color(0,1,0) );
+
+  static const EAxis axes[3] = { kXAxis, kYAxis, kZAxis };
+  static const G4ThreeVector axisVectors[3] = {G4ThreeVector(1,0,0),
+                 G4ThreeVector(0,1,0),
+                 G4ThreeVector(0,0,1) };
+
+  G4bool drawLimits = limits[0] <= limits[1];
+
+  G4ThreeVector dmin[3], dmax[3], lvec[2];
+  G4int i;
+  for( i=0; i<3; i++ ) {
+    G4double min, max;
+    if (voxel.IsLimited(axes[i])) {
+      min = voxel.GetMinExtent(axes[i]);
+      max = voxel.GetMaxExtent(axes[i]);
+    }
+    else {
+      min = -4.0*m;
+      max = +4.0*m;
+    }
+
+    dmin[i] = min*axisVectors[i];
+    dmax[i] = max*axisVectors[i];
+    
+    if (drawLimits && axis==axes[i]) {
+      lvec[0] = limits[0]*axisVectors[i];
+      lvec[1] = limits[1]*axisVectors[i];
+    }
+  }
+
+  G4Transform3D objectTransformation; 
+  
+  for( i=0; i<3 ;i++ ) {
+    G4int bitmask;
+    for( bitmask=0; bitmask < 8; bitmask++ ) {
+      if (bitmask&(1<<i)) continue;
+      
+      G4ThreeVector a = dmin[i], b = dmax[i];
+      G4ThreeVector c = a, d = b;
+      G4int j;
+      for( j=0; j<3; j++ ) {
+        if (i==j) continue;
+        G4ThreeVector *use = bitmask&(1<<j) ? dmin+j : dmax+j;
+        a += *use;
+        b += *use;
+        if (drawLimits) {
+          if (axes[j]==axis) use = lvec + (bitmask&(1<<j) ? 0 : 1);
+          c += *use;
+          d += *use;
+        }
+      }
+      G4Polyline polyline;
+      polyline.SetVisAttributes( blueStuff );
+      inverseTransform.ApplyPointTransform( a );
+      inverseTransform.ApplyPointTransform( b );
+      polyline.push_back( a );
+      polyline.push_back( b );
+      visManager->Draw( polyline, objectTransformation);
+      
+      if (drawLimits && axes[i]!=axis) {
+        G4Polyline polyline;
+        polyline.SetVisAttributes( yuckStuff );
+        inverseTransform.ApplyPointTransform( c );
+        inverseTransform.ApplyPointTransform( d );
+        polyline.push_back( c );
+        polyline.push_back( d );
+        visManager->Draw( polyline, objectTransformation );
+      }
+    }
+  }
+
+  
+  //
+  // Draw points
+  //
+        G4VisAttributes whiteStuff( G4Color(1,1,1) );
+
+  const G4ThreeVector *thisPoint;
+  for (thisPoint = points; thisPoint < points+numPoints; thisPoint++ ) {
+    G4Circle circle(*thisPoint);
+    circle.SetWorldSize( 5*cm );
+    circle.SetVisAttributes( whiteStuff );
+    visManager->Draw( circle, objectTransformation );
+  }
+    
+  
+  //
+  // This draws the target solid
+  //
+        G4VisAttributes redStuff( G4Color(1,0,0) );
+  visManager->Draw( *testVolume, redStuff, objectTransformation );
+
+        // visManager->Show();
+}
+
+
+//
+// RunTest
+//
+// Perform a test on the specified solid
+//
+void SBTvoxel::RunTest( const G4VSolid *testVolume, std::ostream &logger )
+{
+  //
+  // Output test parameters
+  //
+  time_t now = time(0);
+  time(&now);
+  G4String dateTime(ctime(&now));
+  
+  logger << "% SBT voxel logged output " << dateTime;
+  logger << "% target =    " << target << G4endl;
+  logger << "% widths =    " << widths << G4endl;
+  logger << "% maxVoxels = " << maxVoxels << G4endl;
+  logger << "% maxErrors = " << maxErrors << G4endl;
+
+  G4int nVoxel = 0,
+        nError = 0;
+        
+  //
+  // Generate a list of 1000 random points inside the solid
+  //
+  G4ThreeVector inside[1000];
+  G4int numInside;
+  
+  GetInsidePoints( testVolume, inside, &numInside, 1000, 100000 );
+  
+  G4RotationMatrix randomRotate1, randomRotate2;
+        
+  for(;;) {
+    //
+    // Generate a random voxel limit.
+    // G4VoxelLimits has no "reset" method, so we need
+    // to create a brand spanking new one each iteration
+    //
+    G4VoxelLimits *voxel = NewRandomVoxel( widths );
+
+    //
+    // Move it to random positions
+    //
+    G4int j;
+    for( j=0; j < 20; j++ ) {
+      G4ThreeVector offset = j > 0 ? GetRandomPoint() : G4ThreeVector(0,0,0);
+    
+      G4AffineTransform transform( offset );
+      
+      //
+      // Test aligned
+      //
+      if (TestOneVoxel( testVolume, *voxel, transform, inside, numInside, logger )) {
+        if (++nError >= maxErrors) break;
+      }
+
+      //
+      // Generate a couple random orientations
+      //
+      randomRotate1.rotateZ( G4UniformRand() );
+      transform.SetNetRotation( randomRotate1 );
+      
+      if (TestOneVoxel( testVolume, *voxel, transform, inside, numInside, logger )) {
+        if (++nError >= maxErrors) break;
+      }
+      
+      randomRotate2.rotateX( G4UniformRand() );
+      transform.SetNetRotation( randomRotate2 );
+      
+      if (TestOneVoxel( testVolume, *voxel, transform, inside, numInside, logger )) {
+        if (++nError >= maxErrors) break;
+      }
+      
+      randomRotate2.rotateY( G4UniformRand() );
+      transform.SetNetRotation( randomRotate2 );
+      
+      if (TestOneVoxel( testVolume, *voxel, transform, inside, numInside, logger )) {
+        if (++nError >= maxErrors) break;
+      }
+      
+      randomRotate2.rotateZ( G4UniformRand() );
+      transform.SetNetRotation( randomRotate2 );
+      
+      if (TestOneVoxel( testVolume, *voxel, transform, inside, numInside, logger )) {
+        if (++nError >= maxErrors) break;
+      }
+    }
+    delete voxel;
+
+    if (nError >= maxErrors) {
+      logger << "% End of test (maximum number errors) ";
+      break;
+    }
+    if (++nVoxel >= maxVoxels) {
+      logger << "% End of test (maximum number voxels) ";
+      break;
+    }
+  }
+  
+  now = time(0);
+  G4String dateTime2(ctime(&now));
+  logger << dateTime2;
+
+  logger << "% Statistics: voxels=" << nVoxel << " errors=" << nError << G4endl;
+         
+  logger << "%(End of file)" << G4endl;
+}
+
+
+//
+// TestOneVoxel
+//
+G4bool SBTvoxel::TestOneVoxel( const G4VSolid *testVolume, 
+             const G4VoxelLimits &voxel,
+             const G4AffineTransform &transform,
+             const G4ThreeVector inside[], const G4int numInside,
+             std::ostream &logger ) const
+{
+  static const EAxis axes[3] = { kXAxis, kYAxis, kZAxis };
+  G4int numError = 0;
+  G4double kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
+ 
+  //
+  // Get inverse transform
+  //
+  G4AffineTransform inverseTransform = transform.Inverse();
+  
+  //
+  // Loop over the points, collecting min/max for each axis
+  //
+  G4double pointMins[3] = {+kInfinity, +kInfinity, +kInfinity}, 
+     pointMaxs[3] = {-kInfinity, -kInfinity, -kInfinity};
+  G4int   numPointInside = 0;
+  
+  G4int i = numInside;
+  while( i-- > 0 ) {
+    G4ThreeVector point = transform.TransformPoint( inside[i] );
+    if (voxel.Inside(point)) {
+      numPointInside++;
+      
+      G4int j;
+      for (j=0; j<3; j++) {
+        G4double pv = point(axes[j]);
+        if (pv < pointMins[j]) pointMins[j] = pv;
+        if (pv > pointMaxs[j]) pointMaxs[j] = pv;
+      }
+    }
+  }
+
+  //
+  // Loop over axes
+  //
+  for( i=0; i<3; i++ ) {
+    G4double min, max;
+    
+    //
+    // Query the solid
+    //
+    if (testVolume->CalculateExtent( axes[i], voxel, transform, min, max )) {
+      //
+      // Compare min/max to the list of inside points
+      //
+      if (min > pointMins[i] || max < pointMaxs[i]) {
+        numError++;
+        logger << "ERROR: Voxel limits are incorrect, axis " << i << G4endl;
+        logger << "  reported limits were: " << min << " " << max << G4endl;
+        logger << "  but points were found at: " << pointMins[i] << " " << pointMaxs[i] << G4endl;
+      }
+      
+      //
+      // Min or max in reversee order?
+      //
+      if (min >= max) {
+        numError++;
+        logger << "ERROR: Voxel limits max <= min, axis " << i << G4endl;
+        logger << "  reported limits were: " << min << " " << max << G4endl;
+      }
+      
+      //
+      // Min or max outside limits?
+      //
+      // We give the solid an extra "kCarTolerance" space, since
+      // some solids like to add this value to their return values
+      //
+      
+      // logger << std::setw(20) << std::setprecision(20);
+      
+      if ( voxel.IsLimited(axes[i]) ) {
+        if (min < voxel.GetMinExtent(axes[i])-1.1*kCarTolerance) {
+          numError++;
+          logger << "ERROR: Voxel min is below pre-existing limit, axis " << i << G4endl;
+          logger << "  reported limits were: " << min << " " << max << G4endl;
+        }
+        if (max > voxel.GetMaxExtent(axes[i])+1.1*kCarTolerance) {
+          numError++;
+          logger << "ERROR: Voxel max is above pre-existing limit, axis " << i << G4endl;
+          logger << "  reported limits were: " << min << " " << max << G4endl;
+        }
+      }
+          
+      
+      if ( (!voxel.IsLimited(axes[i])) || max < voxel.GetMaxExtent(axes[i]) ) {
+        //
+        // Construct a set of points just outside the voxel limits
+        // and make sure they are outside
+        //
+        G4ThreeVector testPoints[9];
+        MakeVoxelTestPoints( voxel, axes[i], max, testPoints );
+        
+        G4ThreeVector *testPoint = testPoints;
+        do {
+          G4ThreeVector tp = inverseTransform.TransformPoint( *testPoint );
+          if (testVolume->Inside( tp ) == kInside) {
+            numError++;
+            logger << "ERROR: Voxel MAX limit is too small, axis " << i << G4endl;
+            logger << "  reported limits were: " << min << " " << max << G4endl;
+            logger << "  test point " << *testPoint << " [" << tp << "] was inside" << G4endl;
+            
+            MakeVoxelTestPoints( voxel, axes[i], max+10.0*kCarTolerance, testPoints );
+            tp = inverseTransform.TransformPoint( *testPoint );
+            if (testVolume->Inside( tp ) == kInside)
+              logger << "  and so was a more tolerant test point" << G4endl;
+            break;
+          }
+        } while( ++testPoint < testPoints+9 );
+      }
+      
+      if ( (!voxel.IsLimited(axes[i])) || min > voxel.GetMinExtent(axes[i]) ) {
+        G4ThreeVector testPoints[9];
+        MakeVoxelTestPoints( voxel, axes[i], min, testPoints );
+        
+        G4ThreeVector *testPoint = testPoints;
+        do {
+          G4ThreeVector tp = inverseTransform.TransformPoint( *testPoint );
+          if (testVolume->Inside( tp ) == kInside) {
+            numError++;
+            logger << "ERROR: Voxel MIN limit is too large, axis " << i << G4endl;
+            logger << "  reported limits were: " << min << " " << max << G4endl;
+            logger << "  test point " << *testPoint << " [" << tp << "] was inside" << G4endl;
+            
+            MakeVoxelTestPoints( voxel, axes[i], min-10.0*kCarTolerance, testPoints );
+            tp = inverseTransform.TransformPoint( *testPoint );
+            if (testVolume->Inside( tp ) == kInside)
+              logger << "  and so was a more tolerant test point" << G4endl;
+            break;
+          }
+        } while( ++testPoint < testPoints+9 );
+      }
+      
+    }
+    else {
+      //
+      // The voxel does not intersect the solid
+      // Make sure there are no inside points inside
+      //
+      if (numPointInside) {
+        numError++;
+        logger << "ERROR: Voxel isn't empty, axis " << i 
+               << ",  number points inside: " << numPointInside << " out of " << numInside << G4endl;
+        logger << "  they have limits of: " << pointMins[i] << " " << pointMaxs[i] << G4endl;
+      }
+    }
+  }
+  
+  if (numError) {
+    DumpVoxel( voxel, logger );
+    DumpTransform( transform, logger );
+    return true;
+  }
+  
+  return false;
+}
+
+
+//
+// DumpVoxel
+//
+void SBTvoxel::DumpVoxel( const G4VoxelLimits &voxel, std::ostream &logger ) const
+{
+  logger << "VOXEL =";
+  
+  static const EAxis axes[3] = { kXAxis, kYAxis, kZAxis };
+  
+  const EAxis *axis = axes;
+  do {
+    logger << " (";
+    if (voxel.IsLimited(*axis))
+      logger << voxel.GetMinExtent(*axis) << " "
+             << voxel.GetMaxExtent(*axis);
+    else
+      logger << "unlimited";
+    logger << ")";
+  } while( ++axis < axes+3 );
+  
+  logger << G4endl;
+}  
+
+
+//
+// DumpTransform
+//
+void SBTvoxel::DumpTransform( const G4AffineTransform &transform, std::ostream &logger ) const
+{
+  G4RotationMatrix rotate = transform.NetRotation();
+  
+    G4ThreeVector axis;
+  G4double      amount;
+  
+  rotate.getAngleAxis( amount, axis );
+  
+  logger << "TRANLATE = " << transform.NetTranslation() << G4endl;
+  logger << "ROTATE = " << axis << " " << amount << G4endl;
+}
+
+  
+
+//
+// GetInsidePoints
+//
+void SBTvoxel::GetInsidePoints( const G4VSolid *testVolume,
+        G4ThreeVector inside[], G4int *numInside,
+        const G4int numPoints,
+        const G4int maxAttempts ) const
+{
+  *numInside = 0;
+  
+  G4int i;
+  for( i=0; i<maxAttempts; i++ ) {
+    G4ThreeVector point = GetRandomPoint();
+    
+    if (testVolume->Inside( point ) == kInside) {
+      inside[*numInside] = point;
+      if (++(*numInside) == numPoints) return;
+    }
+  }
+}
+
+
+//
+// GetRandomPoint
+//
+// Return a random point in three dimensions using the current
+// specs 
+//
+G4ThreeVector SBTvoxel::GetRandomPoint() const {
+  G4double dx = widths.x()*GaussianRandom(10*m/widths.x()),
+     dy = widths.y()*GaussianRandom(10*m/widths.y()),
+     dz = widths.z()*GaussianRandom(10*m/widths.z());
+     
+     
+  G4ThreeVector randvec( dx, dy, dz );
+  
+  return target + randvec;
+}
+
+
+//
+// GaussianRandom
+//
+// Return Gaussian random number of unit width
+//
+// A classic, slow, but remarkably effective algorithm. Certainly good
+// enough for our purposes.
+//
+G4double SBTvoxel::GaussianRandom(const G4double cutoff) const {
+  if (cutoff <= 0) G4Exception( "Illegal cutoff" );
+
+  G4double answer;
+  do {
+    answer = -3.0;
+    for( G4int j = 0; j < 6; j++ ) answer += G4UniformRand();
+    answer *= std::sqrt(2.0);
+  } while( std::fabs(answer) > cutoff );
+  
+  return(answer);
+}
+
+
+//
+// GetRandomLimit
+//
+G4bool SBTvoxel::GetRandomLimit( G4double x[2], const G4double range ) const
+{
+  //
+  // Generate a random number
+  //
+  G4double rand = G4UniformRand();
+  
+  //
+  // Let's say that, well, 20% of the time we are
+  // not limited in this dimension
+  //
+  if (rand < 0.2) return false;
+  
+  //
+  // Otherwise, construct limits
+  //
+  x[0] = range*(rand - 0.6)/0.4;
+  x[1] = x[0] + range*G4UniformRand();
+  return true;
+}
+
+
+//
+// GetRandomVoxel
+//
+// Make a random voxel
+//
+G4VoxelLimits *SBTvoxel::NewRandomVoxel( const G4ThreeVector & // theWidths 
+           ) const
+{
+  G4double xlim[2];
+  
+  G4VoxelLimits *voxel = new G4VoxelLimits;
+  
+  if (GetRandomLimit(xlim,widths.x())) voxel->AddLimit( kXAxis, xlim[0], xlim[1] );
+  if (GetRandomLimit(xlim,widths.y())) voxel->AddLimit( kYAxis, xlim[0], xlim[1] );
+  if (GetRandomLimit(xlim,widths.z())) voxel->AddLimit( kZAxis, xlim[0], xlim[1] );
+
+  return voxel;
+}
+  
+
+//
+// MakeVoxelTestPoints
+//
+// Make a set of nine vectors that lay in a grid inside the
+// voxel at the specified location along the specified axis
+//
+void SBTvoxel::MakeVoxelTestPoints( const G4VoxelLimits &voxel,
+            const EAxis valueAxis, const G4double value,
+            G4ThreeVector testPoints[9] ) const
+{
+  G4ThreeVector grid[6], offset;
+
+  static const EAxis axes[3] = { kXAxis, kYAxis, kZAxis };
+  static const G4ThreeVector axisVectors[3] = {G4ThreeVector(1,0,0),
+                 G4ThreeVector(0,1,0),
+                 G4ThreeVector(0,0,1) };
+  
+  const EAxis *axis = axes;
+  G4ThreeVector *nextGrid = grid;
+  const G4ThreeVector *axisVector = axisVectors;
+  do {
+    if (*axis == valueAxis) {
+      offset = value*(*axisVector);
+    }
+    else if (voxel.IsLimited(*axis)) {
+      G4double min = voxel.GetMinExtent(*axis);
+      G4double max = voxel.GetMaxExtent(*axis);
+      
+      if (min <= -kInfinity) 
+        min = max - 10.0*m;
+      else if (max >= kInfinity)
+        max = min + 10.0*m;
+      
+      (*nextGrid++) = 0.5*(min+max)*(*axisVector);
+      (*nextGrid++) =           min*(*axisVector);
+      (*nextGrid++) =           max*(*axisVector);
+    }
+    else {
+      nextGrid++;    // zero vector
+      (*nextGrid++) = +10.0*m*(*axisVector);
+      (*nextGrid++) = -10.0*m*(*axisVector);
+    }
+  } while( ++axisVector, ++axis < axes+3 );
+  
+  testPoints[0] = offset + grid[0] + grid[3];
+  testPoints[1] = offset + grid[1] + grid[3];
+  testPoints[2] = offset + grid[2] + grid[3];
+  testPoints[3] = offset + grid[0] + grid[4];
+  testPoints[4] = offset + grid[1] + grid[4];
+  testPoints[5] = offset + grid[2] + grid[4];
+  testPoints[6] = offset + grid[0] + grid[5];
+  testPoints[7] = offset + grid[1] + grid[5];
+  testPoints[8] = offset + grid[2] + grid[5];
+}
Index: trunk/source/geometry/solids/test/SBT/src/SBTvoxelMessenger.cc
===================================================================
--- trunk/source/geometry/solids/test/SBT/src/SBTvoxelMessenger.cc	(revision 1316)
+++ trunk/source/geometry/solids/test/SBT/src/SBTvoxelMessenger.cc	(revision 1316)
@@ -0,0 +1,463 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+// SBTvoxelMessenger.cc
+//
+// Implementation of the messenger for the voxel test
+//
+
+#include "SBTvoxelMessenger.hh"
+#include "SBTvoxel.hh"
+#include "SBTVisManager.hh"
+#include "G4SolidQuery.hh"
+
+#include "G4VoxelLimits.hh"
+#include "G4AffineTransform.hh"
+
+#include "G4ios.hh"
+#include "G4UIdirectory.hh"
+#include "G4UIcommand.hh"
+#include "G4UIcmdWith3VectorAndUnit.hh"
+#include "G4UIcmdWithAnInteger.hh"
+#include "G4UIcmdWithAString.hh"
+#include "G4UIcmdWithoutParameter.hh"
+#include "G4UIcmdWith3Vector.hh"
+
+#include "G4UIcmdWithPargs.hh"
+#include "G4UIcmdPargDouble.hh"
+#include "G4UIcmdPargInteger.hh"
+
+#include <fstream>
+
+//
+// Constructor
+//
+SBTvoxelMessenger::SBTvoxelMessenger( const G4String prefix, 
+				      const G4SolidQuery *theSolidQuery, SBTVisManager *theVisManager )
+			: tester(), errorFile("sbtvoxel.log")
+{
+	//
+	// Initialize
+	//
+	visManager = theVisManager;
+	translate = new G4ThreeVector;
+	rotate = new G4RotationMatrix;
+	voxel = 0;
+	point = 0;
+	limits[0] = +1000.0;
+	limits[1] = -1000.0;
+	axis = kXAxis;
+	
+	//
+	// Store solid query
+	//
+	solidQuery = theSolidQuery;
+
+	//
+	// Declare directory
+	//
+	voxelDirectory = new G4UIdirectory( prefix );
+	voxelDirectory->SetGuidance( "Controls for CSG batch voxel tester" );
+	
+	//
+	// Target command
+	//
+	G4String com = prefix+"target";
+	targetCmd = new G4UIcmdWith3VectorAndUnit( com, this );
+	targetCmd->SetGuidance( "Center of distribution of random points" );
+	targetCmd->SetParameterName( "X", "Y", "Z", true, true );
+	
+	//
+	// Widths command
+	//
+	com = prefix+"widths";
+	widthsCmd = new G4UIcmdWith3VectorAndUnit( com, this );
+	widthsCmd->SetGuidance( "Widths of distribution of random points" );
+	widthsCmd->SetParameterName( "Dx", "Dy", "Dz", true, true );
+
+	//
+	// Max Voxels command
+	//
+	com = prefix+"maxVoxels";
+	maxVoxelsCmd = new G4UIcmdWithAnInteger( com, this );
+	maxVoxelsCmd->SetGuidance( "Maximum number of Voxels before test ends" );
+
+	//
+	// Max Errors command
+	//	
+	com = prefix+"maxErrors";
+	maxErrorsCmd = new G4UIcmdWithAnInteger( com, this );
+	maxErrorsCmd->SetGuidance( "Maximum number of errors before test ends" );
+	
+	//
+	// Error filename command
+	//
+	com = prefix+"errorFileName";
+	errorFileCmd = new G4UIcmdWithAString( com, this );
+	errorFileCmd->SetGuidance( "Filename in which to send error listings" );
+	
+	//
+	// Run command
+	//
+	com = prefix+"run";
+	runCmd = new G4UIcmdWithoutParameter( com, this );
+	runCmd->SetGuidance( "Execute voxel test" );
+	
+	//
+	// Picture directory
+	//
+	com = prefix+"picture/";
+	pictDirectory = new G4UIdirectory( com );
+	pictDirectory->SetGuidance( "Controls for drawing CSG voxel tests" );
+	
+	//
+	// picture/voxel command
+	//
+	pictVoxelArgs[0] = new G4UIcmdPargDouble( "xmin", 1.0, mm );
+	pictVoxelArgs[1] = new G4UIcmdPargDouble( "xmax", 1.0, mm );
+	pictVoxelArgs[2] = new G4UIcmdPargDouble( "ymin", 1.0, mm );
+	pictVoxelArgs[3] = new G4UIcmdPargDouble( "ymax", 1.0, mm );
+	pictVoxelArgs[4] = new G4UIcmdPargDouble( "zmin", 1.0, mm );
+	pictVoxelArgs[5] = new G4UIcmdPargDouble( "zmax", 1.0, mm );
+	com = prefix+"picture/voxel";
+	pictVoxelCmd = new G4UIcmdWithPargs( com, this, pictVoxelArgs, 6 );
+	pictVoxelCmd->SetGuidance( "Specifies the voxel to draw" );
+
+	//
+	// picture/translate command
+	//
+	com = prefix+"picture/translate";
+	pictTranCmd = new G4UIcmdWith3Vector( com, this );
+	pictTranCmd->SetGuidance( "Specifies the voxel translation" );
+	
+	//
+	// picture/rotate command
+	//
+	pictRotArgs[0] = new G4UIcmdPargDouble( "xaxis", 1.0, 1 );
+	pictRotArgs[1] = new G4UIcmdPargDouble( "yaxis", 1.0, 1 );
+	pictRotArgs[2] = new G4UIcmdPargDouble( "zaxis", 1.0, 1 );
+	pictRotArgs[3] = new G4UIcmdPargDouble( "amount", 1.0, 1 );
+	com = prefix+"picture/rotate";
+	pictRotCmd = new G4UIcmdWithPargs( com, this, pictRotArgs, 4 );
+	pictRotCmd->SetGuidance( "Specifies rotation matrix" );
+
+	//
+	// picture/point command
+	//
+	com = prefix+"picture/point";
+	pictPointCmd = new G4UIcmdWith3Vector( com, this );
+	pictPointCmd->SetGuidance( "Specifies one point to include in the picture" );
+	
+	//
+	// picture/limit command
+	//
+	pictLimitArgs[0] = new G4UIcmdPargInteger( "axis", 1 );
+	pictLimitArgs[1] = new G4UIcmdPargDouble( "min", 1.0, mm );
+	pictLimitArgs[2] = new G4UIcmdPargDouble( "max", 1.0, mm );
+	com = prefix+"picture/limit";
+	pictLimitCmd = new G4UIcmdWithPargs( com, this, pictLimitArgs, 3 );
+	pictLimitCmd->SetGuidance( "Specifies voxel limits" );
+	
+	//
+	// picture/draw command
+	//
+	com = prefix+"picture/draw";
+	pictDrawCmd = new G4UIcmdWithoutParameter( com, this );
+	pictDrawCmd->SetGuidance( "Draw the picture" );
+
+	//
+	// picture/debug command
+	//
+	com = prefix+"picture/debug";
+	pictDebugCmd = new G4UIcmdWithoutParameter( com, this );
+	pictDebugCmd->SetGuidance( "Call CalculateExtent for the picture" );
+}
+
+
+
+//
+// Destructor
+//
+SBTvoxelMessenger::~SBTvoxelMessenger()
+{
+	if (voxel) delete voxel;
+	if (point) delete point;
+
+//	delete targetCmd;
+//	delete widthsCmd;
+//	delete maxVoxelsCmd;
+//	delete maxVoxelsCmd;
+//	delete errorFileCmd;
+	delete voxelDirectory;
+	
+	delete pictDirectory;
+}
+	
+
+//
+// InvokeTest
+//
+// Run the test
+//
+void SBTvoxelMessenger::InvokeTest()
+{
+	//
+	// Is there a Solid to test?
+	//
+	G4VSolid *testSolid = solidQuery->GetSolid();
+	if (testSolid == 0) {
+		G4cerr << "Please initialize geometry before running test" << G4endl;
+		G4cerr << "Test ABORTED" << G4endl;
+		return;
+	}
+
+	//
+	// Open output file
+	//
+	std::ofstream logFile( errorFile );
+	
+	//
+	// Run the test
+	//
+	tester.RunTest( testSolid, logFile );
+}
+
+
+void SBTvoxelMessenger::Draw()
+{
+	if (!visManager) 
+		G4cerr << "Visualization is not available in this executable" << G4endl;
+
+	//
+	// Is there a Solid to test?
+	//
+	G4VSolid *testSolid = solidQuery->GetSolid();
+	if (testSolid == 0) {
+		G4cerr << "Please initialize geometry before running test" << G4endl;
+		return;
+	}
+	
+	//
+	// Is there a voxel to test?
+	//
+	if (voxel == 0) {
+		G4cerr << "Please specify a voxel to draw using /pict/voxel command" << G4endl;
+		return;
+	}
+
+	//
+	// Go do it
+	//
+	visManager->BuildFakeWorld();
+	
+	G4AffineTransform transform( *rotate, *translate );
+	
+	tester.Draw( testSolid, *voxel, transform, point, point ? 1 : 0, axis, limits, visManager );
+}
+
+
+void SBTvoxelMessenger::Debug()
+{
+	//
+	// Is there a Solid to test?
+	//
+	G4VSolid *testSolid = solidQuery->GetSolid();
+	if (testSolid == 0) {
+		G4cerr << "Please initialize geometry before running test" << G4endl;
+		return;
+	}
+	
+	//
+	// Is there a voxel to test?
+	//
+	if (voxel == 0) {
+		G4cerr << "Please specify a voxel to debug using /pict/voxel command" << G4endl;
+		return;
+	}
+
+	//
+	// Go do it
+	//
+	G4AffineTransform transform( *rotate, *translate );
+	
+	tester.Debug( testSolid, axis, *voxel, transform, point );
+}
+
+
+//
+// SetNewValue
+//
+// Call by the UI when user requests a change
+//
+void SBTvoxelMessenger::SetNewValue( G4UIcommand *command, G4String newValues )
+{
+	if (command == targetCmd) {
+		tester.SetTarget( targetCmd->GetNew3VectorValue( newValues ) );
+	}
+	else if (command == widthsCmd) {
+		tester.SetWidths( widthsCmd->GetNew3VectorValue( newValues ) );
+	}
+	else if (command == maxVoxelsCmd) {
+		tester.SetMaxVoxels( maxVoxelsCmd->GetNewIntValue( newValues ) );
+	}
+	else if (command == maxErrorsCmd) {
+		tester.SetMaxErrors( maxErrorsCmd->GetNewIntValue( newValues ) );
+	}
+	else if (command == errorFileCmd) {
+		errorFile = newValues;
+	}
+	else if (command == runCmd) {
+		InvokeTest();
+	}
+	else if (command == pictVoxelCmd) {
+		if (pictVoxelCmd->GetArguments( newValues )) {
+			G4UIcmdPargDouble *minX = (G4UIcmdPargDouble *)pictVoxelArgs[0],
+					  *maxX = (G4UIcmdPargDouble *)pictVoxelArgs[1],
+					  *minY = (G4UIcmdPargDouble *)pictVoxelArgs[2],
+					  *maxY = (G4UIcmdPargDouble *)pictVoxelArgs[3],
+					  *minZ = (G4UIcmdPargDouble *)pictVoxelArgs[4],
+					  *maxZ = (G4UIcmdPargDouble *)pictVoxelArgs[5];
+
+			if (voxel) delete voxel;
+
+			voxel = new G4VoxelLimits;
+
+			if (minX->GetValue() < maxX->GetValue())
+				voxel->AddLimit( kXAxis, minX->GetValue(), maxX->GetValue() );
+			if (minY->GetValue() < maxY->GetValue())
+				voxel->AddLimit( kYAxis, minY->GetValue(), maxY->GetValue() );
+			if (minZ->GetValue() < maxZ->GetValue())
+				voxel->AddLimit( kZAxis, minZ->GetValue(), maxZ->GetValue() );
+		}
+		else
+			G4cerr << "Syntax error" << G4endl;
+	}
+	else if (command == pictTranCmd) {
+		*translate = pictTranCmd->GetNew3VectorValue( newValues );
+	}
+	else if (command == pictRotCmd) {
+		if (pictRotCmd->GetArguments( newValues )) {
+			G4UIcmdPargDouble *rotX = (G4UIcmdPargDouble *)pictRotArgs[0],
+					  *rotY = (G4UIcmdPargDouble *)pictRotArgs[1],
+					  *rotZ = (G4UIcmdPargDouble *)pictRotArgs[2],
+					  *amount = (G4UIcmdPargDouble *)pictRotArgs[3];
+
+			G4ThreeVector rotAxis( rotX->GetValue(), rotY->GetValue(), rotZ->GetValue() );
+
+			delete rotate;
+			rotate = new G4RotationMatrix();
+			rotate->rotate( amount->GetValue(), &rotAxis );
+		}
+		else
+			G4cerr << "Syntax error" << G4endl;
+	}
+	else if (command == pictPointCmd) {
+		if (point) delete point;
+		point = new G4ThreeVector();
+		*point = pictPointCmd->GetNew3VectorValue( newValues );
+	}
+	else if (command == pictLimitCmd) {
+		if (pictLimitCmd->GetArguments( newValues )) {
+			static const EAxis axes[3] = { kXAxis, kYAxis, kZAxis };
+			
+			G4UIcmdPargInteger *axisArg = (G4UIcmdPargInteger *)pictLimitArgs[0];
+			G4UIcmdPargDouble     *min  = (G4UIcmdPargDouble  *)pictLimitArgs[1],
+					      *max  = (G4UIcmdPargDouble  *)pictLimitArgs[2];
+			
+			G4int axisIndex = axisArg->GetValue();	  
+			if (axisIndex < 0 || axisIndex > 2) {
+				G4cerr << "Axis value must be from 0 to 2" << G4endl;
+			}
+			else {
+				axis = axes[axisIndex];
+				limits[0] = min->GetValue();
+				limits[1] = max->GetValue();
+			}
+		}
+		else
+			G4cerr << "Syntax error" << G4endl;
+	}
+	else if (command == pictDrawCmd) {
+		Draw();
+	}
+	else if (command == pictDebugCmd) {
+		Debug();
+	}
+	else {
+		G4Exception( "Unrecognized command" );
+	}
+}
+
+	
+
+//
+// GetCurrentValue
+//
+G4String SBTvoxelMessenger::GetCurrentValue( G4UIcommand *command )
+{
+	if (command == targetCmd) {
+		return targetCmd->ConvertToString( tester.GetTarget(), "m" );
+	}
+	else if (command == widthsCmd) {
+		return widthsCmd->ConvertToString( tester.GetWidths(), "m" );
+	}
+	else if (command == maxVoxelsCmd) {
+		return maxVoxelsCmd->ConvertToString( tester.GetMaxVoxels() );
+	}
+	else if (command == maxErrorsCmd) {
+		return maxErrorsCmd->ConvertToString( tester.GetMaxErrors() );
+	}
+	else if (command == errorFileCmd) {
+		return errorFile;
+	}
+	else if (command == runCmd) {
+		return "";
+	}
+	else if (command == pictVoxelCmd) {
+		return "";
+	}
+	else if (command == pictTranCmd) {
+		return "";
+	}
+	else if (command == pictRotCmd) {
+		return "";
+	}
+	else if (command == pictPointCmd) {
+		return "";
+	}
+	else if (command == pictLimitCmd) {
+		return "";
+	}
+	else if (command == pictDebugCmd) {
+		return "";
+	}
+	else if (command == pictDrawCmd) {
+		return "";
+	}
+	
+	G4Exception( "Unrecognized command" );
+	return "foo!";
+}
