Commit in GeomConverter/src/org/lcsim/detector on MAIN
IDetectorConstruction.java+6added 1.1
IDetectorFactory.java+21added 1.1
IDetectorStore.java+12added 1.1
SimpleTestGeometry.java+87added 1.1
CoordinateTransformation3D.java+33-61.4 -> 1.5
DetectorElement.java+1-11.1 -> 1.2
ICoordinateTransformation3D.java+1-11.2 -> 1.3
IGeometryInfo.java+8-21.2 -> 1.3
ILogicalVolume.java-21.5 -> 1.6
IPhysicalVolumeNavigator.java+76-71.2 -> 1.3
IPhysicalVolumePath.java+1-11.2 -> 1.3
IPhysicalVolumeStore.java+1-11.1 -> 1.2
PhysicalVolumeNavigator.java+124-151.1 -> 1.2
PhysicalVolumeStore.java+8-11.1 -> 1.2
DetectorTestUtil.java-701.2 removed
material/IMaterialMixture.java+5added 1.1
        /MaterialMixture.java+386added 1.1
        /IMaterial.java+25-91.1 -> 1.2
        /MaterialElement.java+61-141.1 -> 1.2
solids/Tube.java+11-21.2 -> 1.3
+867-132
6 added + 1 removed + 13 modified, total 20 files
JM: Snapshot.  PhysicalVolumeNavigator is working now.

GeomConverter/src/org/lcsim/detector
IDetectorConstruction.java added at 1.1
diff -N IDetectorConstruction.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IDetectorConstruction.java	3 Mar 2007 13:33:56 -0000	1.1
@@ -0,0 +1,6 @@
+package org.lcsim.detector;
+
+public interface IDetectorConstruction 
+{
+	public IPhysicalVolume create();
+}
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
IDetectorFactory.java added at 1.1
diff -N IDetectorFactory.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IDetectorFactory.java	3 Mar 2007 13:33:56 -0000	1.1
@@ -0,0 +1,21 @@
+package org.lcsim.detector;
+
+import org.lcsim.detector.material.IMaterial;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.solids.ISolid;
+import org.lcsim.detector.solids.ITube;
+
+public interface IDetectorFactory 
+{
+	ILogicalVolume createLogicalVolume(String name, ISolid solid, IMaterial material);
+	IPhysicalVolume createPhysicalVolume();
+	IPhysicalVolumeNavigator createPhysicalVolumeNavigator();
+	IRotation3D createRotation3D();
+	ICoordinateTransformation3D createTransform3D();
+	
+	IMaterial createMaterialElement();
+	IMaterial createMaterialMixture();
+	
+	Box createBox();
+	ITube createTube();
+}

GeomConverter/src/org/lcsim/detector
IDetectorStore.java added at 1.1
diff -N IDetectorStore.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IDetectorStore.java	3 Mar 2007 13:33:56 -0000	1.1
@@ -0,0 +1,12 @@
+package org.lcsim.detector;
+
+import org.lcsim.detector.material.IMaterialStore;
+import org.lcsim.detector.solids.ISolidStore;
+
+public interface IDetectorStore 
+{
+	IPhysicalVolumeStore getPhysicalVolumeStore();
+	ILogicalVolumeStore getLogicalVolumeStore();
+	ISolidStore getSolidStore();
+	IMaterialStore getMaterialStore();
+}
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
SimpleTestGeometry.java added at 1.1
diff -N SimpleTestGeometry.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SimpleTestGeometry.java	3 Mar 2007 13:33:56 -0000	1.1
@@ -0,0 +1,87 @@
+package org.lcsim.detector;
+
+import static org.lcsim.units.clhep.SystemOfUnits.cm;
+import static org.lcsim.units.clhep.SystemOfUnits.m;
+import hep.physics.vec.BasicHep3Vector;
+
+import org.lcsim.detector.material.IMaterial;
+import org.lcsim.detector.material.MaterialElement;
+import org.lcsim.detector.solids.Box;
+
+/**
+ * Makes simplistic detector geometry for testing the detector package.
+ * 
+ * @author jeremym
+ *
+ */
+public class SimpleTestGeometry 
+{
+	private static IMaterial dummymat = new MaterialElement("dummymat",1,1,1.0);
+	
+	public static IPhysicalVolume createTestGeometry()
+	{
+		IPhysicalVolume world = createWorld();
+		createTestGeometryBoxes(world);
+		return world;
+	}
+	
+	public static final void createTestGeometryBoxes(IPhysicalVolume mom)
+	{
+		// A 1 x 1 m box in the world.
+		Box box = new Box("test_box",1.0*m,1.0*m,1.0*m);
+		LogicalVolume lvTest = new LogicalVolume("lvTest",box,dummymat);
+		new PhysicalVolume(
+				new CoordinateTransformation3D(),
+				"test",
+				lvTest,
+				mom.getLogicalVolume(),
+				1);
+	
+		// Box daughter volume inside mother at x = +20 cm.
+		Box box2 = new Box("test_box2",10.0*cm,10.0*cm,10.0*cm);
+		LogicalVolume lvTest2 = new LogicalVolume("lvTest2",box2,dummymat);
+		// Box is displayed 5.0 mm in X.
+		new PhysicalVolume(
+				new CoordinateTransformation3D(new BasicHep3Vector(5.0,0,0)),
+				"test2",
+				lvTest2,
+				lvTest,
+				1);
+
+		// Another box in the big one at x = -20 cm.
+		//Box box3 = new Box("test_box3",10.0*cm,10.0*cm,10.0*cm);
+		//LogicalVolume lvTest3 = new LogicalVolume("lvTest3",box3,dummymat);
+		//new PhysicalVolume(
+		//		new CoordinateTransformation3D(
+		//				new BasicHep3Vector(-20.0*cm,0.0,0.0)),
+		//		"test3",
+		//		lvTest3,
+		//		lvTest,
+		//		2);		
+	}
+	
+	public static final IPhysicalVolume createWorld()
+	{		
+		Box boxWorld = new Box(
+				"world_box",
+				10.0*m,
+				10.0*m,
+				10.0*m);
+		
+		LogicalVolume lvWorld = 
+			new LogicalVolume(
+					"world",
+					boxWorld,
+					dummymat);
+		
+		IPhysicalVolume pvTop = 
+			new PhysicalVolume(
+					null,
+					"world",
+					lvWorld,
+					null,
+					0);
+		
+		return pvTop;
+	}
+}
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
CoordinateTransformation3D.java 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- CoordinateTransformation3D.java	28 Feb 2007 21:37:28 -0000	1.4
+++ CoordinateTransformation3D.java	3 Mar 2007 13:33:56 -0000	1.5
@@ -4,15 +4,20 @@
 
 package org.lcsim.detector;
 
-import hep.physics.vec.Hep3Vector;
 import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
 import hep.physics.vec.VecOp;
 
 /**
+ * A class for representing a 3D coordinate transformation
+ * using a @see Rotation3D for the rotation and a
+ * @see hep.physics.vec.Hep3Vector for the translation.
  *
- * @author tknelson
+ * @author Tim Nelson <[log in to unmask]>
+ * @author Jeremy McCormick <[log in to unmask]>
  */
-public class CoordinateTransformation3D implements ICoordinateTransformation3D
+public class CoordinateTransformation3D 
+implements ICoordinateTransformation3D
 {
     
     // Fields
@@ -21,10 +26,10 @@
             
     /**
      * Creates a new instance of CoordinateTransformation3D
+     * with the identity matrix.
      */
     public CoordinateTransformation3D()
-    {
-    }
+    {}
     
     public CoordinateTransformation3D(Rotation3D rotation)
     {
@@ -135,4 +140,26 @@
                 VecOp.mult(transformation.getRotation().inverse().getRotationMatrix(),_translation),
                 transformation.getTranslation());
     }
-}
+    
+    public String toString()
+    {
+    	return _translation.toString() + '\n' + _rotation.toString();
+    }
+    
+    public static CoordinateTransformation3D copy(ICoordinateTransformation3D ci)
+    {
+    	CoordinateTransformation3D c = (CoordinateTransformation3D)ci; 
+    	try { return (CoordinateTransformation3D)c.clone(); } catch (Throwable x) {}
+    	return null;
+    }
+    
+    public static CoordinateTransformation3D copy(CoordinateTransformation3D c)
+    {
+    	try {
+    		return (CoordinateTransformation3D)c.clone();
+    	}
+    	catch (Exception x)
+    	{}
+    	return null;
+    }
+}
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
DetectorElement.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- DetectorElement.java	28 Feb 2007 21:52:00 -0000	1.1
+++ DetectorElement.java	3 Mar 2007 13:33:56 -0000	1.2
@@ -54,4 +54,4 @@
 	{
 		return id;
 	}
-}
+}
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
ICoordinateTransformation3D.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- ICoordinateTransformation3D.java	28 Feb 2007 21:37:28 -0000	1.2
+++ ICoordinateTransformation3D.java	3 Mar 2007 13:33:56 -0000	1.3
@@ -12,7 +12,6 @@
  */
 public interface ICoordinateTransformation3D
 {       
-    // Access to translation and rotation
     public Hep3Vector getTranslation();
     public Rotation3D getRotation();
     
@@ -29,4 +28,5 @@
     public void multiplyBy(ICoordinateTransformation3D trans);
     
     public void invert();
+    public CoordinateTransformation3D inverse();
 }
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
IGeometryInfo.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- IGeometryInfo.java	2 Mar 2007 02:28:23 -0000	1.2
+++ IGeometryInfo.java	3 Mar 2007 13:33:56 -0000	1.3
@@ -13,11 +13,17 @@
  * @author Jeremy McCormick <[log in to unmask]>
  */
 public interface IGeometryInfo
-{    
+{  	
     public ILogicalVolume getLogicalVolume();
     
     public String getLogicalVolumeName();
-	
+
+	public IPhysicalVolumePath getSupport();
+    
+    public boolean hasSupport();
+    
+    public void setSupport(IPhysicalVolumePath support);
+
     public boolean hasLogicalVolume();
     
     // global to local transformation

GeomConverter/src/org/lcsim/detector
ILogicalVolume.java 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- ILogicalVolume.java	3 Mar 2007 02:24:51 -0000	1.5
+++ ILogicalVolume.java	3 Mar 2007 13:33:56 -0000	1.6
@@ -10,8 +10,6 @@
  * but does not include regions, sensitive detectors, or the magnetic
  * field.
  * 
- * {@link }
- * 
  * @author Jeremy McCormick <[log in to unmask]>
  *
  */

GeomConverter/src/org/lcsim/detector
IPhysicalVolumeNavigator.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- IPhysicalVolumeNavigator.java	3 Mar 2007 02:24:51 -0000	1.2
+++ IPhysicalVolumeNavigator.java	3 Mar 2007 13:33:56 -0000	1.3
@@ -1,14 +1,83 @@
 package org.lcsim.detector;
 
+import hep.physics.vec.Hep3Vector;
+
+/**
+ * This interface provides utilities for
+ * returning IPhysicalVolumePath objects
+ * that represent a volume's unique
+ * position in the physical geometry tree.
+ * It can also calculate the combined geometric
+ * transform of an IPhysicalVolumePath.
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @version $Id: IPhysicalVolumeNavigator.java,v 1.3 2007/03/03 13:33:56 jeremy Exp $
+ */
 public interface IPhysicalVolumeNavigator 
 {
+	/**
+	 * Get the top physical volume assigned to
+	 * this navigator.
+	 * 
+	 * @return
+	 */
 	public IPhysicalVolume getTopPhysicalVolume();
+	
+	/**
+	 * Set the top physical volume assigned to 
+	 * this navigator.
+	 * 
+	 * @param physvol
+	 */
 	public void setTopPhysicalVolume(IPhysicalVolume physvol);
-	public IPhysicalVolumePath getPath(String path);
-	//public IPhysicalVolumePath getPath(IPhysicalVolume physvol);
-	//public IPhysicalVolumePath getPath(String[] path);
-	//public IPhysicalVolumePath getPath(int[] copyNums);
-	//public ICoordinateTransformation3D getTransformation(IPhysicalVolume physvol);
-	//public ICoordinateTransformation3D getInverseTransformation(IPhysicalVolume physvol);
-	//public IPhysicalVolume getPhysicalVolume(Hep3Vector globalPoint);
+	
+	/**
+	 * 
+	 * Get the full stack of PhysicalVolumes from a path string
+	 * of PhysicalVolume names.
+	 * 
+	 * "/name1/name2/[...]"
+	 * 
+	 * @param path
+	 * @return
+	 */
+	public IPhysicalVolumePath getPath(String path);	
+
+	/**
+	 * 
+	 * Get the full transformation from the origin of
+	 * the coordinate system to the given path.
+	 * 
+	 * @param path
+	 * @return
+	 */
+	CoordinateTransformation3D getTransform(String path);
+	
+	/**
+	 * Get the full transformation from the origin of
+	 * the coordinate system from a stack of physical volumes.
+	 * 
+	 * @param path
+	 * @return
+	 */
+	CoordinateTransformation3D getTransform(IPhysicalVolumePath path);
+
+	/**
+	 * Given a global point, return the full path to
+	 * deepest volume containing this point, not past depth
+	 * of @param level.
+	 * 
+	 * @param point A point in the global coordinate system.
+	 * @param level Max depth.  -1 will go to bottom.
+	 * @return
+	 */
+	IPhysicalVolumePath getPath(Hep3Vector globalPoint, int level);
+	
+	/**
+	 * Same as above with no depth arg.
+	 * 
+	 * @param globalPoint
+	 * @return
+	 */
+	IPhysicalVolumePath getPath(Hep3Vector globalPoint);
 }
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
IPhysicalVolumePath.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- IPhysicalVolumePath.java	2 Mar 2007 02:28:23 -0000	1.2
+++ IPhysicalVolumePath.java	3 Mar 2007 13:33:56 -0000	1.3
@@ -4,4 +4,4 @@
 
 public interface IPhysicalVolumePath 
 extends List<IPhysicalVolume> 
-{}
+{}
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
IPhysicalVolumeStore.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- IPhysicalVolumeStore.java	2 Mar 2007 02:28:23 -0000	1.1
+++ IPhysicalVolumeStore.java	3 Mar 2007 13:33:56 -0000	1.2
@@ -1,5 +1,5 @@
 package org.lcsim.detector;
 
 public interface IPhysicalVolumeStore 
-extends IObjectStore<IPhysicalVolume>
+extends IPhysicalVolumeContainer
 {}

GeomConverter/src/org/lcsim/detector
PhysicalVolumeNavigator.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- PhysicalVolumeNavigator.java	3 Mar 2007 02:24:51 -0000	1.1
+++ PhysicalVolumeNavigator.java	3 Mar 2007 13:33:56 -0000	1.2
@@ -1,40 +1,133 @@
 package org.lcsim.detector;
 
+import hep.physics.vec.Hep3Vector;
+
 public class PhysicalVolumeNavigator 
 implements IPhysicalVolumeNavigator
 {
-	private IPhysicalVolume pvTop;
+	public IPhysicalVolumePath getPath(Hep3Vector globalPoint, int level) 
+	{
+		IPhysicalVolumePath path = new PhysicalVolumePath();
+		IPhysicalVolume pvWorld = getTopPhysicalVolume();
+		ILogicalVolume lvCurr = pvWorld.getLogicalVolume();
 
-	public PhysicalVolumeNavigator(IPhysicalVolume pvTop)
+		// First time, this compares in world.
+		if (lvCurr.getSolid().isInside(globalPoint))
+		{
+			path.add(pvWorld);
+		}		
+		else {
+			// The point is outside the world!	
+			System.err.println("!!! Point " + globalPoint.v() + " is outside the top volume <"+pvWorld.getName()+">. !!!");
+			
+			// Return an empty path.
+			return path;
+		}
+
+		// Current depth.
+		int depth=0;
+
+		// Go into the geometry tree as long as
+		// there are daughter volumes.
+		while(lvCurr.getNumberOfDaughters() != 0)
+		{					
+			boolean inDau=false;
+			
+			// Loop over the daughters.
+			for (IPhysicalVolume dau : lvCurr.getDaughters())
+			{													
+				// Multiply the daughter by the combined
+				// transform up to this point to get the
+				// combined global to local transform.				
+				// !!! WRONG ... NEEDS TO BE FIXED !!!
+				CoordinateTransformation3D combinedTransform
+					= CoordinateTransformation3D.multiply(
+							getTransform(path),
+							(CoordinateTransformation3D)
+							dau.getTransform());
+
+				// Check if the global point is inside the volume's solid.
+				// !!! WRONG ... NEEDS TO BE FIXED !!!
+				if (dau.getLogicalVolume().getSolid().isInside(
+						dau.getTransform().transformed(globalPoint))) 
+				{
+					inDau=true;
+					
+					// Add this daughter to the path.
+					path.add(dau);
+
+					// Go to next logical volume.
+					lvCurr = dau.getLogicalVolume();
+
+					// Increment the depth.
+					++depth;
+					
+					// Stop looking at daughters once
+					// one has been found to contain
+					// the point.
+					break;
+				}								
+			}
+
+			// If depth is past selected level, 
+			// stop looking in sub-volumes and quit.
+			if ( level != -1 && depth > level || !inDau)
+			{
+				break;
+			}			
+		}
+
+		return path;
+	}
+
+	public IPhysicalVolumePath getPath(Hep3Vector globalPoint) 
 	{
-		if ( pvTop == null )
+		return getPath(globalPoint,-1);
+	}
+
+	public CoordinateTransformation3D getTransform(String path) 
+	{
+		return getTransform(getPath(path));
+	}
+
+	public CoordinateTransformation3D getTransform(IPhysicalVolumePath path) 
+	{
+		CoordinateTransformation3D theTransform = new CoordinateTransformation3D();
+		for (IPhysicalVolume physvol : path)
 		{
-			throw new IllegalArgumentException("PhysicalVolumeNavigator cannot be setup with a null PhysicalVolume!");
+			theTransform.multiplyBy(physvol.getTransform());
 		}
-		setTopPhysicalVolume(pvTop);
+		return theTransform;
 	}
-	
-	private String[] splitPath(String path)
+
+	private static String[] splitPath(String path)
 	{
 		// Eat the first slash.
-		if (path.charAt(0) == '/')
+		if (path.startsWith("/"))
 		{
 			path = path.substring(1);
 		}
 		
+		// Eat the last slash.
+		if (path.endsWith("/"))
+		{
+			path = path.substring(0,(path.length()-2));
+		}
+		
+		//System.out.println("path after eating slashes: "+path);
+
 		// Split on remaining slashes.
 		return path.split("/");
-	}
+	}	
 	
-	public IPhysicalVolumePath getPath(String path) 
-	{		
-		String[] names = splitPath(path);
+	public IPhysicalVolumePath getPath(String[] path)
+	{
 		IPhysicalVolumePath physvols = new PhysicalVolumePath();
 		IPhysicalVolume pv = getTopPhysicalVolume();
-		for (String name : names)
+		for (String name : path)
 		{
 			//System.out.println("looking for physvol = " + name);
-				
+
 			PhysicalVolumeContainer pvSearch = 
 				pv.getLogicalVolume().getDaughters().findByName(name);			
 			if (pvSearch.size() > 1)
@@ -55,6 +148,11 @@
 		return physvols;
 	}
 
+	public IPhysicalVolumePath getPath(String path) 
+	{		
+		return getPath(splitPath(path));
+	}
+
 	public IPhysicalVolume getTopPhysicalVolume() 
 	{
 		return pvTop;
@@ -64,4 +162,15 @@
 	{
 		pvTop = physvol;		
 	}
-}
+	
+	private IPhysicalVolume pvTop;
+
+	public PhysicalVolumeNavigator(IPhysicalVolume pvTop)
+	{
+		if ( pvTop == null )
+		{
+			throw new IllegalArgumentException("!!! PhysicalVolumeNavigator cannot be setup with a null PhysicalVolume !!!");
+		}
+		setTopPhysicalVolume(pvTop);
+	}	
+}
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
PhysicalVolumeStore.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- PhysicalVolumeStore.java	2 Mar 2007 02:28:23 -0000	1.1
+++ PhysicalVolumeStore.java	3 Mar 2007 13:33:56 -0000	1.2
@@ -1,7 +1,7 @@
 package org.lcsim.detector;
 
 public class PhysicalVolumeStore 
-extends ObjectStore<IPhysicalVolume>
+extends PhysicalVolumeContainer
 implements IPhysicalVolumeStore
 {
 	private static IPhysicalVolumeStore store;
@@ -13,4 +13,11 @@
 		}
 		return store;
 	}
+	public PhysicalVolumeStore()
+	{
+		// Disallow duplicate physical volumes to be 
+		// added but globally non-unique name and
+		// copyNum is okay.
+		super(true,false,false);
+	}
 }
\ No newline at end of file

GeomConverter/src/org/lcsim/detector
DetectorTestUtil.java removed after 1.2
diff -N DetectorTestUtil.java
--- DetectorTestUtil.java	3 Mar 2007 02:24:51 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,70 +0,0 @@
-package org.lcsim.detector;
-
-import static org.lcsim.units.clhep.SystemOfUnits.cm;
-import static org.lcsim.units.clhep.SystemOfUnits.m;
-import hep.physics.vec.BasicHep3Vector;
-
-import org.lcsim.detector.material.IMaterial;
-import org.lcsim.detector.material.MaterialElement;
-import org.lcsim.detector.solids.Box;
-
-public class DetectorTestUtil 
-{
-	private static IMaterial dummymat = new MaterialElement("dummymat",1,1,1.0);
-	
-	public static IPhysicalVolume createTestSetup()
-	{
-		IPhysicalVolume world = createWorld();
-		createTestDetector(world);
-		return world;
-	}
-	
-	public static final void createTestDetector(IPhysicalVolume mom)
-	{
-		// Simple box.
-		Box box = new Box("test_box",1.0*m,1.0*m,1.0*m);
-		LogicalVolume lvTest = new LogicalVolume("lvTest",box,dummymat);
-		new PhysicalVolume(
-				new CoordinateTransformation3D(),
-				"test",
-				lvTest,
-				mom.getLogicalVolume(),
-				1);
-		
-		// Box daughter volume.
-		Box box2 = new Box("test_box2",10.0*cm,10.0*cm,10.0*cm);
-		LogicalVolume lvTest2 = new LogicalVolume("lvTest2",box2,dummymat);
-		new PhysicalVolume(
-				new CoordinateTransformation3D(
-						new BasicHep3Vector(1.0,0.0,0.0)),
-				"test2",
-				lvTest2,
-				lvTest,
-				1);
-	}
-	
-	public static final IPhysicalVolume createWorld()
-	{		
-		Box boxWorld = new Box(
-				"world_box",
-				10.0*m,
-				10.0*m,
-				10.0*m);
-		
-		LogicalVolume lvWorld = 
-			new LogicalVolume(
-					"world",
-					boxWorld,
-					dummymat);
-		
-		IPhysicalVolume pvTop = 
-			new PhysicalVolume(
-					null,
-					"world",
-					lvWorld,
-					null,
-					0);
-		
-		return pvTop;
-	}
-}
\ No newline at end of file

GeomConverter/src/org/lcsim/detector/material
IMaterialMixture.java added at 1.1
diff -N IMaterialMixture.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IMaterialMixture.java	3 Mar 2007 13:33:57 -0000	1.1
@@ -0,0 +1,5 @@
+package org.lcsim.detector.material;
+
+public interface IMaterialMixture 
+extends IMaterial
+{}

GeomConverter/src/org/lcsim/detector/material
MaterialMixture.java added at 1.1
diff -N MaterialMixture.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ MaterialMixture.java	3 Mar 2007 13:33:57 -0000	1.1
@@ -0,0 +1,386 @@
+package org.lcsim.detector.material;
+
+import static java.lang.Math.abs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Material mixture is a composition of MaterialElements
+ * by mass fraction or atom count. 
+ * 
+ * @author Jeremy McCormick <[log in to unmask]>
+ *
+ */
+public class MaterialMixture 
+extends MaterialElement
+{    
+    // Max radiation length.
+    public static final double MAX_RADIATION_LENGTH = java.lang.Double.MAX_VALUE;
+    
+    // Max interaction length.
+    public static final double MAX_NUCLEAR_INTERACTION_LENGTH = java.lang.Double.MAX_VALUE;
+         
+    // Corresponds to single MaterialElement? 
+    boolean isElement;
+    
+    // Effective, computed Z value.
+    public double Zeff;
+    
+    // Effective, computed A value.
+    public double Aeff;
+    
+    // Number of components added.
+    int nComponentsAdded;
+    
+    // Number of components that are allowed to be added.
+    int nComponentsMax;
+    
+    // Number of elements in the mass fraction list.
+    int nElements;
+    
+    // The list of elements making up the mixture.
+    private List<MaterialElement> elementList = new ArrayList<MaterialElement>();
+    
+    // List of mass fractions.
+    private List<Double> massFractionList = new ArrayList<Double>();
+    
+    // Number of atoms of each element.
+    private List<Integer> atomCountList = new ArrayList<Integer>();      
+    
+    /** Construct a material with a number of components. */
+    public MaterialMixture(String name,
+            int nComponents,
+            double density,
+            State state,
+            double temp,
+            double pressure)
+    {
+    	super(name,0,0,density,0.0,state,temp,pressure,0,0);
+        
+        if ( nComponents <= 0 )
+        {
+            throw new IllegalArgumentException("nComponents must be >= 0.");
+        }
+        
+        nComponentsMax = nComponents;
+        nComponentsAdded = nElements = 0;
+        isElement = false;
+    }
+
+    public double getZ()
+    {
+    	return Zeff;
+    }
+
+    public double getA()
+    {
+    	return Aeff;
+    }                
+            
+    /** @return maximum number of 1st-level (non-recursive) components that can be defined */
+    public int getNComponentsMax()
+    {
+        return nComponentsMax;
+    }
+    
+    /** @return number of components defined so far in this material */
+    public int getNComponents()
+    {
+        return nComponentsAdded;
+    }
+    
+    /** @return number of elements defined in this material */
+    public int getNElements()
+    {
+        return nElements;
+    }
+    
+    /** @return lambda (nuclear interaction length) based on mass fractions of elements */
+    private double computeNuclearInteractionLengthForMixture()
+    {
+        double NILinv = 0.0;
+        
+        for (int i = 0; i < nElements; i++)
+        {
+            MaterialElement me = elementList.get(i);
+            NILinv += massFractionList.get(i) / me.getNuclearInteractionLength();
+        }
+        
+        nuclearInteractionLength = (NILinv <= 0.0 ? MAX_NUCLEAR_INTERACTION_LENGTH : 1.0/NILinv);
+        nuclearInteractionLengthWithDensity = nuclearInteractionLength / getDensity();
+        
+        return NILinv;
+    }
+    
+    /** compute X0 (radiation length) based on mass fractions of elements */
+    private double computeRadiationLengthForMixture()
+    {
+        double rlinv = 0.0;
+        
+        for (int i = 0; i < nElements; i++)
+        {
+            MaterialElement me = elementList.get(i);
+            rlinv += massFractionList.get(i) / me.getRadiationLength();
+        }
+        
+        radiationLength = (rlinv <= 0.0 ? MAX_RADIATION_LENGTH : 1.0/rlinv);
+        
+        return radiationLength;
+    }
+    
+    /** Caches computed quantities after all components have been added to the material. */
+    private void computeDerivedQuantities()
+    {
+
+        computeZeff();
+        computeAeff();
+        computeRadiationLengthForMixture();
+        computeNuclearInteractionLengthForMixture();
+		computeCriticalEnergy();
+		computeMoliereRadius();
+    	computeEffectiveNumberOfNucleons();
+		computeMolecularWeigth();    
+    }    
+    
+    /** @return total number of (unique) elements in the element list for this material */
+    public int getNumberOfElements()
+    {
+        return nElements;
+    }
+    
+    /** @return a list of elements referenced by this material */
+    public List<MaterialElement> getElements()
+    {
+        return elementList;
+    }
+    
+    /** @return corresponding mass fractions for each element in the material */
+    public List<Double> getMassFractions()
+    {
+        return massFractionList;
+    }
+    
+    /**
+     * Add an element to the material by atom count.
+     *
+     * Based on Geant4's G4Material::AddElement() .
+     */
+    public void addElement(MaterialElement element,
+            int nAtoms)
+    {
+        if ( nElements < nComponentsMax )
+        {
+            elementList.add(element);
+            atomCountList.add( nElements, nAtoms);
+            nComponentsAdded = ++nElements;
+        }
+        else
+        {
+            throw new RuntimeException("Attempting to add more than declared number of elements for this material: " + getName());
+        }
+        
+        if ( isFilled() )
+        {
+            //double Zmol = 0;
+            double Amol = 0;
+            
+            int atomCnt = 0;
+            for ( MaterialElement e : elementList )
+            {
+                Amol += atomCountList.get(atomCnt) * e.getA();
+                ++atomCnt;
+            }
+            
+            int massCnt = 0;
+            for ( MaterialElement ee : elementList )
+            {
+                massFractionList.add(atomCountList.get(massCnt) * ee.getA() / Amol);
+                ++massCnt;
+            }
+            
+            computeDerivedQuantities();
+        }
+    }
+    
+    /**
+     * Add element to the material by fraction of mass. (out of 1.0)
+     */
+    public void addElement(MaterialElement element,
+            double fraction)
+    {
+        if ( nComponentsAdded < nComponentsMax )
+        {
+            int elCnt = 0;
+            while (( elCnt < nElements ) && element != elementList.get(elCnt)) elCnt++;
+            
+            /* Element already exists.  Increase the mass fraction. */
+            if (elCnt < nElements)
+            {
+                double currFrac = massFractionList.get(elCnt);
+                currFrac += fraction;
+                massFractionList.add(elCnt, currFrac);
+            }
+            /* Element does not exist.  Add a new mass fraction. */
+            else
+            {
+                elementList.add(element);
+                massFractionList.add(elCnt, fraction);
+                ++nElements;
+            }
+            ++nComponentsAdded;
+        }
+        else
+        {
+            throw new RuntimeException("Attempting to add more than declared number of components to material: " + getName() );
+        }
+        
+        if ( isFilled() )
+        {
+            checkMassSum();
+            computeDerivedQuantities();
+        }
+    }
+    
+    /** Add material by fraction of mass. */
+    public void addMaterial(
+    		MaterialMixture material,
+            double fraction)
+    {                
+        if ( atomCountList.size() > 0 )
+        {
+            throw new RuntimeException("Material is already defined by atoms: " + getName());
+        }
+        
+        if ( nComponentsAdded < nComponentsMax )
+        {
+            /* Loop over elements in the material. */
+            for ( int i = 0; i < material.getNumberOfElements(); i++)
+            {
+                MaterialElement element = material.getElements().get(i);
+                int elCnt = 0;
+                /* Find the element. */
+                while ((elCnt < nElements) && (element != elementList.get(elCnt)))
+                {
+                    ++elCnt;
+                }
+                
+                /* Add fraction to existing element. */
+                if ( elCnt < nElements )
+                {
+                    double currFrac = massFractionList.get(elCnt);
+                    currFrac += fraction * material.getMassFractions().get(i) ;
+                    massFractionList.set(elCnt, currFrac);
+                }
+                /* Add a new element. */
+                else
+                {
+                    //System.out.println("adding mass fraction: " + element.getName() + "=" + fraction * material.getMassFractions().get(i) );
+                    
+                    elementList.add(element);
+                    
+                    /**
+                     * Add the mass fraction of this element, scaled by its percentage in the material's
+                     * mass fraction list.
+                     */
+                    massFractionList.add(elCnt, fraction * material.getMassFractions().get(i));
+                    ++nElements;
+                }
+            }
+            ++nComponentsAdded;
+        }
+        else
+        {
+            throw new RuntimeException("Attempting to add more than declared number of components for material: " + getName() );
+        }
+        
+        if ( isFilled() )
+        {
+            checkMassSum();
+            computeDerivedQuantities();
+        }
+    }
+    
+    /** @return true if all 1st-level (non-recursive) component elements and materials have been added */
+    public boolean isFilled()
+    {
+        return (nComponentsAdded == nComponentsMax);
+    }
+    
+    /** Check that the massFractions list adds up to 1.0 */
+    private void checkMassSum()
+    {
+        double weightSum = 0;
+        for ( int i = 0; i < massFractionList.size(); i++)
+        {
+            weightSum += massFractionList.get(i);
+        }
+        
+        if ( abs(1 - weightSum) > 0.001 )
+        {
+            throw new RuntimeException("Mass fractions do not sum to 1 within 0.001 tolerance for this material: " + getName() );
+        }
+    }
+    
+    /** Compute effective Z for this material using element list. */
+    private double computeZeff()
+    {
+        double ZsumNotNorm = 0;
+        double atomCntFracSum = 0;
+        
+        int nelem = this.getNElements();
+        for ( int i = 0; i < nelem; i++ )
+        {
+            MaterialElement me = this.getElements().get(i);
+            //double elemZ = me.getZ();
+            double massFrac = this.getMassFractions().get(i);
+            double atomCntFrac = massFrac / me.getA();
+            ZsumNotNorm += atomCntFrac * me.getZ();
+            atomCntFracSum += atomCntFrac;
+        }
+        
+        double ZsumNorm = ZsumNotNorm / atomCntFracSum;
+        Zeff = ZsumNorm;
+        return Zeff;
+    }
+    
+    /** Compute effective A for this material using element list. */
+    private double computeAeff()
+    {
+        double AsumNotNorm = 0;
+        double atomCntFracSum = 0;
+        
+        int nelem = this.getNElements();
+        for ( int i = 0; i < nelem; i++ )
+        {
+            MaterialElement me = this.getElements().get(i);
+            double massFrac = this.getMassFractions().get(i);
+            double atomCntFrac = massFrac / me.getA();
+            AsumNotNorm += atomCntFrac * me.getA();
+            atomCntFracSum += atomCntFrac;
+        }
+        double ZsumNorm = AsumNotNorm / atomCntFracSum;
+        Aeff = ZsumNorm;
+        return Aeff;
+    }    
+    
+    /** Translate this material to human-readable string. */
+    public String toString()
+    {
+    	StringBuffer sb = new StringBuffer();
+    	sb.append(super.toString());
+    	sb.append("nComponents=" + nComponentsAdded + "; ");
+    	sb.append("nComponentsMax=" + nComponentsMax + "; ");
+    	sb.append("nElements=" + nElements);                                  
+        
+        for ( int i = 0; i < this.getNElements(); i++)
+        {
+        	sb.append('\n');
+        	sb.append('\t');
+            sb.append(this.getElements().get(i).getName() + " ");
+            sb.append(this.getMassFractions().get(i) * 100);
+        }
+        
+        return sb.toString();
+    }
+}
\ No newline at end of file

GeomConverter/src/org/lcsim/detector/material
IMaterial.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- IMaterial.java	3 Mar 2007 01:19:39 -0000	1.1
+++ IMaterial.java	3 Mar 2007 13:33:57 -0000	1.2
@@ -6,20 +6,36 @@
 	public double getDensity();
 	public double getZ();
 	public double getA();
+	public double getMeltingPoint();
+	public double getBoilingPoint();
+	public double getTemperature();
+	public double getPressure();
 	public double getMolecularWeight();
 	public double getEffectiveNumberOfNucleons();
 	public double getNuclearInteractionLength();
+	public double getNuclearInteractionLengthWithDensity();
 	public double getRadiationLength();
+	public double getRadiationLengthWithDensity();
+	public double getMoliereRadius();
 	public State getState();
-	public double getMeltingPoint();
-	public double getBoilingPoint();
-	public double getTemperature();
-	public double getPressure();
-	enum State
+	
+    public final static State Unknown = new State("unknown");
+    public final static State Gas = new State("gas");
+    public final static State Liquid = new State("liquid");
+    public final static State Solid = new State("solid");
+	
+	public class State
 	{
-		Gas,
-		Liquid,
-		Solid,
-		Unknown
+	    private String state;
+	    	    
+	    private State(String state)
+	    {
+	        this.state = state;
+	    }
+	    
+	    public String toString()
+	    {	       
+	        return state;
+	    }
 	}
 }
\ No newline at end of file

GeomConverter/src/org/lcsim/detector/material
MaterialElement.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- MaterialElement.java	3 Mar 2007 01:19:39 -0000	1.1
+++ MaterialElement.java	3 Mar 2007 13:33:57 -0000	1.2
@@ -21,11 +21,11 @@
 implements IMaterial
 {
 	// Defaults for non-mandatory parameters.
-	static private final double defaultTemperature=0.0;
-	static private final State defaultState=State.Unknown;
+	static private final double defaultTemperature=273.15;
+	static private final State defaultState=Unknown;
 	static private final double defaultBoilingPoint=0.0;
 	static private final double defaultMeltingPoint=0.0;
-	static private final double defaultPressure=0.0;
+	static private final double defaultPressure=1.0;
 	static private final double defaultIonizationPotential=0.0;
 	
 	// From constructor.
@@ -43,15 +43,19 @@
 	private State state=defaultState;
 	
 	// Derived quantities.
-	private double N;
-	private double molecularWeight;
-	private double nuclearInteractionLength;
-	private double radiationLength;
+	protected double N;
+	protected double molecularWeight;
+	protected double nuclearInteractionLength;
+	protected double nuclearInteractionLengthWithDensity;
+	protected double radiationLength;
+	protected double radiationLengthWithDensity;
+	protected double criticalEnergy;
+	protected double moliereRadius;
 	
 	public MaterialElement(
 			String name,
-			int Z,
-			int A,
+			double Z,
+			double A,
 			double density)
 	{
 		// Basic parameters.
@@ -97,32 +101,47 @@
 	
 	private void computeDerivedQuantities()
 	{		
+		// Order is important!
 		computeEffectiveNumberOfNucleons();
 		computeMolecularWeigth();
 		computeRadiationLength();
 		computeNuclearInteractionLength();
+		computeCriticalEnergy();
+		computeMoliereRadius();
+	}
+
+	protected void computeCriticalEnergy()
+	{
+		criticalEnergy  = 2.66 * pow(getRadiationLength() * getZ()/getA(), 1.1);
 	}
 	
-	private void computeEffectiveNumberOfNucleons()
+	protected void computeMoliereRadius()
+	{
+		moliereRadius = getRadiationLengthWithDensity() * 21.2052 / criticalEnergy;
+	}
+		
+	protected void computeEffectiveNumberOfNucleons()
 	{
 		N = A / Avogadro;	
 	}
 	
 	// FIXME: Wrong for isotopes.
-	private void computeMolecularWeigth()
+	protected void computeMolecularWeigth()
 	{
 		double natoms=1.0;
 		molecularWeight = A * natoms;
 	}
 	
-	private void computeRadiationLength()
+	protected void computeRadiationLength()
 	{
 		radiationLength = computeRadiationLengthTsai(A,Z);
+		radiationLengthWithDensity = radiationLength / getDensity();
 	}
 	
-	private void computeNuclearInteractionLength()
+	protected void computeNuclearInteractionLength()
 	{
 		nuclearInteractionLength = computeNuclearInteractionLength(A,Z);		
+		nuclearInteractionLengthWithDensity = nuclearInteractionLength / getDensity();
 	}
 
 	public double getA() 
@@ -192,6 +211,22 @@
 	{
 		return N;
 	}
+
+	public double getMoliereRadius() 
+	{
+		return moliereRadius;
+	}
+
+	public double getNuclearInteractionLengthWithDensity() 
+	{
+		return nuclearInteractionLengthWithDensity;
+	}
+
+	public double getRadiationLengthWithDensity() 
+	{
+		return radiationLengthWithDensity;
+	}
+
 	
 	public static double computeRadiationLengthTsai(double A, double Z)
     {
@@ -255,5 +290,17 @@
         }
         
         return NIL;
-    }	
+    }	       
+    
+    public String toString()
+    {
+    	StringBuffer sb = new StringBuffer();
+    	sb.append(getName() + "; ");
+    	sb.append(getDensity() + " g/cm3 ; ");
+    	sb.append("A="+getA() + "; ");
+    	sb.append("Z="+getZ() + "; ");
+    	sb.append("nucIntLen=" + getNuclearInteractionLength() + "; ");
+    	sb.append("radLen=" + getRadiationLength() + "; ");
+    	return sb.toString();
+    }
 }
\ No newline at end of file

GeomConverter/src/org/lcsim/detector/solids
Tube.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- Tube.java	3 Mar 2007 01:19:39 -0000	1.2
+++ Tube.java	3 Mar 2007 13:33:57 -0000	1.3
@@ -8,11 +8,11 @@
  *
  * @author Tim Nelson <[log in to unmask]>
  * @author Jeremy McCormick <[log in to unmask]>
- * @version $Id: Tube.java,v 1.2 2007/03/03 01:19:39 jeremy Exp $
+ * @version $Id: Tube.java,v 1.3 2007/03/03 13:33:57 jeremy Exp $
  */
 public class Tube
 extends Named
-implements ISolid
+implements ISolid, ITube
 {
 	private double innerRadius, outerRadius, zHalfLength;
 	
@@ -24,16 +24,25 @@
     	this.zHalfLength = zHalfLength;    	
     }
     
+    /* (non-Javadoc)
+	 * @see org.lcsim.detector.solids.ITube#getInnerRadius()
+	 */
     public double getInnerRadius()
     {
     	return innerRadius;
     }
     
+    /* (non-Javadoc)
+	 * @see org.lcsim.detector.solids.ITube#getOuterRadius()
+	 */
     public double getOuterRadius()
     {
     	return outerRadius;
     }
     
+    /* (non-Javadoc)
+	 * @see org.lcsim.detector.solids.ITube#getZHalfLength()
+	 */
     public double getZHalfLength()
     {
     	return zHalfLength;
CVSspam 0.2.8