Print

Print


Commit in GeomConverter/src/org/lcsim/detector on MAIN
tracker/silicon/BiasSurface.java+41added 1.1
               /ChargeCarrier.java+81.3 -> 1.4
               /ChargeDistribution.java+2-11.1 -> 1.2
               /SiSensor.java+114-1281.16 -> 1.17
               /SiSensorElectrodes.java+7-11.8 -> 1.9
               /SiStrips.java+196-841.11 -> 1.12
solids/GeomOp2D.java+52added 1.1
      /Transformable.java+23added 1.1
      /AbstractPolyhedron.java+58added 1.1
      /Box.java+2-181.4 -> 1.5
      /Polygon3D.java+221.1 -> 1.2
      /Line3D.java+17-61.1 -> 1.2
      /LineSegment3D.java+61.1 -> 1.2
      /IPolyhedron.java+21.2 -> 1.3
      /Trd.java+2-181.6 -> 1.7
      /Trap.java+2-181.7 -> 1.8
      /Point3D.java+12-11.1 -> 1.2
      /GeomOp3D.java+80-281.2 -> 1.3
      /Plane3D.java+15-21.1 -> 1.2
converter/compact/SiTrackerBarrelConverter.java+47-101.24 -> 1.25
+708-315
4 added + 16 modified, total 20 files
Many changes:
=========
In solids, changes to accommodate some required operations on geometry 
------------
- new AbstractPolyhedron takes care of some generic capabilities for polyhedra: existing polyhedra updated
- new Transformable interface for geometry objects: existing geometry objects updated
- new GeomOp2D for 2D optimized operations.  Only a few things defined and in use as of now.
In tracker.silicon: changes to support electrodes on arbitrary surface of polyhedron and with extent limited by the polygon associated with that surface
------------------
- BiasSurface defines face of polyhedron to which bias voltage is applied
- ChargeCarriers can be accessed by charge (+/- 1) simplifying access to electrodes from the side ID field of a hit
- Many changes to electrodes to improve realism of strips (capacitance dependent on calculated length of a strip)
- Strips modeled as LineSegment3D, calcuable from cell_id on the fly
- Changes to SiSensorElectrodes and SiSensor to support more detailed strip information
Changes to SiTrackerBarrelConverter to go with all of this.

GeomConverter/src/org/lcsim/detector/tracker/silicon
BiasSurface.java added at 1.1
diff -N BiasSurface.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ BiasSurface.java	3 Dec 2007 23:23:30 -0000	1.1
@@ -0,0 +1,41 @@
+/*
+ * BiasSurface.java
+ *
+ * Created on November 29, 2007, 11:13 AM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.detector.tracker.silicon;
+
+import org.lcsim.detector.solids.Polygon3D;
+
+/**
+ *
+ * @author tknelson
+ */
+public class BiasSurface
+{
+    
+    Polygon3D _surface;
+    double _voltage;
+    
+    /** Creates a new instance of BiasSurface */
+    public BiasSurface(Polygon3D surface, double voltage)
+    {
+        _surface = surface;
+        _voltage = voltage;
+    }
+    
+    public Polygon3D getSurface()
+    {
+        return _surface;
+    }
+    
+    public double getVoltage()
+    {
+        return _voltage;
+    }
+    
+}

GeomConverter/src/org/lcsim/detector/tracker/silicon
ChargeCarrier.java 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- ChargeCarrier.java	18 May 2007 21:56:34 -0000	1.3
+++ ChargeCarrier.java	3 Dec 2007 23:23:29 -0000	1.4
@@ -55,4 +55,12 @@
     double alpha(double temperature)
     {return _alpha_factor * Math.pow( (temperature/300.0), _alpha_exponent);}
     
+    // Static
+    public static ChargeCarrier getCarrier(int charge)
+    {
+        if (charge == -1) return ChargeCarrier.ELECTRON;
+        if (charge == +1) return ChargeCarrier.HOLE;
+        else throw new RuntimeException("No ChargeCarrier for charge: "+charge);
+    }
+    
 }

GeomConverter/src/org/lcsim/detector/tracker/silicon
ChargeDistribution.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- ChargeDistribution.java	14 Oct 2007 06:13:09 -0000	1.1
+++ ChargeDistribution.java	3 Dec 2007 23:23:29 -0000	1.2
@@ -11,12 +11,13 @@
 
 import org.lcsim.detector.ITransform3D;
 import hep.physics.vec.Hep3Vector;
+import org.lcsim.detector.solids.Transformable;
 
 /**
  *
  * @author tknelson
  */
-public interface ChargeDistribution
+public interface ChargeDistribution extends Transformable
 {
     // Transform this charge distribution into new coordinates in place
     public void transform(ITransform3D transform);

GeomConverter/src/org/lcsim/detector/tracker/silicon
SiSensor.java 1.16 -> 1.17
diff -u -r1.16 -r1.17
--- SiSensor.java	14 Oct 2007 06:13:09 -0000	1.16
+++ SiSensor.java	3 Dec 2007 23:23:29 -0000	1.17
@@ -29,22 +29,23 @@
 import org.lcsim.detector.identifier.IIdentifierHelper;
 import org.lcsim.detector.identifier.IIdentifierDictionary.FieldNotFoundException;
 import org.lcsim.detector.identifier.IIdentifierDictionary.InvalidIndexException;
-import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.solids.GeomOp3D;
+import org.lcsim.detector.solids.Point3D;
+import org.lcsim.detector.solids.Polygon3D;
 
 /**
  *
  * @author tknelson
  */
-public class SiSensor extends DetectorElement {
-
+public class SiSensor extends DetectorElement
+{
+    
     // Enumerated types
     //=================
-    public enum Orientation { PSIDE_NEGATIVE_Z, PSIDE_POSITIVE_Z };
     
     // Fields
     //=======
     // Static defaults - actual values user modifiable
-    private static Orientation _ORIENTATION_DEFAULT = Orientation.PSIDE_POSITIVE_Z;
     private static double _DEPLETION_VOLTAGE_DEFAULT = 100;// * volt;
     private static double _BIAS_VOLTAGE_DEFAULT = 110;// * volt;
     
@@ -54,13 +55,12 @@
     // Sensor ID
     private int _sensorid;
     
-    // electrodes, electrode angles and orientation of sensor
+    // biasing and electrodes
+    private Map<ChargeCarrier, Polygon3D> _bias_surfaces = new EnumMap<ChargeCarrier,Polygon3D>(ChargeCarrier.class);
     private Map<ChargeCarrier, SiSensorElectrodes> _sense_electrodes = new EnumMap<ChargeCarrier,SiSensorElectrodes>(ChargeCarrier.class);
     private Map<ChargeCarrier, SiSensorElectrodes> _readout_electrodes = new EnumMap<ChargeCarrier,SiSensorElectrodes>(ChargeCarrier.class);
     private Map<ChargeCarrier, BasicMatrix> _transfer_efficiencies = new EnumMap<ChargeCarrier,BasicMatrix>(ChargeCarrier.class);
-//    private Map<ChargeCarrier, Double> _electrode_angles = new EnumMap<ChargeCarrier,Double>(ChargeCarrier.class);
-    private Orientation _orientation;
-
+    
     // bulk - propoerties of the bulk
     private DopedSilicon _bulk;
     private double _thickness;  // accessed often, cached here for speed
@@ -69,11 +69,6 @@
     private double _depletion_voltage;
     private double _bias_voltage;
     
-    // derived properties
-    //-------------------
-    // measured coordinates in local coordinates
-//    private EnumMap<ChargeCarrier, Hep3Vector[]> _measured_coordinates = new EnumMap<ChargeCarrier,Hep3Vector[]>(ChargeCarrier.class);
-    
     // Constructors
     //=============
     
@@ -89,7 +84,6 @@
         super(name,parent,support,id);
         setSensorID(sensorid);
         setBulk(new DopedSilicon());
-        this.setOrientation(SiSensor._ORIENTATION_DEFAULT);
         setDepletionVoltage(SiSensor._DEPLETION_VOLTAGE_DEFAULT);
         setBiasVoltage(SiSensor._BIAS_VOLTAGE_DEFAULT);
     }
@@ -104,19 +98,19 @@
         _sensorid = sensorid;
     }
     
-    public void setElectrodes(ChargeCarrier carrier, SiSensorElectrodes electrodes)
+    public void setSenseElectrodes(SiSensorElectrodes sense_electrodes)
     {
-        _sense_electrodes.put(carrier,electrodes);
+        _sense_electrodes.put(sense_electrodes.getChargeCarrier(),sense_electrodes);
     }
- 
-    public void setSenseElectrodes(ChargeCarrier carrier, SiSensorElectrodes sense_electrodes)
+    
+    public void setReadoutElectrodes(SiSensorElectrodes readout_electrodes)
     {
-        _sense_electrodes.put(carrier,sense_electrodes);
+        _readout_electrodes.put(readout_electrodes.getChargeCarrier(),readout_electrodes);
     }
-
-    public void setReadoutElectrodes(ChargeCarrier carrier, SiSensorElectrodes readout_electrodes)
+    
+    public void setBiasSurface(ChargeCarrier carrier, Polygon3D bias_surface)
     {
-        _readout_electrodes.put(carrier,readout_electrodes);
+        _bias_surfaces.put(carrier,bias_surface);
     }
     
     public void setTransferEfficiencies(ChargeCarrier carrier, BasicMatrix transfer_efficiencies)
@@ -124,16 +118,6 @@
         _transfer_efficiencies.put(carrier,transfer_efficiencies);
     }
     
-//    public void setElectrodeAngle(ChargeCarrier carrier, double electrode_angle)
-//    {
-//        _electrode_angles.put(carrier,electrode_angle);
-//    }
-    
-    public void setOrientation(Orientation orientation)
-    {
-        _orientation = orientation;
-    }
-    
     public void setBulk(DopedSilicon bulk)
     {
         _bulk = bulk;
@@ -153,11 +137,6 @@
     public int getSensorID()
     {
         return _sensorid;
-    }    
-    
-    public SiSensorElectrodes getElectrodes(ChargeCarrier carrier)
-    {
-        return _sense_electrodes.get(carrier);
     }
     
     public SiSensorElectrodes getSenseElectrodes(ChargeCarrier carrier)
@@ -170,19 +149,14 @@
         return _readout_electrodes.get(carrier);
     }
     
-    public BasicMatrix getTransferEfficiencies(ChargeCarrier carrier)
+    public Polygon3D getBiasSurface(ChargeCarrier carrier)
     {
-        return _transfer_efficiencies.get(carrier);
+        return _bias_surfaces.get(carrier);
     }
     
-//    public double getElectrodeAngle(ChargeCarrier carrier)
-//    {
-//        return _electrode_angles.get(carrier);
-//    }
-    
-    public Orientation getOrientation()
+    public BasicMatrix getTransferEfficiencies(ChargeCarrier carrier)
     {
-        return _orientation;
+        return _transfer_efficiencies.get(carrier);
     }
     
     public DopedSilicon getBulk()
@@ -192,6 +166,20 @@
     
     public double getThickness()
     {
+        if (_thickness == 0)
+        {
+            
+            
+//            System.out.println("Hole plane normal: "+_bias_surfaces.get(ChargeCarrier.HOLE).getPlane().getNormal());
+//            System.out.println("Hole plane direction: "+_bias_surfaces.get(ChargeCarrier.HOLE).getPlane().getDistance());
+//
+//            System.out.println("Electron plane normal: "+_bias_surfaces.get(ChargeCarrier.ELECTRON).getPlane().getNormal());
+//            System.out.println("Electron plane direction: "+_bias_surfaces.get(ChargeCarrier.ELECTRON).getPlane().getDistance());
+            
+            _thickness = Math.abs(GeomOp3D.distanceBetween( _bias_surfaces.get(ChargeCarrier.HOLE).getPlane(), _bias_surfaces.get(ChargeCarrier.ELECTRON).getPlane()));            
+            
+//            System.out.println("Calculated thickness: "+_thickness);
+        }
         return _thickness;
     }
     
@@ -213,56 +201,24 @@
         {
             ancestor = ancestor.getParent();
         }
-        if (ancestor == null) System.out.println("WARNING: SiSensor.getBField CANNOT FIND DETECTOR!!");                
-
+        if (ancestor == null) throw new RuntimeException("SiSensor.getBField CANNOT FIND DETECTOR!!");
+        
         Hep3Vector global_position = getGeometry().getLocalToGlobal().transformed(local_position);
         Hep3Vector field_global = ((DeDetector)ancestor).getBField(global_position);
+//        Hep3Vector field_global = new BasicHep3Vector(0,0,5);
         
         return getGeometry().getGlobalToLocal().rotated(field_global);
         
     }
-        
-//    public Hep3Vector[] getMeasuredCoordinates(ChargeCarrier carrier)
-//    {
-//        return _measured_coordinates.get(carrier);
-//    }
-    
     
     // Operators
     //==========
-    public void initialize()
-    {
-
-        // Cache thickness of bulk
-        _thickness = 2.0*((Box)getGeometry().getLogicalVolume().getSolid()).getZHalfLength();
-        
-        // Store various important directions
-        for (ChargeCarrier carrier : ChargeCarrier.values())
-        {
-            if (hasElectrodesOnSide(carrier)) {  
-                
-//                // cache coordinates measured by the pattern of electrodes on each side
-//                double electrode_angle = getElectrodeAngle(carrier); 
-//                int naxes = _sense_electrodes.get(carrier).getNAxes();
-//                Hep3Vector[] measured_coordinates = new Hep3Vector[naxes];
-//                
-//                for (int iaxis = 0; iaxis < naxes ; iaxis++)
-//                {
-//                    measured_coordinates[iaxis] = measuredCoordinate(electrode_angle + iaxis*Math.PI/naxes);
-//                }
-//                _measured_coordinates.put(carrier,measured_coordinates);
-
-            
-            }
-        }
-
-    }
-    
-    private double zOfSide(ChargeCarrier carrier)
-    {   
-        if ( (carrier == ChargeCarrier.HOLE) == (_orientation == Orientation.PSIDE_POSITIVE_Z) ) return _thickness/2.0;
-        else return -_thickness/2.0;
-    }
+//    public void initialize()
+//    {
+//        // Cache thickness of bulk
+//        _thickness = Math.abs(GeomOp3D.distanceBetween( _bias_surfaces.get(ChargeCarrier.HOLE).getPlane(), _bias_surfaces.get(ChargeCarrier.HOLE).getPlane()));
+//
+//    }
     
     public boolean isACCoupled(ChargeCarrier carrier)
     {
@@ -271,8 +227,14 @@
     
     public double distanceFromSide(Hep3Vector point, ChargeCarrier carrier)
     {
-        double distance =  Math.abs(point.z() - zOfSide(carrier));
-        return distance;
+//        System.out.println("distanceFromSide: "+-GeomOp3D.distanceBetween(new Point3D(point),_bias_surfaces.get(carrier).getPlane()));
+        
+        
+        return -GeomOp3D.distanceBetween(new Point3D(point),_bias_surfaces.get(carrier).getPlane());
+//        ITransform3D electrode_transform = _sense_electrodes.get(carrier).getParentToLocal().inverse();
+//        Plane3D electrode_plane = _sense_electrodes.get(carrier).getGeometry().transformed(electrode_transform).getPlane();
+//
+//        return GeomOp3D.distanceBetween(new Point3D(point),electrode_plane);
     }
     
     public boolean hasElectrodesOnSide(ChargeCarrier carrier)
@@ -281,21 +243,43 @@
         else return true;
     }
     
-//    private Hep3Vector measuredCoordinate(double electrode_angle)
-//    {
-//        return new BasicHep3Vector(Math.cos(electrode_angle),Math.sin(electrode_angle),0.0);
-//    }
-    
     public Hep3Vector electricField(Hep3Vector position)
     {
-        Hep3Vector electric_field_direction = (this._orientation == Orientation.PSIDE_POSITIVE_Z) ?
-            new BasicHep3Vector(0.0,0.0,1.0) : new BasicHep3Vector(0.0,0.0,-1.0);
         
-        double electric_field_magnitude = (_bias_voltage-_depletion_voltage)/_thickness + 
-                (2.0*_depletion_voltage)/_thickness * (1.0 - this.distanceFromSide(position,ChargeCarrier.ELECTRON));
+        // See Gorelov
+        double electric_field_magnitude = (_bias_voltage-_depletion_voltage)/getThickness() +
+                (2.0*_depletion_voltage)/getThickness() * (1.0 - this.distanceFromSide(position,ChargeCarrier.ELECTRON));
+//        System.out.println("Electric field strength: "+electric_field_magnitude);
+//        System.out.println("Distance from side: "+this.distanceFromSide(position,ChargeCarrier.ELECTRON));
+//        System.out.println("Thickness: "+getThickness());
+        
+        Hep3Vector electric_field_direction = _bias_surfaces.get(ChargeCarrier.HOLE).getNormal();
+
+//        System.out.println("Electric field direction: "+electric_field_direction);
         
         return VecOp.mult(electric_field_magnitude,electric_field_direction);
         
+        
+//        Hep3Vector electric_field_direction = null;
+//        for (ChargeCarrier carrier : ChargeCarrier.values())
+//        {
+//            if (hasElectrodesOnSide(carrier))
+//            {
+//                ITransform3D electrode_transform = _sense_electrodes.get(carrier).getParentToLocal().inverse();
+//                Plane3D electrode_plane = _sense_electrodes.get(carrier).getGeometry().transformed(electrode_transform).getPlane();
+//                electric_field_direction = VecOp.mult(carrier.charge(),electrode_plane.getNormal());
+//                if (!(electric_field_direction == null)) break;
+//            }
+//        }
+//
+////        Hep3Vector electric_field_direction = (this._orientation == Orientation.PSIDE_POSITIVE_Z) ?
+////            new BasicHep3Vector(0.0,0.0,1.0) : new BasicHep3Vector(0.0,0.0,-1.0);
+//
+//        double electric_field_magnitude = (_bias_voltage-_depletion_voltage)/_thickness +
+//                (2.0*_depletion_voltage)/_thickness * (1.0 - this.distanceFromSide(position,ChargeCarrier.ELECTRON));
+//
+//        return VecOp.mult(electric_field_magnitude,electric_field_direction);
+        
     }
     
     public String toString()
@@ -308,7 +292,7 @@
     
     public IIdentifierHelper getIdentifierHelper()
     {
-        List<DeSubdetector> subdet = findAncestors(DeSubdetector.class);        
+        List<DeSubdetector> subdet = findAncestors(DeSubdetector.class);
         if ( subdet.size() == 0 )
         {
             throw new RuntimeException("Can't find DeSubdetector for SiSensor!");
@@ -318,38 +302,40 @@
     
     /**
      * Make an {@link IIdentifier} for a given strip number and side number.
-     * 
+     *
      * @param stripNumber The strip number, which should be from 1 to nstrips - 1.
      * @param sideNumber  The side number, which should be 1 or -1.
      * @return A 64-bit   A packed id for the strip.
      */
     public IIdentifier makeStripId( int stripNumber, int sideNumber )
     {
-		// Copy the DetectorElement's identifier, which will leave blank fields
-		// for side and strip.
-    	IExpandedIdentifier id = new ExpandedIdentifier(getExpandedIdentifier());
-    	
-    	// Get the helper and dictionary.
-    	IIdentifierHelper helper = getIdentifierHelper();
-		IIdentifierDictionary dict = helper.getIdentifierDictionary();
-    	
-    	try {
-    		// Fill in the side and strip numbers.
-    		id.setValue(dict.getFieldIndex("side"), sideNumber);
-    		id.setValue(dict.getFieldIndex("strip"), stripNumber);
-    	}
-    	catch (FieldNotFoundException x)
-    	{
-    		throw new RuntimeException(x);
-    	}
-    	
-    	try {
-    		// Pack and return the id.
-    		return helper.pack( id );
-    	}
-    	catch (InvalidIndexException x)
-    	{
-    		throw new RuntimeException(x);
-    	}
-    }    
+        // Copy the DetectorElement's identifier, which will leave blank fields
+        // for side and strip.
+        IExpandedIdentifier id = new ExpandedIdentifier(getExpandedIdentifier());
+        
+        // Get the helper and dictionary.
+        IIdentifierHelper helper = getIdentifierHelper();
+        IIdentifierDictionary dict = helper.getIdentifierDictionary();
+        
+        try
+        {
+            // Fill in the side and strip numbers.
+            id.setValue(dict.getFieldIndex("side"), sideNumber);
+            id.setValue(dict.getFieldIndex("strip"), stripNumber);
+        }
+        catch (FieldNotFoundException x)
+        {
+            throw new RuntimeException(x);
+        }
+        
+        try
+        {
+            // Pack and return the id.
+            return helper.pack( id );
+        }
+        catch (InvalidIndexException x)
+        {
+            throw new RuntimeException(x);
+        }
+    }
 }
\ No newline at end of file

GeomConverter/src/org/lcsim/detector/tracker/silicon
SiSensorElectrodes.java 1.8 -> 1.9
diff -u -r1.8 -r1.9
--- SiSensorElectrodes.java	16 Nov 2007 22:47:07 -0000	1.8
+++ SiSensorElectrodes.java	3 Dec 2007 23:23:30 -0000	1.9
@@ -14,6 +14,7 @@
 import hep.physics.vec.Hep3Vector;
 import java.util.SortedMap;
 import java.util.Set;
+import org.lcsim.detector.solids.Polygon3D;
 
 /**
  *
@@ -36,6 +37,9 @@
     // Transformation from gloabl coordinates to electrode coordinates
     public ITransform3D getGlobalToLocal();
     
+    // Polygon on which electrodes are defined
+    public Polygon3D getGeometry();
+    
     // Direction of each measured coordinate
     public Hep3Vector getMeasuredCoordinate(int axis);
     
@@ -87,11 +91,13 @@
     // Location of given position within a cell
     public Hep3Vector getPositionInCell(Hep3Vector position);
     
+    // Charge carrier
+    public ChargeCarrier getChargeCarrier();
+    
     // Capacitance of electrode
     public double getCapacitance(int cell_id);
     
     // Compute Gaussian-distributed charge on electrodes
     public SortedMap<Integer,Integer> computeElectrodeData(ChargeDistribution distribution);
-//    public SortedMap<Integer,Integer> computeElectrodeData(double charge, Hep3Vector position, ErrorEllipse2D distribution);
     
 }

GeomConverter/src/org/lcsim/detector/tracker/silicon
SiStrips.java 1.11 -> 1.12
diff -u -r1.11 -r1.12
--- SiStrips.java	16 Nov 2007 22:47:07 -0000	1.11
+++ SiStrips.java	3 Dec 2007 23:23:30 -0000	1.12
@@ -16,11 +16,18 @@
 import hep.physics.vec.Hep3Vector;
 import hep.physics.vec.BasicHep3Vector;
 import hep.physics.vec.VecOp;
+import java.util.ArrayList;
 import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.Set;
 import java.util.HashSet;
-import org.lcsim.units.clhep.SystemOfUnits;
+import java.util.List;
+import org.lcsim.detector.solids.GeomOp2D;
+import org.lcsim.detector.solids.GeomOp3D;
+import org.lcsim.detector.solids.Line3D;
+import org.lcsim.detector.solids.LineSegment3D;
+import org.lcsim.detector.solids.Point3D;
+import org.lcsim.detector.solids.Polygon3D;
 
 /**
  *
@@ -30,60 +37,55 @@
 {
     
     // Fields
+    
+    // Object definition
+    private ChargeCarrier _carrier; // charge carrier collected
     private int _nstrips; // number of strips
     private double _pitch; // sense pitch
     private IDetectorElement _detector; // associated detector element
     private ITransform3D _parent_to_local; // parent to local transform
     private ITransform3D _local_to_global; // transformation to global coordinates
     private ITransform3D _global_to_local; // transformation from global coordinates
+    private Polygon3D _geometry; // region in which strips are defined
+    
+    // Cached for convenience
+    private double _strip_offset;
     
     // Constructors
     //=============
-    
-    public SiStrips(int nstrips, double pitch, IDetectorElement detector, ITransform3D parent_to_local)
+    public SiStrips(ChargeCarrier carrier, double pitch, IDetectorElement detector, ITransform3D parent_to_local)
     {
-        setNStrips(nstrips);
+        
+//        System.out.println("Plane of polygon in sensor coordinates has... ");
+//        System.out.println("                        normal: "+((SiSensor)detector).getBiasSurface(carrier).getNormal());
+//        System.out.println("                        distance: "+((SiSensor)detector).getBiasSurface(carrier).getDistance());
+        
+        setCarrier(carrier);
         setPitch(pitch);
+        setGeometry(((SiSensor)detector).getBiasSurface(carrier).transformed(parent_to_local));
+        setStripNumbering();
         setDetectorElement(detector);
         setParentToLocal(parent_to_local);
         setGlobalToLocal(Transform3D.multiply(parent_to_local,detector.getGeometry().getGlobalToLocal()));
         setLocalToGlobal(getGlobalToLocal().inverse());
     }
     
-    // Setters
-    //==================
-    private void setNStrips(int nstrips)
-    {
-        _nstrips = nstrips;
-    }
-    
-    private void setPitch(double pitch)
+    public SiStrips(ChargeCarrier carrier, double pitch, int nstrips, IDetectorElement detector, ITransform3D parent_to_local)
     {
-        _pitch = pitch;
-    }
-    
-    private void setDetectorElement(IDetectorElement detector)
-    {
-        _detector = detector;
-    }
-    
-    private void setParentToLocal(ITransform3D parent_to_local)
-    {
-        _parent_to_local = parent_to_local;
-    }
-    
-    private void setLocalToGlobal(ITransform3D local_to_global)
-    {
-        _local_to_global = local_to_global;
+        setCarrier(carrier);
+        setPitch(pitch);
+        setGeometry(((SiSensor)detector).getBiasSurface(carrier).transformed(parent_to_local));
+        setNStrips(nstrips);
+        setDetectorElement(detector);
+        setParentToLocal(parent_to_local);
+        setGlobalToLocal(Transform3D.multiply(parent_to_local,detector.getGeometry().getGlobalToLocal()));
+        setLocalToGlobal(getGlobalToLocal().inverse());
     }
     
-    private void setGlobalToLocal(ITransform3D global_to_local)
-    {
-        _global_to_local = global_to_local;
-    }
+    // SiSensorElectrodes interface
+    //=============================
     
-    // Getters
-    //===================
+    // Mechanical properties
     public int getNAxes()
     {
         return 1;
@@ -109,6 +111,11 @@
         return _global_to_local;
     }
     
+    public Polygon3D getGeometry()
+    {
+        return _geometry;
+    }
+    
     public Hep3Vector getMeasuredCoordinate(int axis)
     {
         if (axis == 0) return new BasicHep3Vector(1.0,0.0,0.0);
@@ -165,11 +172,15 @@
     
     public double getPitch(int axis)
     {
-        return _pitch;
+        if (axis == 0)
+        {
+            return _pitch;
+        }
+        else return 0;
     }
     public int getCellID(Hep3Vector position)
     {
-        return (int)Math.round((position.x()+getStripOffset())/_pitch);
+        return (int)Math.round((position.x()+_strip_offset)/_pitch);
     }
     
     
@@ -205,12 +216,18 @@
     
     public Hep3Vector getCellPosition(int strip_number)
     {
-        return new BasicHep3Vector(strip_number*_pitch-getStripOffset(),0.0,0.0);
+        return new BasicHep3Vector(strip_number*_pitch-_strip_offset,0.0,0.0);
+    }
+    
+    // Electrical properties
+    public ChargeCarrier getChargeCarrier()
+    {
+        return _carrier;
     }
     
-    public double getCapacitance(int strip_number) // capacitance in pF
+    public double getCapacitance(int cell_id) // capacitance in pF
     {
-        return 20.0;  // FIXME: hard wired for now
+        return 0.1*getStripLength(cell_id);  // FIXME: hard wired for now to 0.1 pf/mm
     }
     
     public SortedMap<Integer,Integer> computeElectrodeData(ChargeDistribution distribution)
@@ -241,7 +258,10 @@
             
 //            System.out.println("integral_upper: "+integral_upper);
             
-            if (integral_lower<integral_upper) System.out.println("SQUEAL LIKE A PIG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+            if (integral_lower<integral_upper)
+            {
+                throw new RuntimeException("Error in integrating Gaussian charge distribution!");
+            }
             
             int strip_charge = (int)Math.round(integral_lower-integral_upper);
             
@@ -259,52 +279,144 @@
         
     }
     
-//    public SortedMap<Integer,Integer> computeElectrodeData(double charge, Hep3Vector position, ChargeDistribution distribution)
-//    {
-//        
-//        SortedMap<Integer,Integer> electrode_data = new TreeMap<Integer,Integer>();
-//        
-//        int base_strip = getCellID(position);
-//        
-//        Hep3Vector interstrip_position = getPositionInCell(position);
-//        
-//        // put charge on strips in window 3-sigma strips on each side of base strip
-//        double pitch = _pitch;
-//        double axis_angle = 0.0;
-//        
-//        int window_size = (int)Math.ceil(3.0*distribution.sigma1D(axis_angle)/pitch);
-//        
-//        double erfc_lower = 1.0;
-//        double erfc_upper = 1.0;
-//        
-//        for (int istrip = base_strip-window_size; istrip <= base_strip+window_size; istrip++)
-//        {
-//            
-//            double cell_edge_upper = getCellPosition(istrip).x() + pitch/2.0;
-//            
-//            double erfc_limit = cell_edge_upper-position.x();
-//            
-//            erfc_upper = distribution.erfc1D(erfc_limit,axis_angle);
-//            
-//            if (erfc_lower<erfc_upper) System.out.println("SQUEAL LIKE A PIG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
-//            
-//            int strip_charge = (int)Math.round( (erfc_lower-erfc_upper) * charge);
-//            
-//            if (strip_charge != 0)
-//            {
-//                electrode_data.put(istrip,strip_charge);
-//            }
-//            
-//            erfc_lower = erfc_upper;
-//            
-//        }
-//        return electrode_data;
-//    }
+    // Strip specific methods
+    
+    // length of strip
+    public double getStripLength(int cell_id)
+    {
+//        System.out.println("strip_length: "+getStrip(cell_id).getLength());
+        return getStrip(cell_id).getLength();
+    }
+    
+    // center of strip
+    public Hep3Vector getStripCenter(int cell_id)
+    {
+        LineSegment3D strip = getStrip(cell_id);
+        return strip.getEndPoint(strip.getLength()/2);
+    }
+    
+    // line segment for strip
+    public LineSegment3D getStrip(int cell_id)
+    {
+        Line3D strip_line = new Line3D(new Point3D(getCellPosition(cell_id)),getUnmeasuredCoordinate(0));
+        
+//        System.out.println("strip_line start point: "+strip_line.getStartPoint());
+//        System.out.println("strip_line direction: "+strip_line.getDirection());
+        
+        List<Point3D> intersections = new ArrayList<Point3D>();
+        
+        // Get intersections between strip line and edges of electrode polygon
+        for (LineSegment3D edge : _geometry.getEdges())
+        {
+//            System.out.println("edge start point: "+edge.getStartPoint());
+//            System.out.println("edge end point: "+edge.getEndPoint());
+            
+            if (GeomOp2D.intersects(strip_line,edge))
+            {
+                intersections.add(GeomOp3D.lineBetween(strip_line,edge).getStartPoint());
+            }
+        }
+        
+        // Check for rare occurrence of duplicates (can happen at corners of polygon)
+        List<Point3D> strip_ends = new ArrayList<Point3D>(intersections);
+        if (intersections.size() > 2)
+        {
+            for (int ipoint1 = 0; ipoint1 < intersections.size(); ipoint1++)
+            {
+                Point3D point1 = intersections.get(ipoint1);
+                for (int ipoint2 = ipoint1+1; ipoint2 < intersections.size(); ipoint2++)
+                {
+                    Point3D point2 = intersections.get(ipoint2);
+                    if (GeomOp3D.intersects(point1,point2))
+                    {
+                        strip_ends.remove(point2);
+                        if (strip_ends.size() == 2) break;
+                    }
+                }
+            }
+        }
+        
+        return new LineSegment3D(strip_ends.get(0),strip_ends.get(1));
+    }
+    
+    // Private setters
+    //==================
+    public void setCarrier(ChargeCarrier carrier)
+    {
+        _carrier = carrier;
+    }
     
-    // Private
-    private double getStripOffset()
+    public void setGeometry(Polygon3D geometry)
     {
-        return (_nstrips-1)*_pitch/2.;
+//        System.out.println("Plane of polygon has... ");
+//        System.out.println("                        normal: "+geometry.getNormal());
+//        System.out.println("                        distance: "+geometry.getDistance());
+//
+//        System.out.println("Working plane has... ");
+//        System.out.println("                        normal: "+GeomOp2D.PLANE.getNormal());
+//        System.out.println("                        distance: "+GeomOp2D.PLANE.getDistance());
+        
+        if (GeomOp3D.equals(geometry.getPlane(),GeomOp2D.PLANE))
+        {
+            _geometry = geometry;
+        }
+        else
+        {
+            throw new RuntimeException("Electrode geometry must be defined in x-y plane!!");
+        }
+    }
+    
+    private void setStripNumbering()
+    {
+        double xmin = Double.MAX_VALUE;
+        double xmax = Double.MIN_VALUE;
+        for (Point3D vertex : _geometry.getVertices())
+        {
+            xmin = Math.min(xmin,vertex.x());
+            xmax = Math.max(xmax,vertex.x());
+        }
+        
+//        System.out.println("xmin: " + xmin);
+//        System.out.println("xmax: " + xmax);
+//        System.out.println("xmax: " + xmax);
+//
+//        System.out.println("# strips: " +   (int)Math.floor((xmax-xmin-2*getPitch(0))/getPitch(0)) ) ;
+        
+        
+        setNStrips(  (int)Math.floor((xmax-xmin-2*getPitch(0))/getPitch(0)) ) ;
+    }
+    
+    private void setNStrips(int nstrips)
+    {
+        _nstrips = nstrips;
+        _strip_offset = (_nstrips-1)*_pitch/2.;
+    }
+    
+    private void setPitch(double pitch)
+    {
+        _pitch = pitch;
+    }
+    
+    private void setDetectorElement(IDetectorElement detector)
+    {
+        _detector = detector;
+    }
+    
+    private void setParentToLocal(ITransform3D parent_to_local)
+    {
+        _parent_to_local = parent_to_local;
+    }
+    
+    private void setLocalToGlobal(ITransform3D local_to_global)
+    {
+        _local_to_global = local_to_global;
+    }
+    
+    private void setGlobalToLocal(ITransform3D global_to_local)
+    {
+        _global_to_local = global_to_local;
     }
     
 }
+
+

GeomConverter/src/org/lcsim/detector/solids
GeomOp2D.java added at 1.1
diff -N GeomOp2D.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ GeomOp2D.java	3 Dec 2007 23:23:30 -0000	1.1
@@ -0,0 +1,52 @@
+/*
+ * GeomOp2D.java
+ *
+ * Created on November 20, 2007, 1:28 PM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.detector.solids;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+/**
+ *
+ * @author tknelson
+ */
+public class GeomOp2D
+{
+    
+    // All operations are defined on x,y plane
+    public static final Plane3D PLANE = new Plane3D(new BasicHep3Vector(0,0,1),0);
+    
+    public static final double DISTANCE_TOLERANCE = 1E-9;
+    public static final double ANGULAR_TOLERANCE = 1E-9;
+    
+    /** Creates a new instance of GeomOp2D */
+    public GeomOp2D()
+    {
+    }
+    
+    public static boolean intersects(Line3D line, LineSegment3D linesegment)
+    {
+        Hep3Vector diff_start = VecOp.sub(linesegment.getStartPoint(),line.getStartPoint());
+        Hep3Vector diff_end = VecOp.sub(linesegment.getEndPoint(),line.getStartPoint());
+        Hep3Vector start_cross = VecOp.cross(line.getDirection(),diff_start);
+        Hep3Vector end_cross = VecOp.cross(line.getDirection(),diff_end);
+        return (VecOp.dot(start_cross,end_cross) < 0);
+    }
+    
+//    public Point3D intersection(Line3D line, LineSegment3D linesegment)
+//    {
+//        
+//        
+//        
+//    }
+    
+    
+    
+}

GeomConverter/src/org/lcsim/detector/solids
Transformable.java added at 1.1
diff -N Transformable.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Transformable.java	3 Dec 2007 23:23:30 -0000	1.1
@@ -0,0 +1,23 @@
+/*
+ * Transformable.java
+ *
+ * Created on November 23, 2007, 4:54 AM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.detector.solids;
+
+import org.lcsim.detector.ITransform3D;
+
+/**
+ *
+ * @author tknelson
+ */
+public interface Transformable
+{
+    public void transform(ITransform3D transform);
+    
+    public Transformable transformed(ITransform3D transform);
+}

GeomConverter/src/org/lcsim/detector/solids
AbstractPolyhedron.java added at 1.1
diff -N AbstractPolyhedron.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ AbstractPolyhedron.java	3 Dec 2007 23:23:30 -0000	1.1
@@ -0,0 +1,58 @@
+/*
+ * AbstractPolyhedron.java
+ *
+ * Created on November 29, 2007, 9:45 AM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.detector.solids;
+
+import hep.physics.vec.Hep3Vector;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author tknelson
+ */
+public abstract class AbstractPolyhedron extends AbstractSolid implements IPolyhedron
+{
+    
+    /** Creates a new instance of AbstractPolyhedron */
+    public AbstractPolyhedron(String name)
+    {
+        super(name);
+    }
+    
+    public Inside inside(Hep3Vector p)
+    {
+        Point3D point = new Point3D(p);
+        
+        boolean inside = true;
+        for (Polygon3D face : getFaces())
+        {
+            if (GeomOp3D.intersects(point,face)) return Inside.SURFACE;
+            inside = inside && (GeomOp3D.distanceBetween(point,face.getPlane()) < 0);
+        }
+        
+        if (inside) return Inside.INSIDE;
+        else return Inside.OUTSIDE;
+    }
+    
+    public List<Polygon3D> getFacesNormalTo(Hep3Vector normal)
+    {
+        List<Polygon3D> faces = new ArrayList<Polygon3D>();
+      
+        for (Polygon3D face : getFaces())
+        {
+            if (GeomOp3D.isNormal(normal,face)) 
+            {
+                faces.add(face);
+            }
+        }
+        return faces;
+    }
+    
+}

GeomConverter/src/org/lcsim/detector/solids
Box.java 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- Box.java	14 Nov 2007 19:34:51 -0000	1.4
+++ Box.java	3 Dec 2007 23:23:30 -0000	1.5
@@ -13,10 +13,9 @@
  *
  * @author Tim Nelson <[log in to unmask]>
  * @author Jeremy McCormick <[log in to unmask]>
- * @version $Id: Box.java,v 1.4 2007/11/14 19:34:51 tknelson Exp $
+ * @version $Id: Box.java,v 1.5 2007/12/03 23:23:30 tknelson Exp $
  */
-public class Box
-        extends AbstractSolid implements IPolyhedron
+public class Box extends AbstractPolyhedron
 {
     
     private final static int[] _HEPREP_VERTEX_ORDERING = {2,3,1,0,6,7,5,4};
@@ -46,21 +45,6 @@
         return zHalf;
     }
 
-    public Inside inside(Hep3Vector p)
-    {
-        Point3D point = new Point3D(p);
-        
-        boolean inside = true;
-        for (Polygon3D face : getFaces())
-        {
-            if (GeomOp3D.intersects(point,face)) return Inside.SURFACE;
-            inside = inside && (GeomOp3D.distanceBetween(point,face.getPlane()) < 0);
-        }
-        
-        if (inside) return Inside.INSIDE;
-        else return Inside.OUTSIDE;
-    }
-
     public double getCubicVolume()
     {
         return 8 * (getXHalfLength() * getYHalfLength() * getZHalfLength());

GeomConverter/src/org/lcsim/detector/solids
Polygon3D.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- Polygon3D.java	13 Nov 2007 21:04:50 -0000	1.1
+++ Polygon3D.java	3 Dec 2007 23:23:30 -0000	1.2
@@ -11,6 +11,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import org.lcsim.detector.ITransform3D;
 
 /**
  *
@@ -65,4 +66,25 @@
         return edges;
     }
     
+    public void transform(ITransform3D transform)
+    {
+        for (Point3D point : _points)
+        {
+            point.transform(transform);
+        }   
+        Plane3D new_plane = new Plane3D(_points);
+        this._distance = new_plane.getDistance();
+        this._normal = new_plane.getNormal();
+    }
+    
+    public Polygon3D transformed(ITransform3D transform)
+    {
+        List<Point3D> transformed_points = new ArrayList<Point3D>();
+        for (Point3D point : _points)
+        {
+            transformed_points.add(point.transformed(transform));
+        }
+        return new Polygon3D(transformed_points);
+    }
+    
 }

GeomConverter/src/org/lcsim/detector/solids
Line3D.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- Line3D.java	13 Nov 2007 21:04:50 -0000	1.1
+++ Line3D.java	3 Dec 2007 23:23:30 -0000	1.2
@@ -12,16 +12,17 @@
 import hep.physics.vec.BasicHep3Vector;
 import hep.physics.vec.Hep3Vector;
 import hep.physics.vec.VecOp;
+import org.lcsim.detector.ITransform3D;
 
 /**
  *
  * @author tknelson
  */
-public class Line3D
+public class Line3D implements Transformable
 {
     
-    private Point3D _startpoint;
-    private Hep3Vector _direction;
+    protected Point3D _startpoint;
+    protected Hep3Vector _direction;
     
     /**
      * Creates a new instance of Line3D
@@ -46,7 +47,7 @@
     public Hep3Vector getDirection()
     {
         return _direction;
-    }    
+    }
     
     public Point3D getEndPoint(double length)
     {
@@ -56,7 +57,7 @@
     public Inside inside(Hep3Vector point)
     {
         Hep3Vector v1 = VecOp.sub(point,getStartPoint());
-       
+        
         double v1mag = v1.magnitude();
         
         if ( Math.abs(VecOp.dot(v1,_direction)) - v1mag < Tolerance.TOLERANCE ) return Inside.INSIDE;
@@ -69,7 +70,7 @@
     {
         Hep3Vector normal = VecOp.cross(line.getDirection(),this.getDirection());
         Hep3Vector diff = VecOp.sub(line.getStartPoint(),this.getStartPoint());
-        return VecOp.dot(normal,diff)/normal.magnitude();       
+        return VecOp.dot(normal,diff)/normal.magnitude();
     }
     
     public double distanceTo(Point3D point)
@@ -78,5 +79,15 @@
         return Math.sqrt( diff.magnitudeSquared() - Math.pow(VecOp.dot(diff,this.getDirection()),2) );
     }
     
+    public void transform(ITransform3D transform)
+    {
+        _startpoint.transform(transform);
+        transform.rotate(_direction);
+    }
+    
+    public Line3D transformed(ITransform3D transform)
+    {
+        return new Line3D(_startpoint.transformed(transform),transform.rotated(_direction));
+    }
     
 }

GeomConverter/src/org/lcsim/detector/solids
LineSegment3D.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- LineSegment3D.java	13 Nov 2007 21:04:50 -0000	1.1
+++ LineSegment3D.java	3 Dec 2007 23:23:30 -0000	1.2
@@ -81,4 +81,10 @@
         return points;
     }       
     
+    public void reverse()
+    {
+        _startpoint = getEndPoint();
+        _direction = VecOp.mult(-1,getDirection());
+    }
+    
 }

GeomConverter/src/org/lcsim/detector/solids
IPolyhedron.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- IPolyhedron.java	14 Nov 2007 19:34:51 -0000	1.2
+++ IPolyhedron.java	3 Dec 2007 23:23:30 -0000	1.3
@@ -9,6 +9,7 @@
 
 package org.lcsim.detector.solids;
 
+import hep.physics.vec.Hep3Vector;
 import java.util.List;
 
 /**
@@ -20,5 +21,6 @@
     public List<Polygon3D> getFaces();
     public List<LineSegment3D> getEdges();
     public List<Point3D> getVertices();
+    public List<Polygon3D> getFacesNormalTo(Hep3Vector normal);
     public int[] getHepRepVertexOrdering();
 }

GeomConverter/src/org/lcsim/detector/solids
Trd.java 1.6 -> 1.7
diff -u -r1.6 -r1.7
--- Trd.java	14 Nov 2007 19:34:51 -0000	1.6
+++ Trd.java	3 Dec 2007 23:23:30 -0000	1.7
@@ -15,10 +15,9 @@
  *
  * @author Jeremy McCormick
  * @author Tim Nelson (modified to use standard geometry objects and operations)
- * @version $Id: Trd.java,v 1.6 2007/11/14 19:34:51 tknelson Exp $
+ * @version $Id: Trd.java,v 1.7 2007/12/03 23:23:30 tknelson Exp $
  */
-public class Trd
-        extends AbstractSolid implements IPolyhedron
+public class Trd extends AbstractPolyhedron
 {
     
     private final static int[] _HEPREP_VERTEX_ORDERING = {2,3,1,0,6,7,5,4};
@@ -55,21 +54,6 @@
         return volume;
     }
     
-    public Inside inside(Hep3Vector p)
-    {
-        Point3D point = new Point3D(p);
-        
-        boolean inside = true;
-        for (Polygon3D face : getFaces())
-        {
-            if (GeomOp3D.intersects(point,face)) return Inside.SURFACE;
-            inside = inside && (GeomOp3D.distanceBetween(point,face.getPlane()) < 0);
-        }
-        
-        if (inside) return Inside.INSIDE;
-        else return Inside.OUTSIDE;
-    }
-    
     public double getXHalfLength1()
     {
         return dx1;

GeomConverter/src/org/lcsim/detector/solids
Trap.java 1.7 -> 1.8
diff -u -r1.7 -r1.8
--- Trap.java	14 Nov 2007 19:34:51 -0000	1.7
+++ Trap.java	3 Dec 2007 23:23:30 -0000	1.8
@@ -23,11 +23,10 @@
  *
  * @author Jeremy McCormick
  * @author Tim Nelson (modified to use standard geometry objects and operations)
- * @version $Id: Trap.java,v 1.7 2007/11/14 19:34:51 tknelson Exp $
+ * @version $Id: Trap.java,v 1.8 2007/12/03 23:23:30 tknelson Exp $
  */
 
-public class Trap
-        extends AbstractSolid implements IPolyhedron
+public class Trap extends AbstractPolyhedron
 {
     
     private final static int[] _HEPREP_VERTEX_ORDERING = {2,3,1,0,6,7,5,4};
@@ -169,21 +168,6 @@
         return cubicVolume;
     }
     
-    public Inside inside(Hep3Vector p)
-    {
-        Point3D point = new Point3D(p);
-        
-        boolean inside = true;
-        for (Polygon3D face : getFaces())
-        {
-            if (GeomOp3D.intersects(point,face)) return Inside.SURFACE;
-            inside = inside && (GeomOp3D.distanceBetween(point,face.getPlane()) < 0);
-        }
-        
-        if (inside) return Inside.INSIDE;
-        else return Inside.OUTSIDE;
-    }
-    
     // Implementation of IPolyhedron
     
     public int[] getHepRepVertexOrdering()

GeomConverter/src/org/lcsim/detector/solids
Point3D.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- Point3D.java	13 Nov 2007 21:04:50 -0000	1.1
+++ Point3D.java	3 Dec 2007 23:23:30 -0000	1.2
@@ -11,12 +11,13 @@
 
 import hep.physics.vec.BasicHep3Vector;
 import hep.physics.vec.Hep3Vector;
+import org.lcsim.detector.ITransform3D;
 
 /**
  *
  * @author tknelson
  */
-public class Point3D extends BasicHep3Vector
+public class Point3D extends BasicHep3Vector implements Transformable
 {
     
     /**
@@ -41,4 +42,14 @@
         return (Hep3Vector)this;
     }
     
+    public void transform(ITransform3D transform)
+    {
+        transform.transform(this);
+    }
+    
+    public Point3D transformed(ITransform3D transform)
+    {
+        return new Point3D(transform.transformed(this));
+    }
+    
 }

GeomConverter/src/org/lcsim/detector/solids
GeomOp3D.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- GeomOp3D.java	14 Nov 2007 21:48:48 -0000	1.2
+++ GeomOp3D.java	3 Dec 2007 23:23:30 -0000	1.3
@@ -32,6 +32,20 @@
     {
     }
     
+    // equivalence tests (objects are same within tolerances)
+    //=======================================================
+    public static boolean equals(Point3D point1, Point3D point2)
+    {
+        return intersects(point1, point2);
+    }
+    
+    public static boolean equals(Plane3D plane1, Plane3D plane2)
+    {
+        return ( parallel(plane1,plane2) &&
+                VecOp.dot(plane1.getNormal(),plane2.getNormal()) > 0 &&
+                plane1.getDistance() - plane2.getDistance() < DISTANCE_TOLERANCE);
+    }
+    
     // intersection tests
     //===================
     
@@ -399,7 +413,7 @@
      * @param   polygon
      * @return  closest distance between point and polygon
      */
-    public static double distanceBetween(Point3D point, Polygon3D polygon)
+    public static double distanceBetween(Point3D point, Polygon3D polygon)  // FIXME (there is a bug here ... getting negative values)
     {
         double distance = Double.POSITIVE_INFINITY;
         
@@ -457,13 +471,20 @@
         Hep3Vector start_diff = VecOp.sub(linesegment.getStartPoint(),line.getStartPoint());
         if (parallel(line,linesegment.getLine()))
         {
+//            System.out.println("Lines are parallel ");
             return VecOp.cross(start_diff,line.getDirection()).magnitude();
         }
         else
         {
-            double[] pca = linesPCA(line,linesegment);
+            double[] pca = linesPCA(line,linesegment);                         // FIXME (check usage here) (fixed?)
+            
+//            System.out.println("pca returns: "+ pca[0]+", "+pca[1]);
+            
             pca[1] = Math.max(0.0,pca[1]);
-            pca[1] = Math.min(1.0,pca[1]);
+            pca[1] = Math.min(linesegment.getLength(),pca[1]);
+            
+//            System.out.println("closest point on line is: "+line.getEndPoint(pca[0]));
+//            System.out.println("closest point on line segment is: "+linesegment.getLine().getEndPoint(pca[1]));
             
             return distanceBetween(line.getEndPoint(pca[0]),linesegment.getLine().getEndPoint(pca[1]));
         }
@@ -555,12 +576,13 @@
         }
         else
         {
-            double[] pca = linesPCA(linesegment1,linesegment2);
-            for (int iseg = 0; iseg < pca.length; iseg++)
-            {
-                pca[iseg] = Math.max(0.0,pca[iseg]);
-                pca[iseg] = Math.min(1.0,pca[iseg]);
-            }
+            double[] pca = linesPCA(linesegment1,linesegment2);                         // FIXME (check usage here) (fixed?)
+            
+            pca[0] = Math.max(0.0,pca[0]);
+            pca[0] = Math.min(linesegment1.getLength(),pca[0]);
+            
+            pca[1] = Math.max(0.0,pca[1]);
+            pca[1] = Math.min(linesegment2.getLength(),pca[1]);
             
             return distanceBetween(linesegment1.getEndPoint(pca[0]),linesegment2.getEndPoint(pca[1]));
         }
@@ -633,13 +655,13 @@
      *
      * @param   plane1
      * @param   plane2
-     * @return  closest distance between planes (signed in direction of normal to plane2)
+     * @return  closest distance between planes
      */
-    public static double distanceBetween(Plane3D plane1, Plane3D plane2)
+    public static double distanceBetween(Plane3D plane1, Plane3D plane2)  // FIXME!!!!!!!!!!!!!!
     {
-        if ( Math.abs(VecOp.dot(plane1.getNormal(),plane2.getNormal())) - 1.0 < ANGULAR_TOLERANCE )
+        if ( parallel(plane1,plane2) )
         {
-            return plane2.getDistance()-plane1.getDistance();
+            return plane2.getDistance()-VecOp.dot(plane1.getNormal(),plane2.getNormal())*plane1.getDistance();
         }
         else
         {
@@ -876,7 +898,7 @@
         }
         else
         {
-            double pca[] = linesPCA(line1,line2);
+            double pca[] = linesPCA(line1,line2);                         // FIXME (check usage here) (OK?)
             return new LineSegment3D(line1.getEndPoint(pca[0]),line2.getEndPoint(pca[1]));
         }
     }
@@ -890,16 +912,32 @@
      */
     public static LineSegment3D lineBetween(Line3D line, LineSegment3D linesegment)
     {
+        LineSegment3D line_between;
+        
         if (parallel(line,linesegment.getLine()))
         {
             throw new RuntimeException("Line and line segment are parallel!  Please check first with parallel(Line line,LineSegment linesegment)");
         }
         else
         {
-            double[] pca = linesPCA(line,linesegment);
-            pca[1] = Math.max(0.0,pca[1]);
-            pca[1] = Math.min(1.0,pca[1]);
-            return new LineSegment3D(line.getEndPoint(pca[0]),linesegment.getEndPoint(pca[1]));
+            double[] pca = linesPCA(line,linesegment);                         // FIXME (check usage here) (fixed?)
+            
+            if (pca[1]<0.0)
+            {
+                line_between = lineBetween(linesegment.getStartPoint(),line);
+                line_between.reverse();
+            }
+            else if (pca[1]>linesegment.getLength())
+            {
+                line_between = lineBetween(linesegment.getEndPoint(),line);
+                line_between.reverse();
+            }
+            else
+            {
+                line_between = new LineSegment3D(line.getEndPoint(pca[0]),linesegment.getEndPoint(pca[1]));
+            }
+           
+            return line_between;            
         }
     }
     
@@ -989,12 +1027,12 @@
         }
         else
         {
-            double[] pca = linesPCA(linesegment1,linesegment2);
-            for (int iseg = 0; iseg < pca.length; iseg++)
-            {
-                pca[iseg] = Math.max(0.0,pca[iseg]);
-                pca[iseg] = Math.min(1.0,pca[iseg]);
-            }
+            double[] pca = linesPCA(linesegment1,linesegment2);                         // FIXME (check usage here) (fixed?)
+            pca[0] = Math.max(0.0,pca[0]);
+            pca[0] = Math.min(linesegment1.getLength(),pca[0]);
+            
+            pca[1] = Math.max(0.0,pca[1]);
+            pca[1] = Math.min(linesegment2.getLength(),pca[1]);
             
             return new LineSegment3D(linesegment1.getEndPoint(pca[0]),linesegment2.getEndPoint(pca[1]));
         }
@@ -1207,7 +1245,6 @@
         return (parallel(line,plane) && intersects(line.getStartPoint(),plane));
     }
     
-    
     /**
      * collinearity test for a list of points
      *
@@ -1239,7 +1276,7 @@
      */
     public static boolean parallel(Line3D line1, Line3D line2)
     {
-        return Math.abs(VecOp.dot(line1.getDirection(),line2.getDirection()) - 1.0) < ANGULAR_TOLERANCE;
+        return VecOp.cross(line1.getDirection(),line2.getDirection()).magnitude() < ANGULAR_TOLERANCE;
     }
     
     /**
@@ -1251,7 +1288,7 @@
      */
     public static boolean parallel(Line3D line, Plane3D plane)
     {
-        return Math.abs(VecOp.dot(line.getDirection(),plane.getNormal()) - 0.0) < ANGULAR_TOLERANCE;
+        return Math.abs(VecOp.dot(line.getDirection(),plane.getNormal())) < ANGULAR_TOLERANCE;
     }
     
     /**
@@ -1263,9 +1300,24 @@
      */
     public static boolean parallel(Plane3D plane1, Plane3D plane2)
     {
-        return Math.abs(VecOp.dot(plane1.getNormal(),plane2.getNormal()) - 1.0) < ANGULAR_TOLERANCE;
+        return VecOp.cross(plane1.getNormal(),plane2.getNormal()).magnitude() < ANGULAR_TOLERANCE;
     }
     
+    /**
+     * test for plane normal to a vector
+     *
+     * @param   plane
+     * @param   unit_vector (unchecked)
+     * @return  true if plane normal to a unit vector within ANGULAR_TOLERANCE
+     */
+    public static boolean isNormal(Hep3Vector unit_vector, Plane3D plane)
+    {
+        if ( VecOp.cross(unit_vector,plane.getNormal()).magnitude() < ANGULAR_TOLERANCE )
+        {
+            return VecOp.dot(unit_vector,plane.getNormal()) > 0;
+        }
+        else return false;
+    }
     
 //========================================
 // Private methods

GeomConverter/src/org/lcsim/detector/solids
Plane3D.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- Plane3D.java	13 Nov 2007 21:04:50 -0000	1.1
+++ Plane3D.java	3 Dec 2007 23:23:30 -0000	1.2
@@ -12,12 +12,13 @@
 import hep.physics.vec.Hep3Vector;
 import hep.physics.vec.VecOp;
 import java.util.List;
+import org.lcsim.detector.ITransform3D;
 
 /**
  *
  * @author tknelson
  */
-public class Plane3D
+public class Plane3D implements Transformable
 {
     
     Hep3Vector _normal; // normal to plane
@@ -49,7 +50,7 @@
         
         // normal and distance
         _normal = VecOp.unit(VecOp.cross(v1,v2));
-        _distance = VecOp.dot(_normal,points.get(0));                
+        _distance = VecOp.dot(_normal,points.get(0));
     }
     
     public Hep3Vector getNormal()
@@ -73,5 +74,17 @@
         _distance *= -1;
     }
     
+    public void transform(ITransform3D transform)
+    {
+        Point3D closest_point = (Point3D)VecOp.mult(_distance,_normal);
+        _distance = closest_point.transformed(transform).magnitude();
+        transform.rotate(_normal);       
+    }
+    
+    public Plane3D transformed(ITransform3D transform)
+    {
+        Point3D closest_point = (Point3D)VecOp.mult(_distance,_normal);
+        return new Plane3D(transform.rotated(_normal),closest_point.transformed(transform).magnitude());
+    }
     
 }

GeomConverter/src/org/lcsim/detector/converter/compact
SiTrackerBarrelConverter.java 1.24 -> 1.25
diff -u -r1.24 -r1.25
--- SiTrackerBarrelConverter.java	14 Oct 2007 06:00:27 -0000	1.24
+++ SiTrackerBarrelConverter.java	3 Dec 2007 23:23:30 -0000	1.25
@@ -3,6 +3,8 @@
 import static java.lang.Math.cos;
 import static java.lang.Math.sin;
 import hep.physics.matrix.BasicMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.VecOp;
 
 import java.util.HashMap;
 import java.util.Iterator;
@@ -31,7 +33,10 @@
 import org.lcsim.detector.material.IMaterial;
 import org.lcsim.detector.material.MaterialStore;
 import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.solids.IPolyhedron;
 import org.lcsim.detector.solids.ISolid;
+import org.lcsim.detector.solids.Point3D;
+import org.lcsim.detector.solids.Polygon3D;
 import org.lcsim.detector.solids.Tube;
 import org.lcsim.detector.tracker.silicon.ChargeCarrier;
 import org.lcsim.detector.tracker.silicon.DeSiTrackerBarrel;
@@ -40,7 +45,6 @@
 import org.lcsim.detector.tracker.silicon.SiStrips;
 import org.lcsim.detector.tracker.silicon.SiTrackerBarrelLayer;
 import org.lcsim.detector.tracker.silicon.SiTrackerBarrelModule;
-import org.lcsim.detector.tracker.silicon.SiSensor.Orientation;
 import org.lcsim.geometry.compact.Detector;
 import org.lcsim.geometry.compact.Subdetector;
 import org.lcsim.geometry.subdetector.SiTrackerBarrel;
@@ -543,22 +547,55 @@
                         SiSensor sensor = new SiSensor(sensorId,sensorName,module,sensorPath,id);
                         sensor.setIdentifier(id);
                         
-                        ITranslation3D electrodes_position = new Translation3D(0.0,0.0,sensor.getThickness()/2);
-                        IRotation3D electrodes_rotation = new RotationPassiveXYZ(0.0,0.0,0.0);
+                        // Set up SiStrips for the sensors
+                        IPolyhedron sensor_solid = (IPolyhedron)sensor.getGeometry().getLogicalVolume().getSolid();
+                        
+                        // Bias the sensor
+                        Polygon3D p_side = sensor_solid.getFacesNormalTo(new BasicHep3Vector(0,0,1)).get(0);
+//                        System.out.println("Plane of p_side polygon has... ");
+//                        System.out.println("                        normal: "+p_side.getNormal());
+//                        System.out.println("                        distance: "+p_side.getDistance());
+//                        for (Point3D point : p_side.getClosedVertices())
+//                        {
+//                            System.out.println("      Vertex: "+point);
+//                        }
+                        
+                        
+                        Polygon3D n_side = sensor_solid.getFacesNormalTo(new BasicHep3Vector(0,0,-1)).get(0);
+//                        System.out.println("Plane of n_side polygon has... ");
+//                        System.out.println("                        normal: "+n_side.getNormal());
+//                        System.out.println("                        distance: "+n_side.getDistance());
+                        
+                        sensor.setBiasSurface(ChargeCarrier.HOLE,p_side);
+                        sensor.setBiasSurface(ChargeCarrier.ELECTRON,n_side);
+                        
+                        // Add sense and readout electrodes
+                        ITranslation3D electrodes_position = new Translation3D(VecOp.mult(-p_side.getDistance(),p_side.getNormal()));  // translate to p_side
+                        IRotation3D electrodes_rotation = new RotationPassiveXYZ(0.0,0.0,0.0);                                      // no rotation (global x-y = local x-y for axial strips)
                         Transform3D electrodes_transform = new Transform3D(electrodes_position, electrodes_rotation);
                         
-                        SiSensorElectrodes sense_electrodes = new SiStrips(3679,0.025,sensor,electrodes_transform);
-                        SiSensorElectrodes readout_electrodes = new SiStrips(1840,0.050,sensor,electrodes_transform);
-                        double[][] transfer_efficiencies = { {0.986,0.419} };
+                        // Free calculation of sense electrodes, readout electrodes determined thereon
+                        SiSensorElectrodes sense_electrodes = new SiStrips(ChargeCarrier.HOLE,0.025,sensor,electrodes_transform);
+                        SiSensorElectrodes readout_electrodes = new SiStrips(ChargeCarrier.HOLE,0.050,(sense_electrodes.getNCells()+1)/2,sensor,electrodes_transform);
                         
-                        sensor.setSenseElectrodes(ChargeCarrier.HOLE,sense_electrodes);
-                        sensor.setReadoutElectrodes(ChargeCarrier.HOLE,readout_electrodes);
+                        sensor.setSenseElectrodes(sense_electrodes);
+                        sensor.setReadoutElectrodes(readout_electrodes);
+                        
+                        double[][] transfer_efficiencies = { {0.986,0.419} };
                         sensor.setTransferEfficiencies(ChargeCarrier.HOLE,new BasicMatrix(transfer_efficiencies));
-                        sensor.setOrientation(Orientation.PSIDE_POSITIVE_Z);
-                        sensor.initialize();
                         
                         // Incremenet sensorID for double-sided.
                         ++sensorId;
+                        
+                        
+//                        SiSensorElectrodes sense_electrodes = new SiStrips(3679,0.025,sensor,electrodes_transform);
+//                        SiSensorElectrodes readout_electrodes = new SiStrips(1840,0.050,sensor,electrodes_transform);
+//
+//                        double[][] transfer_efficiencies = { {0.986,0.419} };
+//                        sensor.setSenseElectrodes(ChargeCarrier.HOLE,sense_electrodes);
+//                        sensor.setReadoutElectrodes(ChargeCarrier.HOLE,readout_electrodes);
+//                        sensor.setTransferEfficiencies(ChargeCarrier.HOLE,new BasicMatrix(transfer_efficiencies));
+                        
                     }
                 }
                 
CVSspam 0.2.8