Print

Print


Commit in lcsim/src/org/lcsim/contrib/onoprien/util/swim on MAIN
AbstractIntersection.java+63added 1.1
AbstractSurface.java+22added 1.1
AbstractTrajectory.java+68added 1.1
Helix.java+344added 1.1
Intersection.java+72added 1.1
IntersectionHelixZ.java+137added 1.1
IntersectionMultiple.java+69added 1.1
IntersectionNone.java+50added 1.1
IntersectionPeriodic.java+177added 1.1
IntersectionPeriodicBound.java+115added 1.1
IntersectionSingle.java+80added 1.1
Line.java+222added 1.1
ParCovMatrix.java+56added 1.1
ParVector.java+49added 1.1
Poca.java+59added 1.1
PocaXY.java+58added 1.1
Surface.java+18added 1.1
Trajectory.java+95added 1.1
ZCylinder.java+56added 1.1
ZDisk.java+57added 1.1
ZPlane.java+42added 1.1
package-info.java+6added 1.1
+1915
22 added files
Removed duplicate functionality, moved classes used by multiple packages to contrib.onoprien.util

lcsim/src/org/lcsim/contrib/onoprien/util/swim
AbstractIntersection.java added at 1.1
diff -N AbstractIntersection.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ AbstractIntersection.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,63 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import hep.physics.vec.Hep3Vector;
+import org.lcsim.units.clhep.SystemOfUnits;
+
+/**
+ * Abstract class that provides a skeletal implementation of the {@link Intersection}
+ * interface to minimize the effort required to implement this interface.
+ *
+ * @author D. Onoprienko
+ * @version $Id: AbstractIntersection.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+abstract public class AbstractIntersection implements Intersection {
+  
+  /**
+   * Precision with which the path length to an intersection is calculated.
+   * <i>Intersections closer to each other than this distance will be merged.
+   * <b>This behavior is currently disabled.</b></i>
+   * Default value: 0.1 micrometer.
+   */
+  public static double pathLengthTolerance = .1 * SystemOfUnits.micrometer;
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public AbstractIntersection() {
+  }
+  
+  public AbstractIntersection(Trajectory trajectory, Surface surface) {
+    _trajectory = trajectory;
+    _surface = surface;
+  }
+  
+// -- Stepping through intersection points :  ----------------------------------
+  
+  public void stepForward() {
+    step(1);
+  }
+  
+  public void stepBack() {
+    step(-1);
+  }
+
+// -- Trajectory parameters at the next intersection point :  ------------------
+  
+  public Hep3Vector getPoint() {
+    return _trajectory.getPoint(getPathLength());
+  }
+  
+  public Hep3Vector getDirection() {
+    return _trajectory.getDirection(getPathLength());
+  }
+
+// -- Access to intersecting objects :  ----------------------------------------
+  
+  public Trajectory getTrajectory() {return _trajectory;}
+  
+  public Surface getSurface() {return _surface;}
+
+// -- Private parts :  ---------------------------------------------------------
+  
+  protected Trajectory _trajectory;
+  protected Surface _surface;
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
AbstractSurface.java added at 1.1
diff -N AbstractSurface.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ AbstractSurface.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,22 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+/**
+ * Abstract class that provides a skeletal implementation of the {@link Surface}
+ * interface to minimize the effort required to implement this interface.
+ *
+ * @author D. Onoprienko
+ * @version $Id: AbstractSurface.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+abstract public class AbstractSurface implements Surface {
+  
+  /**
+   * Default implementation provided by this class throws <tt>UnsupportedOperationException</tt>
+   * with a diagnostic message. Concrete subclasses must override to return intersection 
+   * of the specified trajectory with this surface.
+   */
+  public Intersection intersect(Trajectory trajectory) {
+    throw new UnsupportedOperationException("No idea how to find intersection of " 
+      + this.getClass().getName() + " with " + trajectory.getClass().getName() + " - please implement");
+  }
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
AbstractTrajectory.java added at 1.1
diff -N AbstractTrajectory.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ AbstractTrajectory.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,68 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import hep.physics.vec.Hep3Vector;
+
+/**
+ * Abstract class that provides a skeletal implementation of the {@link Trajectory}
+ * interface to minimize the effort required to implement this interface.
+ * <p>
+ * This class also declares a few additional methods (<tt>getLengthToZPlane</tt>,
+ * <tt>getLengthToZCylinder</tt>) that can be implemented by concrete trajectory
+ * classes to facilitate finding intersections with surfaces. Default implementation
+ * provided by this class throws <tt>UnsupportedOperationException</tt>.
+ *
+ * @author D. Onoprienko
+ * @version $Id: AbstractTrajectory.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+abstract public class AbstractTrajectory implements Trajectory {
+  
+// -- Implementing Trajectory :  -----------------------------------------------
+
+  /**
+   * Returns the position of the origin of the trajectory.
+   * Implemented by forwarding the call to {@link #getPoint(double)} with zero argument.
+   * Concrete subclasses can override.
+   */
+  public Hep3Vector getPoint() {
+    return getPoint(0.);
+  }
+  
+  /**
+   * Returns direction unit vector at the origin.
+   * Implemented by forwarding the call to {@link #getDirection(double)} with zero argument.
+   * Concrete subclasses can override.
+   */
+  public Hep3Vector getDirection() {
+    return getDirection(0.);
+  }
+  
+  /**
+   * Returns intersection of this trajectory with the specified surface.
+   * Implemented by forwarding the call to {@link Surface#intersect(Surface)}.
+   * Concrete subclasses can override.
+   */
+  public Intersection intersect(Surface surface) {
+    return surface.intersect(this);
+  }
+  
+// -- Get trajectory parameters :  ---------------------------------------------
+
+  /**
+   * Returns the value of a parameter that describes the shape of this trajectory.
+   * The parameter is identified by enum constant that belongs to a particular representation.
+   */
+  public <T extends Enum<T>> double getParameter(T parameter) {
+    ParVector<T> v = getParameters(parameter.getClass());
+    return v.get(parameter);
+  }
+
+  /**
+   * Returns an element of a covariance matrix of parameters that describe the shape of this trajectory.
+   * The parameter is identified by enum constant that belongs to a particular representation.
+   */
+  public <T extends Enum<T>> double getCovElement(T parameter1, T parameter2) {
+    ParCovMatrix<T> m = getCovMatrix(parameter1.getClass());
+    return m.get(parameter1, parameter2);
+  }
+
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
Helix.java added at 1.1
diff -N Helix.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Helix.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,344 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import java.util.*;
+
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.util.ConstHep3Vector;
+
+/**
+ * Helical {@link Trajectory} with its axis parallel to Z.
+ *
+ * @author D. Onoprienko
+ * @version $Id: Helix.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class Helix extends AbstractTrajectory {
+  
+  /** 
+   * Emumeration of helix parameters in C-representation.
+   */
+  public enum CRep {
+    /** D0 (signed impact parameter in XY plane). */
+    D0,
+    /** Phi0. */
+    PHI0,
+    /**  Omega (signed curvature). */
+    OMEGA,
+    /** Z0. */
+    Z0,
+    /** Tangent of the dip angle. */
+    LAMBDA
+  }
+  
+  /** 
+   * Emumeration of helix parameters in W-representation.
+   */
+  public enum WRep {
+    /** X of the helix origin. */
+    X,
+    /** Y of the helix origin. */
+    Y,
+    /** Z of the helix origin. */
+    Z,
+    /** X component of the unit vector in the direction of the helix at its origin. */
+    DX,
+    /** Y component of the unit vector in the direction of the helix at its origin. */
+    DY,
+    /** Z component of the unit vector in the direction of the helix at its origin. */
+    DZ,
+    /** Amplitude of the transverse component of the unit vector in the direction of 
+     * the helix at its origin, devided by the helix radius. */
+    RO
+  }
+
+// -- Constructors :  ----------------------------------------------------------
+  
+  public Helix(Hep3Vector origin, Hep3Vector direction, double curvature) {
+    
+    if (origin instanceof ConstHep3Vector) {
+      _orig = (ConstHep3Vector) origin;
+    } else {
+      _orig = new ConstHep3Vector(origin);
+    }
+    
+    double mag = direction.magnitude();
+    _dir = new ConstHep3Vector(direction.x()/mag, direction.y()/mag, direction.z()/mag);
+    
+    _ro = - curvature * Math.hypot(_dir.x(), _dir.y());
+  }
+  
+  public Helix(ParVector<CRep> parameters, Hep3Vector referencePoint) {
+    _ref = new ConstHep3Vector(referencePoint);
+    _parC = new ParVector<CRep>(parameters);
+    repCtoW();
+  }
+
+  public Helix(ParVector<WRep> parameters) {
+    _orig = new ConstHep3Vector(parameters.get(WRep.X), parameters.get(WRep.Y), parameters.get(WRep.Z));
+    _dir = new ConstHep3Vector(parameters.get(WRep.DX), parameters.get(WRep.DY), parameters.get(WRep.DZ));
+    _ro = parameters.get(WRep.RO);
+  }
+  
+  public Helix(Helix helix) {
+    _orig = helix._orig;
+    _dir = helix._dir;
+    _ro = helix._ro;
+    _ref = helix._ref;
+  }
+
+// -- Get helix parameters :  --------------------------------------------------
+  
+  /** 
+   * Returns helix parameters in the requested representation.
+   *
+   * @param representation  Enum class that defines helix parameters representation.
+   *                        Currently either {@link CRep} or {@link WRep}.
+   */
+  public <T extends Enum<T>> ParVector<T> getParameters(Class<T> representation) {
+    if (CRep.class.isAssignableFrom(representation)) {
+      if (_parC == null) repWtoC();
+      return (ParVector) _parC;
+    } else if (WRep.class.isAssignableFrom(representation)) {
+      return new ParVector<T>(representation, _orig.x(),_orig.y(),_orig.z(),_dir.x(),_dir.y(),_dir.z(),_ro); 
+    } else {
+      throw new IllegalArgumentException();
+    }
+  }
+  
+  /** 
+   * Returns covariance matrix for helix parameters in the requested representation.
+   *
+   * @param representation  Enum class that defines helix parameters representation.
+   *                        Currently either {@link CRep} or {@link WRep}.
+   */
+  public <T extends Enum<T>> ParCovMatrix<T> getCovMatrix(Class<T> representation) {
+    throw new UnsupportedOperationException("Covariance matrix operations are not yet implemented");  // FIXME
+  }
+  
+  public double getZPeriod() {
+    return Math.abs(_dir.z()*TWOPI / _ro);
+  }
+  
+  public double getLengthPeriod() {
+    return Math.abs(TWOPI / _ro);
+  }
+
+  /**
+   * Returns reference point used to calculate helix parameters in C-representation.
+   */
+  public ConstHep3Vector getReferencePoint() {
+    return (_ref == null) ? _orig : _ref ;
+  }
+  
+  /** 
+   * Sets the reference point for C-representation of the helix parameters.
+   * Once set by this method, the reference point will not be affected by calls to {@link #swim}.
+   * Calling this method with <tt>null</tt> vector resets the reference point to
+   * the origin of this trajectory, and allows subsequent calls to {@link #swim} to
+   * modify it.
+   */
+  public void setReferencePoint(Hep3Vector referencePoint) {
+    if (referencePoint == null) {
+      _ref = null;
+    } else {
+      _ref = new ConstHep3Vector(referencePoint);
+    }
+    _parC = null;
+  }
+  
+// -- Position at the given point :  -------------------------------------------
+  
+  /**
+   * Returns the position of the origin of the trajectory.
+   */
+  public ConstHep3Vector getPoint() {
+    return _orig;
+  }
+
+  /**
+   * Returns the position at given path length along the trajectory.
+   */
+  public ConstHep3Vector getPoint(double pathLength) {
+    double nx = _dir.x()/_ro;
+    double ny = _dir.y()/_ro;
+    double x, y, z;
+    if (Double.isInfinite(nx) || Double.isInfinite(ny)) {
+      x = _orig.x() + _dir.x() * pathLength;
+      y = _orig.y() + _dir.y() * pathLength;
+    } else {
+      double sin = Math.sin(_ro*pathLength);
+      double cos1 = 1. - Math.cos(_ro*pathLength);
+      x = _orig.x() + nx * sin - ny * cos1;
+      y = _orig.y() + ny * sin + nx * cos1;
+    }
+    z = _orig.z() + _dir.z() * pathLength;
+    return new ConstHep3Vector(x,y,z);
+  }
+  
+// -- Direction at the given point :  ------------------------------------------
+  
+  /**
+   * Returns the direction unit vector at the origin.
+   */
+  public ConstHep3Vector getDirection() {
+    return _dir;
+  }
+  
+  /**
+   * Returns the direction unit vector at given path length along the trajectory.
+   */
+  public ConstHep3Vector getDirection(double pathLength) {
+    double sin = Math.sin(_ro*pathLength);
+    double cos = Math.cos(_ro*pathLength);
+    double dx = _dir.x() * cos - _dir.y() * sin;
+    double dy = _dir.y() * cos + _dir.x() * sin;
+    return new ConstHep3Vector(dx, dy, _dir.z());
+  }
+  
+// -- Intersections :  ---------------------------------------------------------
+  
+  public Intersection intersect(Surface surface) {
+    if (surface instanceof Poca) {
+      return intersect((Poca) surface);
+    } else if (surface instanceof PocaXY) {
+      return intersect((PocaXY) surface);
+    } else if (surface instanceof ZPlane) {
+      return intersect((ZPlane) surface);
+    } else if (surface instanceof ZCylinder) {
+      return intersect((ZCylinder) surface);
+    } else {
+      return surface.intersect(this);
+    }
+  }
+  
+  public Intersection intersect(Poca poca) {
+    Hep3Vector point = poca.getPoint();
+    double s = 0;   // FIXME
+    return new IntersectionSingle(s, this, poca);
+  }
+  
+  public Intersection intersect(PocaXY poca) {
+    Hep3Vector point = poca.getPoint();
+    double s = 0;   // FIXME
+    return new IntersectionSingle(s, this, poca);
+  }
+  
+  public Intersection intersect(ZPlane zPlane) {
+    double s = getLengthToZ(zPlane._z);
+    return (Double.isInfinite(s)) ? new IntersectionNone(this, zPlane) : new IntersectionSingle(s, this, zPlane) ;
+  }
+  
+  public Intersection intersect(ZDisk zDisk) {
+    double s = getLengthToZ(zDisk._z);
+    if (Double.isInfinite(s)) return new IntersectionNone(this, zDisk);
+    Hep3Vector pos = getPoint(s);
+    double x = pos.x();
+    double y = pos.y();
+    double r2 = x*x + y*y;
+    return (r2 > zDisk._rMin2 && r2 < zDisk._rMax2) ? new IntersectionSingle(s, this, zDisk) : new IntersectionNone(this, zDisk);
+  }
+  
+  public Intersection intersectZCylinder(ZCylinder zCylinder) { // FIXME
+    
+    double ro2 = _ro*_ro;
+    double a1 = 1. - _dir.z()*_dir.z() - _ro*(_orig.x()*_dir.y() + _orig.y()*_dir.x());
+    double a2 = _orig.x()*_dir.x() - _orig.y()*_dir.y();
+    double deltaR = _orig.x()*_orig.x() + _orig.y()*_orig.y() - zCylinder._r*zCylinder._r;
+    double a12 = a1*a1 + ro2*a2*a2;
+    double d = 4.*a2*a2 - 4.*deltaR*a1 - ro2*deltaR*deltaR;
+    if (d < 0.) return new IntersectionNone(this, zCylinder);
+    d = Math.sqrt(d);
+    
+    double cos1 = 1. - (ro2* (2.*a2*a2 - deltaR*a1 + a2*d) ) / (2.*a12);
+    double cos2 = 1. - (ro2* (2.*a2*a2 - deltaR*a1 - a2*d) ) / (2.*a12);
+    
+    double sin1 = (- _ro* (2.*a1*a2 + ro2*deltaR*a2 + a1*d)) / (2.*a12);
+    double sin2 = (- _ro* (2.*a1*a2 + ro2*deltaR*a2 - a1*d)) / (2.*a12);
+    
+    double s1 = getLength(sin1, cos1);
+    double s2 = getLength(sin2, cos2);
+    
+    double[] s;
+    if (Double.isNaN(s1)) {
+      if (Double.isNaN(s2)) {
+        return new IntersectionNone(this, zCylinder);
+      } else {
+        s = new double[]{s2};
+      }
+    } else {
+      if (Double.isNaN(s2) || s1==s2) {
+        s = new double[]{s1};
+      } else {
+        s = new double[]{s1,s2};
+      }
+    }
+    s1 = getLengthToZ(zCylinder.getMinZ());
+    s2 = getLengthToZ(zCylinder.getMaxZ());
+    return new IntersectionPeriodicBound(false, s1, s2, s, getLengthPeriod(), this, zCylinder);
+  }
+  
+// -- Modifying the trajectory :  ----------------------------------------------
+  
+  /** 
+   * Reverse the direction of the trajectory.
+   */
+  public void reverse() {
+    throw new UnsupportedOperationException();  // FIXME
+  }
+  
+  /**
+   * Moves the origin by the specified path length along the trajectory.
+   * Returns <tt>null</tt> if an attemt to move the origin by the requested length would place
+   * it beyond the boundary of this trajectory.
+   * Unless the reference point that defines C-representation of helix parameters has
+   * been set explicitly in a constructor or through a call to {@link #setReferencePoint(Hep3Vector)}
+   * method, the new origin also becomes the new reference point.
+   */
+  public boolean swim(double pathLength) {
+    throw new UnsupportedOperationException();  // FIXME
+  }
+  
+// -- Helper methods :  --------------------------------------------------------
+  
+  double getLength(double sin, double cos) {
+    double ros = Math.acos(cos);
+    if (sin < 0.) {
+      ros = - ros;
+    }
+    return ros/_ro;
+  }
+  
+  /** Returns path length to Z plane specified by the argument. */
+  double getLengthToZ(double z) {
+    return (z - _orig.z()) / _dir.z();
+  }
+  
+  private void repWtoC() {
+    throw new UnsupportedOperationException();  // FIXME
+  }
+  
+  private void repCtoW() {
+    throw new UnsupportedOperationException();  // FIXME
+  }
+
+// -- Private parts :  ---------------------------------------------------------
+  
+  // W-representation :
+  
+  ConstHep3Vector _orig;
+  ConstHep3Vector _dir;
+  double _ro;
+  SymmetricMatrix _covW;
+  
+  // C-representation :
+  
+  ConstHep3Vector _ref;    // Ref.point 
+  ParVector<CRep> _parC;   // D0, Phi0, Omega, Z0, Tan Lambda at XY POCA to ref.point
+  SymmetricMatrix _covC;
+  
+  static private final double TWOPI = 2. * Math.PI;
+
+  
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
Intersection.java added at 1.1
diff -N Intersection.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Intersection.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,72 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import java.util.NoSuchElementException;
+
+import hep.physics.vec.Hep3Vector;
+
+/**
+ * An intersection between a trajectory and a surface.
+ * <p>
+ * The intersection consists of zero or more intersection points ordered along the
+ * trajectory direction, and the <tt>Intersection</tt>
+ * object provides a way to iterate over them. Each instance of this class has a cursor 
+ * that is always positioned between two intersection points. In an <tt>Intersection</tt>
+ * consisting of <tt>n</tt> points, there are <tt>n+1</tt> valid cursor positions corresponding
+ * to <tt>n+1</tt> gaps between points, including the gap before the first point and the gap 
+ * after the last point. The cursor can be moved by calling <tt>step(int)</tt>, 
+ * <tt>stepForward()</tt>, and <tt>stepBack()</tt> methods. <tt>hasPrevious()</tt> and
+ * <tt>hasNext()</tt> methods check whether thare is an intersection point upstream and
+ * downstream from the cursor. <tt>getPathLength()</tt>, <tt>getPoint()</tt>, and 
+ * <tt>getDirection()</tt> methods return trajectory parameters at the point downstream
+ * from the cursor. An attempt to move the cursor beyond the ends of the point list, or to
+ * obtain trajectory parameters when the cursor is downstream from the last intersection point,
+ * throws {@link NoSuchElementException}.
+ * <p>
+ * When the <tt>Intersection</tt> is first created, its cursor is positioned before the first 
+ * intersection point downstream (along the trajectory direction) from the trajectory origin.
+ * Therefore, an immediate call to <tt>getPathLength()</tt> will return the path length to
+ * that point, or throw <tt>NoSuchElementException</tt> if there are no intersections downstream
+ * from the origin.
+ *
+ * @author D. Onoprienko
+ * @version $Id: Intersection.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public interface Intersection {
+  
+// -- Number of intersection points :  -----------------------------------------
+  
+  /**
+   * Returns the number of intersection points.
+   * If the number is infinite, returns <tt>-1</tt>.
+   */
+  public int size();
+  
+// -- Stepping through intersection points :  ----------------------------------
+  
+  public void step(int steps);
+  
+  public void stepForward();
+  
+  public void stepBack();
+  
+  public boolean hasNext();
+  
+  public boolean hasPrevious();
+  
+// -- Trajectory parameters at the next intersection point :  ------------------
+  
+  public double getPathLength();
+  
+  public Hep3Vector getPoint();
+  
+  public Hep3Vector getDirection();
+  
+// -- Access to intersecting objects :  ----------------------------------------
+  
+  /** Returns the trajectory this intersection belongs to. */
+  public Trajectory getTrajectory();
+  
+  /** Returns the surface this intersection belongs to. */
+  public Surface getSurface();
+
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
IntersectionHelixZ.java added at 1.1
diff -N IntersectionHelixZ.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IntersectionHelixZ.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,137 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import java.util.*;
+
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.util.ConstHep3Vector;
+
+/**
+ * Specialized implementation of {@link Intersection} interface suitable for use when
+ * locations of intersection points are periodic along the path length of the trajectory,
+ * possibly bounded to certain path length interval, and swimming the trajectory by a
+ * period changes only Z coordinate. This is typically used for intersecting {@Helix} with
+ * a surface parallel to Z axis.
+ *
+ * @author D. Onoprienko
+ * @version $Id: IntersectionHelixZ.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class IntersectionHelixZ extends IntersectionPeriodicBound {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  /**
+   * Fast constructor.
+   * Arrays passed to this constructor will be owned by this <tt>Intersection</tt> object.
+   * They are assumed to contain consecutive intersections in increasing path
+   * length order, though not necessarily corresponding to the allowed Z interval.
+   */
+  public IntersectionHelixZ(double zMin, double zMax,
+          double[] pathLengths, ConstHep3Vector[] points, ConstHep3Vector[] directions, 
+          Helix helix, Surface surface) {
+
+    super(helix, surface);
+    _path = pathLengths;
+    _pos = points;
+    _dir = directions;
+    init(zMin, zMax, helix);
+  }
+  
+  /**
+   * Slow constructor.
+   * Arrays passed to this constructor will be copied and re-ordered if necessary.
+   */
+  public IntersectionHelixZ(double zMin, double zMax,
+          double[] pathLengths, Hep3Vector[] points, Hep3Vector[] directions, 
+          Helix helix, Surface surface) {
+    
+    super(helix, surface);
+    
+    // Set periods in path length and Z
+    
+    _pathPeriod = helix.getLengthPeriod();
+    _zPeriod = helix.getZPeriod();
+    
+    // Move all solutions to withing period from _pathLength[0]
+    
+    int n = pathLengths.length;
+    double[] s = new double[n];
+    ConstHep3Vector[] pos = new ConstHep3Vector[n];
+    double sMin = pathLengths[0];
+    for (int i=1; i<n; i++) if (pathLengths[i] < sMin) sMin = pathLengths[i];
+    for (int i=0; i<n; i++) {
+      int period = (int) Math.floor((pathLengths[i]-sMin) / _pathPeriod);
+      Hep3Vector point = points[i];
+      if (period != 0) {
+        s[i] = pathLengths[i] - period * _pathPeriod;
+        pos[i] = new ConstHep3Vector(point.x(), point.y(), point.z() - period*_zPeriod);
+      } else {
+        s[i] = pathLengths[i];
+        pos[i] = (point instanceof ConstHep3Vector) ? (ConstHep3Vector)point : new ConstHep3Vector(point) ;
+      }
+    }
+    
+    // Order solutions
+    
+    SortedMap<Double, Integer> map = new TreeMap<Double, Integer>();
+    for (int i=0; i<n; i++) map.put(s[i], i);
+    _path = new double[n];
+    _pos = new ConstHep3Vector[n];
+    _dir = new ConstHep3Vector[n];
+    int newIndex = 0;
+    for (Map.Entry<Double, Integer> entry : map.entrySet()) {
+      double path = entry.getKey();
+      int oldIndex = entry.getValue();
+      _path[newIndex] = path;
+      _pos[newIndex] = pos[oldIndex];
+      Hep3Vector dir = directions[oldIndex];
+      _dir[newIndex] = (dir instanceof ConstHep3Vector) ? (ConstHep3Vector)dir : new ConstHep3Vector(dir);
+    }
+    
+    // Final initialization
+    
+    init(zMin, zMax, helix);
+  }
+  
+  protected void init(double zMin, double zMax, Helix helix) {
+    double sMin = helix.getLengthToZ(zMin);
+    double sMax = helix.getLengthToZ(zMax);
+    if (sMin > sMax) {
+      double temp = sMin;
+      sMin = sMax;
+      sMax = temp;
+    }
+    super.init(sMin, sMax);
+  }
+  
+// -- Trajectory parameters at the next intersection point :  ------------------
+  
+  public ConstHep3Vector getPoint() {
+    if (hasNext()) {
+      if (_index.iPeriod == 0) {
+        return _pos[_index.iNext];
+      } else {
+        return new ConstHep3Vector(_pos[_index.iNext].x(), 
+                                   _pos[_index.iNext].y(), 
+                                   _pos[_index.iNext].z() + _index.iPeriod * _zPeriod);
+      }
+    } else {
+      throw new NoSuchElementException();
+    }
+  }
+  
+  public ConstHep3Vector getDirection() {
+    if (hasNext()) {
+      return _dir[_index.iNext];
+    } else {
+      throw new NoSuchElementException();
+    }
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  ConstHep3Vector[] _dir;
+  ConstHep3Vector[] _pos;
+  double _zPeriod;
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
IntersectionMultiple.java added at 1.1
diff -N IntersectionMultiple.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IntersectionMultiple.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,69 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import java.util.*;
+
+/**
+ * An implementation of {@link Intersection} interface suitable for use when there is
+ * a finite number of intersection points, and their locations along the path length of 
+ * the trajectory need to be explicitly specified to the constructor.
+ *
+ * @author D. Onoprienko
+ * @version $Id: IntersectionMultiple.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class IntersectionMultiple extends AbstractIntersection {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  protected IntersectionMultiple() {
+    super();
+  }
+  
+  public IntersectionMultiple(double[] pathLengths, Trajectory trajectory, Surface surface) {
+    super(trajectory, surface);
+    _next = 0;
+    Arrays.sort(pathLengths);
+    _path = pathLengths;
+    while (_next < pathLengths.length && pathLengths[_next] <= 0.) _next++;
+  }
+  
+// -- Number of intersection points :  -----------------------------------------
+  
+  public int size() {return _path.length;}
+  
+// -- Stepping through intersection points :  ----------------------------------
+  
+  public void step(int steps) {
+    int i = _next + steps;
+    if (i < 0 || i > _path.length) {
+      throw new NoSuchElementException();
+    } else {
+      _next = i;
+    }
+  }
+  
+  public boolean hasNext() {
+    return _next < _path.length;
+  }
+  
+  public boolean hasPrevious() {
+    return _next > 0;
+  }
+
+  
+// -- Trajectory parameters at the next intersection point :  ------------------
+  
+  public double getPathLength() {
+    if (_next < _path.length) {
+      return _path[_next];
+    } else {
+      throw new NoSuchElementException();
+    }
+  }
+
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  protected double[] _path;
+  protected int _next;
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
IntersectionNone.java added at 1.1
diff -N IntersectionNone.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IntersectionNone.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,50 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import java.util.NoSuchElementException;
+
+import hep.physics.vec.Hep3Vector;
+
+/**
+ * An implementation of {@link Intersection} interface suitable for use when the trajectory
+ * and the surface have no intersection points.
+ *
+ * @author D. Onoprienko
+ * @version $Id: IntersectionNone.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class IntersectionNone extends AbstractIntersection {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public IntersectionNone() {
+    super();
+  }
+  
+  public IntersectionNone(Trajectory trajectory, Surface surface) {
+    super(trajectory, surface);
+  }
+  
+// -- Number of intersection points :  -----------------------------------------
+  
+  public int size() {return 0;}
+  
+// -- Stepping through intersection points :  ----------------------------------
+  
+  public void step(int steps) {throw new NoSuchElementException();}
+  
+  public void stepForward() {throw new NoSuchElementException();}
+  
+  public void stepBack() {throw new NoSuchElementException();}
+  
+  public boolean hasNext() {return false;}
+  
+  public boolean hasPrevious() {return false;}
+  
+// -- Trajectory parameters at the next intersection point :  ------------------
+  
+  public double getPathLength() {throw new NoSuchElementException();}
+  
+  public Hep3Vector getPoint() {throw new NoSuchElementException();}
+  
+  public Hep3Vector getDirection() {throw new NoSuchElementException();}
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
IntersectionPeriodic.java added at 1.1
diff -N IntersectionPeriodic.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IntersectionPeriodic.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,177 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import java.util.*;
+
+/**
+ * Specialized implementation of {@link Intersection} interface suitable for use when
+ * locations of intersection points are periodic along the path length of the trajectory.
+ *
+ * @author D. Onoprienko
+ * @version $Id: IntersectionPeriodic.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class IntersectionPeriodic extends AbstractIntersection {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  /** Default constructor for use by superclasses. */
+  protected IntersectionPeriodic() {
+    super();
+  }
+  
+  /** Empty constructor for use by superclasses. */
+  protected IntersectionPeriodic(Trajectory trajectory, Surface surface) {
+    super(trajectory, surface);
+  }
+  
+  /**
+   * Main constructor.
+   *
+   * @param fast  If <tt>true</tt>, the <tt>pathLengths</tt> array will be used "as is" 
+   *              and owned by this <tt>Intersection</tt> object. If <tt>false</tt>, the 
+   *              array will be copied, ordered, and its elements will be shifted to make 
+   *              sure they do not differ by more then <tt>period</tt>.
+   * @param pathLengths An array containing a set of unique path lengths to intersection points
+   *                    (those that cannot be obtained from each other by shifting by several periods).
+   */
+  public IntersectionPeriodic(boolean fast, double[] pathLengths, double period, Trajectory trajectory, Surface surface) {
+    super(trajectory, surface);
+    _pathPeriod = period;
+    if (fast) {
+      _path = pathLengths;
+    } else {
+      int n = pathLengths.length;
+      _path = new double[n];
+      double sMin = pathLengths[0];
+      for (int i=0; i<n; i++) {
+        _path[i] = pathLengths[i];
+        if (pathLengths[i] < sMin) sMin = pathLengths[i];
+      }
+      for (int i=0; i<n; i++) {
+        int iPeriod = (int) Math.floor((_path[i]-sMin) / _pathPeriod);
+        _path[i] = _path[i] - iPeriod * _pathPeriod;
+      }
+      Arrays.sort(_path);
+    }
+    _index = new Index();
+    _index.iSetBeforeGT(0.);
+  }
+  
+// -- Number of intersection points :  -----------------------------------------
+  
+  public int size() {return -1;}
+  
+// -- Stepping through intersection points :  ----------------------------------
+  
+  public void step(int steps) {
+    _index.iStep(steps);
+  }
+  
+  public void stepForward() {
+    _index.iStepForward();
+  }
+  
+  public void stepBack() {
+    _index.iStepBack();
+  }
+  
+  public boolean hasNext() {return true;}
+  
+  public boolean hasPrevious() {return true;}
+  
+// -- Trajectory parameters at the next intersection point :  ------------------
+  
+  public double getPathLength() {
+    return _index.iGetPathLength();
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  protected double[] _path;
+  protected double _pathPeriod;
+  protected Index _index;
+  
+// -- Index class :  -----------------------------------------------------------
+
+  /** Class that represents a pointer to a particular intersection point. */
+  protected class Index implements Comparable<Index> {
+    
+    Index() {
+      iPeriod = 0;
+      iNext = 0;      
+    }
+    
+    Index(int period, int next) {
+      iPeriod = period;
+      iNext = next;
+    }
+    
+    Index(Index index) {
+      iPeriod = index.iPeriod;
+      iNext = index.iNext;
+    }
+    
+    public void iStep(int steps) {
+      int i = iNext + steps;
+      iPeriod += i / _path.length;
+      iNext = i % _path.length;
+      if (iNext < 0) {
+        iNext += _path.length;
+        iPeriod--;
+      }
+    }
+    
+    public void iStepForward() {
+      if (++iNext == _path.length) {
+        iNext = 0;
+        iPeriod++;
+      }
+    }
+    
+    public void iStepBack() {
+      if (--iNext < 0) {
+        iNext = _path.length - 1;
+        iPeriod--;
+      }
+    }
+    
+    public double iGetPathLength() {
+      return _path[iNext] + iPeriod * _pathPeriod;
+    }
+    
+    public int iSubtract(Index index) {
+      return (iPeriod - index.iPeriod) * _path.length + (iNext - index.iNext);
+    }
+    
+    public int compareTo(Index index) {
+      return (iPeriod == index.iPeriod) ? (iNext - index.iNext) : (iPeriod - index.iPeriod) ;
+    }
+    
+    /**
+     * Sets the index to point to the first intersection point with the path length 
+     * greater than the one specified by the argument.
+     */
+    public void iSetBeforeGT(double s) {
+      iPeriod = (int) (Math.ceil( (s - _path[_path.length-1]) / _pathPeriod) );
+      iNext = 0;
+      while (iGetPathLength() <= s) {
+        iStepForward();
+      }
+    }
+
+    /**
+     * Sets the index to point to the first intersection point with the path length 
+     * greater or equal to the one specified by the argument.
+     */
+    public void iSetBeforeGE(double s) {
+      iPeriod = (int) (Math.ceil( (s - _path[_path.length-1]) / _pathPeriod) );
+      iNext = 0;
+      while (iGetPathLength() < s) {
+        iStepForward();
+      }
+    }
+    
+    int iPeriod;
+    int iNext;
+  }
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
IntersectionPeriodicBound.java added at 1.1
diff -N IntersectionPeriodicBound.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IntersectionPeriodicBound.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,115 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import java.util.*;
+
+/**
+ * Specialized implementation of {@link Intersection} interface suitable for use when
+ * locations of intersection points are periodic along the path length of the trajectory,
+ * but bounded to certain path length interval.
+ *
+ * @author D. Onoprienko
+ * @version $Id: IntersectionPeriodicBound.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class IntersectionPeriodicBound extends IntersectionPeriodic {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  /** Default constructor for use by superclasses. */
+  protected IntersectionPeriodicBound() {
+    super();
+  }
+  
+  /** Empty constructor for use by superclasses. */
+  protected IntersectionPeriodicBound(Trajectory trajectory, Surface surface) {
+    super(trajectory, surface);
+  }
+  
+  /**
+   * Main constructor.
+   *
+   * @param fast  If <tt>true</tt>, the <tt>pathLengths</tt> array will be used "as is" 
+   *              and owned by this <tt>Intersection</tt> object. If <tt>false</tt>, the 
+   *              array will be copied, ordered, and its elements will be shifted to make 
+   *              sure they do not differ by more then <tt>period</tt>. The order of bounds will
+   *              also be checked.
+   * @param pathLengths An array containing a set of unique path lengths to intersection points
+   *                    (those that cannot be obtained from each other by shifting by several periods).
+   */
+  public IntersectionPeriodicBound(boolean fast, double pathLengthMin, double pathLengthMax, 
+          double[] pathLengths, double period, Trajectory trajectory, Surface surface) {
+    super(fast, pathLengths, period, trajectory, surface);
+    if (pathLengthMin < pathLengthMax) {
+      init(pathLengthMin, pathLengthMax);
+    } else {
+      init(pathLengthMax, pathLengthMin);
+    }
+  }
+  
+  protected void init(double pathLengthMin, double pathLengthMax) {
+    _min = new Index();
+    _min.iSetBeforeGT(pathLengthMin);
+    _max = new Index();
+    _max.iSetBeforeGE(pathLengthMax);
+    if (_index.compareTo(_min) < 0) {
+      _index = new Index(_min);
+    } else if (_index.compareTo(_max) > 0) {
+      _index = new Index(_max);
+    }    
+  }
+  
+// -- Number of intersection points :  -----------------------------------------
+  
+  public int size() {
+    return _max.iSubtract(_min);
+  }
+  
+// -- Stepping through intersection points :  ----------------------------------
+  
+  public void step(int steps) {
+    Index newIndex = new Index(_index);
+    newIndex.iStep(steps);
+    if (newIndex.compareTo(_min) < 0 || newIndex.compareTo(_max) > 0) {
+      throw new NoSuchElementException();
+    } else {
+      _index = newIndex;
+    }
+  }
+  
+  public void stepForward() {
+    if (hasNext()) {
+      _index.iStepForward();
+    } else {
+      throw new NoSuchElementException();
+    }
+  }
+  
+  public void stepBack() {
+    if (hasPrevious()) {
+      _index.iStepBack();
+    } else {
+      throw new NoSuchElementException();
+    }
+  }
+  
+  public boolean hasNext() {
+    return _index.compareTo(_max) < 0 ;
+  }
+  
+  public boolean hasPrevious() {
+    return _index.compareTo(_min) > 0 ;
+  }
+  
+// -- Trajectory parameters at the next intersection point :  ------------------
+  
+  public double getPathLength() {
+    if (hasNext()) {
+      return _index.iGetPathLength();
+    } else {
+      throw new NoSuchElementException();
+    }
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  protected Index _min, _max;
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
IntersectionSingle.java added at 1.1
diff -N IntersectionSingle.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ IntersectionSingle.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,80 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import java.util.NoSuchElementException;
+
+/**
+ * An implementation of {@link Intersection} interface suitable for use when there
+ * is a single intersection point.
+ *
+ * @author D. Onoprienko
+ * @version $Id: IntersectionSingle.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class IntersectionSingle extends AbstractIntersection {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  protected IntersectionSingle() {
+    super();
+  }
+  
+  public IntersectionSingle(double pathLength, Trajectory trajectory, Surface surface) {
+    super(trajectory, surface);
+    _path = pathLength;
+    _hasNext = pathLength > 0.;
+  }
+
+  
+// -- Number of intersection points :  -----------------------------------------
+  
+  public int size() {return 1;}
+
+  
+// -- Stepping through intersection points :  ----------------------------------
+  
+  public void step(int steps) {
+    if (steps == 1) {
+      stepForward();
+    } else if (steps == -1) {
+      stepBack();
+    } else if (steps != 0) {
+      throw new NoSuchElementException();
+    }
+  }
+  
+  public void stepForward() {
+    if (_hasNext) {
+      _hasNext = false;
+    } else {
+      throw new NoSuchElementException();
+    }
+  }
+  
+  public void stepBack() {
+    if (_hasNext) {
+      throw new NoSuchElementException();
+    } else {
+      _hasNext = true;
+    }
+  }
+  
+  public boolean hasNext() {return _hasNext;}
+  
+  public boolean hasPrevious() {return ! _hasNext;}
+
+  
+// -- Trajectory parameters at the next intersection point :  ------------------
+  
+  public double getPathLength() {
+    if (_hasNext) {
+      return _path;
+    } else {
+      throw new NoSuchElementException();
+    }
+  }
+
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  protected double _path;
+  protected boolean _hasNext;
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
Line.java added at 1.1
diff -N Line.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Line.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,222 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.util.ConstHep3Vector;
+
+/**
+ * Straight line {@link Trajectory}.
+ *
+ * @author D. Onoprienko
+ * @version $Id: Line.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class Line extends AbstractTrajectory {
+  
+  /** 
+   * Emumeration of line parameters in W-representation.
+   */
+  public enum WRep {
+    /** X of the line origin. */
+    X,
+    /** Y of the line origin. */
+    Y,
+    /** Z of the line origin. */
+    Z,
+    /** X component of the unit vector in the direction of the line at its origin. */
+    DX,
+    /** Y component of the unit vector in the direction of the line at its origin. */
+    DY,
+    /** Z component of the unit vector in the direction of the line at its origin. */
+    DZ
+  }
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  /**
+   * Construct from origin and direction.
+   * The direction vector does not have to be normalized.
+   */
+  public Line(Hep3Vector origin, Hep3Vector direction) {
+    _orig = new ConstHep3Vector(origin);
+    double mag = direction.magnitude();
+    _dir = new ConstHep3Vector(direction.x()/mag, direction.y()/mag, direction.z()/mag);
+  }
+  
+  /**
+   * Construct from origin and direction.
+   * The direction vector does not have to be normalized.
+   */
+  public Line(ConstHep3Vector origin, Hep3Vector direction) {
+    _orig = origin;
+    double mag = direction.magnitude();
+    _dir = new ConstHep3Vector(direction.x()/mag, direction.y()/mag, direction.z()/mag);
+  }
+  
+  /**
+   * Copy constructor.
+   */
+  public Line(Line line) {
+    _orig = line._orig;
+    _dir = line._dir;
+  }
+  
+// -- Get line parameters :  ---------------------------------------------------
+  
+  /** 
+   * Returns helix parameters in the requested representation.
+   *
+   * @param representation  Enum class that defines helix parameters representation.
+   *                        Currently either {@link CRep} or {@link WRep}.
+   */
+  public <T extends Enum<T>> ParVector<T> getParameters(Class<T> representation) {
+    if (WRep.class.isAssignableFrom(representation)) {
+      return new ParVector<T>(representation, _orig.x(),_orig.y(),_orig.z(),_dir.x(),_dir.y(),_dir.z()); 
+    } else {
+      throw new IllegalArgumentException();
+    }
+  }
+  
+  /** 
+   * Returns covariance matrix for helix parameters in the requested representation.
+   *
+   * @param representation  Enum class that defines helix parameters representation.
+   *                        Currently either {@link CRep} or {@link WRep}.
+   */
+  public <T extends Enum<T>> ParCovMatrix<T> getCovMatrix(Class<T> representation) {
+    throw new UnsupportedOperationException("Covariance matrix operations are not yet implemented");  // FIXME
+  }
+  
+// -- Position at the given point :  -------------------------------------------
+  
+  /**
+   * Returns the position of the origin of the trajectory.
+   */
+  public Hep3Vector getPoint() {
+    return _orig;
+  }
+
+  /**
+   * Returns the position at given path length along the trajectory.
+   */
+  public Hep3Vector getPoint(double pathLength) {
+    return new ConstHep3Vector(_orig.x() + pathLength * _dir.x(), 
+                               _orig.y() + pathLength * _dir.y(),
+                               _orig.z() + pathLength * _dir.z());
+  }
+  
+// -- Direction at the given point :  ------------------------------------------
+  
+  /**
+   * Returns the direction unit vector at the origin.
+   */
+  public Hep3Vector getDirection() {
+    return _dir;
+  }
+  
+  /**
+   * Returns the direction unit vector at given path length along the trajectory.
+   */
+  public Hep3Vector getDirection(double pathLength) {
+    return _dir;
+  }
+  
+// -- Modifying the trajectory :  ----------------------------------------------
+  
+  /** 
+   * Reverse the direction of the trajectory.
+   */
+  public void reverse() {
+    _dir = new ConstHep3Vector(- _dir.x(), - _dir.y(), - _dir.z());
+  }
+  
+  /**
+   * Move the origin by the given path length along the trajectory.
+   */
+  public boolean swim(double pathLength) {
+    _orig = new ConstHep3Vector(_orig.x() + pathLength * _dir.x(),
+                                  _orig.y() + pathLength * _dir.y(),
+                                  _orig.z() + pathLength * _dir.z());
+    return true;
+  }
+  
+// -- Intersections :  ---------------------------------------------------------
+  
+  public Intersection intersect(Surface surface) {
+    if (surface instanceof Poca) {
+      return intersect((Poca) surface);
+    } else if (surface instanceof PocaXY) {
+      return intersect((PocaXY) surface);
+    } else if (surface instanceof ZPlane) {
+      return intersect((ZPlane) surface);
+    } else if (surface instanceof ZCylinder) {
+      return intersect((ZCylinder) surface);
+    } else {
+      return surface.intersect(this);
+    }
+  }
+  
+  public Intersection intersect(Poca poca) {
+    Hep3Vector point = poca.getPoint();
+    double s = (point.x()-_orig.x())*_dir.x() + (point.y()-_orig.y())*_dir.y() + (point.z()-_orig.z())*_dir.z();
+    return new IntersectionSingle(s, this, poca);
+  }
+  
+  public Intersection intersect(PocaXY poca) {
+    ConstHep3Vector point = poca.getPoint();
+    double s = ((point.x()-_orig.x())*_dir.x() + (point.y()-_orig.y())*_dir.y()) / (_dir.x()*_dir.x() + _dir.y()*_dir.y());
+    if (Double.isInfinite(s)) s = (point.z() - _orig.z()) / _dir.z();
+    return new IntersectionSingle(s, this, poca) ;
+  }
+  
+  public Intersection intersect(ZPlane zPlane) {
+    double s = (zPlane._z - _orig.z()) / _dir.z();
+    return (Double.isInfinite(s)) ? new IntersectionNone(this, zPlane) : new IntersectionSingle(s, this, zPlane) ;
+  }
+  
+  public Intersection intersect(ZDisk zDisk) {
+    double s = (zDisk._z - _orig.z()) / _dir.z();
+    if (Double.isInfinite(s)) return new IntersectionNone(this, zDisk);
+    Hep3Vector pos = getPoint(s);
+    double x = pos.x();
+    double y = pos.y();
+    double r2 = x*x + y*y;
+    return (r2 > zDisk._rMin2 && r2 < zDisk._rMax2) ? new IntersectionSingle(s, this, zDisk) : new IntersectionNone(this, zDisk);
+  }
+  
+  public Intersection intersectZCylinder(ZCylinder zCylinder) {
+    double d2 = _dir.x() * _dir.x() + _dir.y() * _dir.y();
+    if (d2 == 0.) return new IntersectionNone(this, zCylinder);
+    double b = _orig.x() * _dir.x() + _orig.y() * _dir.y();
+    double discr = b*b - d2 * (_orig.x() * _orig.x() + _orig.y() * _orig.y() - zCylinder._r * zCylinder._r);
+    if ((discr < 0.) || Double.isNaN(discr) || Double.isInfinite(discr)) {
+      return new IntersectionNone(this, zCylinder);
+    } else {
+      discr = Math.sqrt(discr);
+      double[] ss = new double[] { (-b - discr) / d2, (-b + discr) / d2};
+      boolean[] good = new boolean[2];
+      for (int i=0; i<2; i++) {
+        double s = ss[i];
+        if (Double.isInfinite(s)) {
+          good[i] = false;
+        } else {
+          double z = getPoint(s).z();
+          good[i] = z > zCylinder._zMin && z < zCylinder._zMax;
+        }
+      }
+      if (good[0] && good[1]) {
+        return new IntersectionMultiple(ss, this, zCylinder);
+      } else if (! (good[0] || good[1])) {
+        return new IntersectionNone(this, zCylinder);
+      } else {
+        double s = (good[0] ? ss[0] : ss[1]);
+        return new IntersectionSingle(s, this, zCylinder);
+      }
+    }
+  }
+
+// -- Private parts :  ---------------------------------------------------------
+  
+  private ConstHep3Vector _orig;
+  private ConstHep3Vector _dir;
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
ParCovMatrix.java added at 1.1
diff -N ParCovMatrix.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ParCovMatrix.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,56 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import hep.physics.matrix.SymmetricMatrix;
+
+/**
+ * An instance of this class represents a covariance matrix of parameters that define a trajectory,
+ * in a particular representation. The representation is described by enum that contains
+ * constants identifying the parameters (for example, {@link Helix} parameters can be
+ * described in {@link Helix.CRep} and {@link Helix.WRep} representations).
+ *
+ * @author D. Onoprienko
+ * @version $Id: ParCovMatrix.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class ParCovMatrix<T extends Enum<T>> extends SymmetricMatrix {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public ParCovMatrix(Class<T> representation) {
+    super(representation.getEnumConstants().length);
+    _rep = representation;
+  }
+  
+  public ParCovMatrix(Class<T> representation, double[] initialValues, boolean isLower) {
+    super(representation.getEnumConstants().length, initialValues, isLower);
+    _rep = representation;
+  }
+  
+  public ParCovMatrix(ParCovMatrix<T> covMatrix) {
+    super(covMatrix);
+    _rep = covMatrix._rep;
+  }
+  
+// -- Getters :  ---------------------------------------------------------------
+  
+  public double get(T parameter) {
+    return diagonal(parameter.ordinal());
+  }
+  
+  public double get(T parameter1, T parameter2) {
+    return e(parameter1.ordinal(), parameter2.ordinal());
+  }
+  
+// -- Setters :  ---------------------------------------------------------------
+  
+  public void set(T parameter, double value) {
+    setElement(parameter.ordinal(), parameter.ordinal(), value);
+  }
+  
+  public void set(T parameter1, T parameter2, double value) {
+    setElement(parameter1.ordinal(), parameter2.ordinal(), value);
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+
+  private Class<T> _rep;
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
ParVector.java added at 1.1
diff -N ParVector.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ParVector.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,49 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+/**
+ * An instance of this class represents a vector of parameters that define a trajectory,
+ * in a particular representation. The representation is described by enum that contains
+ * constants identifying the parameters (for example, {@link Helix} parameters can be
+ * described in {@link Helix.CRep} and {@link Helix.WRep} representations).
+ *
+ * @author D. Onoprienko
+ * @version $Id: ParVector.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class ParVector<T extends Enum<T>> {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public ParVector(Class<T> representation) {
+    _rep = representation;
+    _pars = new double[_rep.getEnumConstants().length];
+  }
+
+  public ParVector(Class<T> representation, double... values) {
+    _rep = representation;
+    int n = _rep.getEnumConstants().length;
+    if (values.length != n) throw new IllegalArgumentException();
+    _pars = values;
+  }
+
+  public ParVector(ParVector parVector) {
+    _rep = parVector._rep;
+    _pars = (double[]) parVector._pars.clone();
+  }
+  
+// -- Getters :  ---------------------------------------------------------------
+  
+  public double get(T parameter) {
+    return _pars[parameter.ordinal()];
+  }
+  
+// -- Setters :  ---------------------------------------------------------------
+  
+  public void set(T parameter, double value) {
+    _pars[parameter.ordinal()] = value;
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  private Class<T> _rep;
+  private double[] _pars;
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
Poca.java added at 1.1
diff -N Poca.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Poca.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,59 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.util.ConstHep3Vector;
+
+/**
+ * {@link Surface} that represents point of closest approach to the point supplied to
+ * its constructor.
+ *
+ * @author D. Onoprienko
+ * @version $Id: Poca.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class Poca extends AbstractSurface {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public Poca(Hep3Vector point) {
+    if (point instanceof ConstHep3Vector) {
+      _point = (ConstHep3Vector) point;
+    } else {
+      _point = new ConstHep3Vector(point.v());
+    }
+  }
+  
+  public Poca(double[] point) {
+    _point = new ConstHep3Vector(point);
+  }
+  
+  public Poca(double x, double y, double z) {
+    _point = new ConstHep3Vector(x,y,z);
+  }
+  
+// -- Getters :  ---------------------------------------------------------------
+  
+  public ConstHep3Vector getPoint() {
+    return _point;
+  }
+  
+// -- Implementing Surface :  --------------------------------------------------
+  
+  /**
+   * Returns intersection of the specified trajectory with this surface.
+   */
+  public Intersection intersect(Trajectory trajectory) {
+    if (trajectory instanceof Line) {
+      return ((Line)trajectory).intersect(this);
+    } else if (trajectory instanceof Helix) {
+      return ((Helix)trajectory).intersect(this);
+    } else {
+      return super.intersect(trajectory);
+    }
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  private ConstHep3Vector _point;
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
PocaXY.java added at 1.1
diff -N PocaXY.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ PocaXY.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,58 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.contrib.onoprien.util.ConstHep3Vector;
+
+/**
+ * {@link Surface} that represents point of closest approach in XY plane to the 
+ * point supplied to its constructor.
+ *
+ * @author D. Onoprienko
+ * @version $Id: PocaXY.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class PocaXY extends AbstractSurface {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public PocaXY(Hep3Vector point) {
+    if (point instanceof ConstHep3Vector) {
+      _point = (ConstHep3Vector) point;
+    } else {
+      _point = new ConstHep3Vector(point.v());
+    }
+  }
+  
+  public PocaXY(double[] point) {
+    _point = new ConstHep3Vector(point);
+  }
+  
+  public PocaXY(double x, double y, double z) {
+    _point = new ConstHep3Vector(x,y,z);
+  }
+  
+// -- Getters :  ---------------------------------------------------------------
+  
+  public ConstHep3Vector getPoint() {
+    return _point;
+  }
+  
+// -- Implementing Surface :  --------------------------------------------------
+  
+  /**
+   * Returns intersection of the specified trajectory with this surface.
+   */
+  public Intersection intersect(Trajectory trajectory) {
+    if (trajectory instanceof Line) {
+      return ((Line)trajectory).intersect(this);
+    } else if (trajectory instanceof Helix) {
+      return ((Helix)trajectory).intersect(this);
+    } else {
+      return super.intersect(trajectory);
+    }
+  }
+
+// -- Private parts :  ---------------------------------------------------------
+  
+  private ConstHep3Vector _point;
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
Surface.java added at 1.1
diff -N Surface.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Surface.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,18 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import hep.physics.vec.Hep3Vector;
+
+/**
+ * A surface in space.
+ *
+ * @author D. Onoprienko
+ * @version $Id: Surface.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public interface Surface {
+  
+  /**
+   * Returns intersection of the specified trajectory with this surface.
+   */
+  public Intersection intersect(Trajectory trajectory);
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
Trajectory.java added at 1.1
diff -N Trajectory.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Trajectory.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,95 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import hep.physics.vec.Hep3Vector;
+
+/**
+ * A trajectory in space.
+ * Trajectory is characterized by its shape, origin, and direction.
+ *
+ * @author D. Onoprienko
+ * @version $Id: Trajectory.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public interface Trajectory {
+  
+// -- Position and direction at the given point :  -----------------------------
+  
+  /**
+   * Returns the position of the origin of the trajectory.
+   */
+  public Hep3Vector getPoint();
+
+  /**
+   * Returns the position at given path length along the trajectory.
+   * Returns <tt>null</tt> if the requested point does not exist on this trajectory.
+   */
+  public Hep3Vector getPoint(double pathLength);
+
+  /**
+   * Returns direction unit vector at the origin.
+   */
+  public Hep3Vector getDirection();
+  
+  /**
+   * Returns direction unit vector at given path length along the trajectory.
+   * Returns <tt>null</tt> if the requested point does not exist on this trajectory.
+   */
+  public Hep3Vector getDirection(double pathLength);
+  
+// -- Get trajectory parameters :  ---------------------------------------------
+  
+  /**
+   * Returns a vector of parameters that define the shape of this trajectory.
+   * Throws <tt>IllegalArgumentException</tt> if the requested representation is not
+   * applicable to this concrete trajectory class.
+   *
+   * @param representation Enum that defines a particular representation of the  trajectory
+   *                       parameters. For example, {@link Helix} parameters can be
+   *                       returned in {@link Helix.CRep} and {@link Helix.WRep} representations.
+   */
+  public <T extends Enum<T>> ParVector<T> getParameters(Class<T> representation);
+
+  /**
+   * Returns the value of a parameter that describes the shape of this trajectory.
+   * The parameter is identified by enum constant that belongs to a particular representation.
+   */
+  public <T extends Enum<T>> double getParameter(T parameter);
+  
+  /**
+   * Returns a covariance matrix of parameters that define the shape of this trajectory.
+   * Throws <tt>IllegalArgumentException</tt> if the requested representation is not
+   * applicable to this concrete trajectory class.
+   *
+   * @param representation Enum that defines a particular representation of the  trajectory
+   *                       parameters. For example, {@link Helix} parameters can be
+   *                       returned in {@link Helix.CRep} and {@link Helix.WRep} representations.
+   */
+  public <T extends Enum<T>> ParCovMatrix<T> getCovMatrix(Class<T> representation);
+
+  /**
+   * Returns an element of a covariance matrix of parameters that describe the shape of this trajectory.
+   * The parameter is identified by enum constant that belongs to a particular representation.
+   */
+  public <T extends Enum<T>> double getCovElement(T parameter1, T parameter2);
+  
+// -- Find intersection with a surface :  --------------------------------------
+  
+  /**
+   * Returns intersection of this trajectory with the specified surface.
+   */
+  public Intersection intersect(Surface surface);
+  
+
+// -- Modifying the trajectory :  ----------------------------------------------
+  
+  /** 
+   * Reverse the direction of the trajectory.
+   */
+  public void reverse();
+  
+  /**
+   * Move the origin by the given path length along the trajectory.
+   * Returns <tt>false</tt> if the requested point does not exist on this trajectory.
+   */
+  public boolean swim(double pathLength);
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
ZCylinder.java added at 1.1
diff -N ZCylinder.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ZCylinder.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,56 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import org.lcsim.contrib.onoprien.util.ConstHep3Vector;
+
+/**
+ * {@link Surface} that represents a bounded cylinder parallel to and centered at Z axis.
+ * This surface is characterized by radius, low Z bound, and high Z bound.
+ *
+ * @author D. Onoprienko
+ * @version $Id: ZCylinder.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class ZCylinder extends AbstractSurface {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public ZCylinder(double radius, double zMin, double zMax) {
+  }
+  
+// -- Getters :  ---------------------------------------------------------------
+  
+  /** Returns radius of this cylinder. */
+  public double getRadius() {
+    return _r;
+  }
+  
+  /** Returns minimum Z of this cylinder. */
+  public double getMinZ() {
+    return _zMin;
+  }
+  
+  /** Returns minimum Z of this cylinder. */
+  public double getMaxZ() {
+    return _zMax;
+  }
+  
+// -- Implementing Surface :  --------------------------------------------------
+  
+  /**
+   * Returns intersection of the specified trajectory with this surface.
+   */
+  public Intersection intersect(Trajectory trajectory) {
+    if (trajectory instanceof Line) {
+      return ((Line)trajectory).intersect(this);
+    } else if (trajectory instanceof Helix) {
+      return ((Helix)trajectory).intersect(this);
+    } else {
+      return super.intersect(trajectory);
+    }
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  double _r;
+  double _zMin, _zMax;
+  
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
ZDisk.java added at 1.1
diff -N ZDisk.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ZDisk.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,57 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+import hep.physics.vec.Hep3Vector;
+
+/**
+ * {@link Surface} that represents a disk centered around Z axis and perpendicular to it.
+ *
+ * @author D. Onoprienko
+ * @version $Id: ZDisk.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class ZDisk extends AbstractSurface {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public ZDisk(double z, double radiusMin, double radiusMax) {
+    _z = z;
+    _rMin2 = radiusMin * radiusMin;
+    _rMax2 = radiusMax * radiusMax;
+  }
+  
+// -- Getters :  ---------------------------------------------------------------
+  
+  /** Returns Z coordinate of this disk. */
+  public double getZ() {
+    return _z;
+  }
+  
+  /** Returns inner radius of this disk. */
+  public double getMinRadius() {
+    return Math.sqrt(_rMin2);
+  }
+  
+  /** Returns outer radius of this disk. */
+  public double getMaxRadius() {
+    return Math.sqrt(_rMax2);
+  }
+  
+// -- Implementing Surface :  --------------------------------------------------
+  
+  /**
+   * Returns intersection of the specified trajectory with this surface.
+   */
+  public Intersection intersect(Trajectory trajectory) {
+    if (trajectory instanceof Line) {
+      return ((Line)trajectory).intersect(this);
+    } else if (trajectory instanceof Helix) {
+      return ((Helix)trajectory).intersect(this);
+    } else {
+      return super.intersect(trajectory);
+    }
+  }
+  
+// -- Private parts :  ---------------------------------------------------------
+  
+  double _z;
+  double _rMin2, _rMax2;
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
ZPlane.java added at 1.1
diff -N ZPlane.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ZPlane.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,42 @@
+package org.lcsim.contrib.onoprien.util.swim;
+
+/**
+ * {@link Surface} that represents a plane perpendicular to Z axis.
+ *
+ * @author D. Onoprienko
+ * @version $Id: ZPlane.java,v 1.1 2008/11/05 03:32:51 onoprien Exp $
+ */
+public class ZPlane extends AbstractSurface {
+  
+// -- Constructors :  ----------------------------------------------------------
+  
+  public ZPlane(double z) {
+    _z = z;
+  }
+  
+// -- Getters :  ---------------------------------------------------------------
+  
+  /** Returns Z coordinate of this plane. */
+  public double getZ() {
+    return _z;
+  }
+  
+// -- Implementing Surface :  --------------------------------------------------
+  
+  /**
+   * Returns intersection of the specified trajectory with this surface.
+   */
+  public Intersection intersect(Trajectory trajectory) {
+    if (trajectory instanceof Line) {
+      return ((Line)trajectory).intersect(this);
+    } else if (trajectory instanceof Helix) {
+      return ((Helix)trajectory).intersect(this);
+    } else {
+      return super.intersect(trajectory);
+    }
+  }
+
+// -- Private parts :  ---------------------------------------------------------
+  
+  double _z;
+}

lcsim/src/org/lcsim/contrib/onoprien/util/swim
package-info.java added at 1.1
diff -N package-info.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ package-info.java	5 Nov 2008 03:32:51 -0000	1.1
@@ -0,0 +1,6 @@
+/**
+ * Classes for representing trajectories and surfaces, finding their
+ * intersections, and propagating parameters and their covariance matrices along trajectories.
+ */
+package org.lcsim.contrib.onoprien.util.swim;
+
CVSspam 0.2.8