content: package edu.stanford.rsl.conrad.geometry.shapes.simple;
  
  import java.util.ArrayList;
  import java.util.Iterator;
  
  import edu.stanford.rsl.conrad.geometry.AbstractCurve;
  import edu.stanford.rsl.conrad.geometry.AbstractShape;
  import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
  import edu.stanford.rsl.conrad.numerics.SimpleOperators;
  import edu.stanford.rsl.conrad.numerics.SimpleVector;
  import edu.stanford.rsl.conrad.utils.CONRAD;
  
  /**
   * <p>Class to model an arbitrary quadric surface like cylinders, cones, and spheres.
   * <p>For more information on quadric surfaces check <a href="http://en.wikipedia.org/wiki/Quadric"> Quadric Surfaces</a>
   * <p>The main function of this class is to provide intersection and membership verification support to all derived quadric surfaces.
   * 
   * @author Rotimi X Ojo
   */
  public abstract class QuadricSurface extends SimpleSurface{
  
  	private static final long serialVersionUID = 2995274520995183991L;
  	protected SimpleMatrix constMatrix;
  	protected double constant;
  	protected PointND origin = new PointND(0,0,0);
  	private ArrayList<PointND> dummy = new ArrayList<PointND>();
  	
  	public QuadricSurface(){
  		super();
  	}
  	
  	public QuadricSurface(QuadricSurface qs){
  		super(qs);
  		constMatrix = (qs.constMatrix!= null) ? qs.constMatrix.clone() : null;
  		constant = qs.constant;
  		origin = (qs.origin != null) ? qs.origin.clone() : null;
  		
  		if (qs.dummy != null){
  			Iterator<PointND> it = qs.dummy.iterator();
  			dummy = new ArrayList<PointND>();
  			while (it.hasNext()) {
  				PointND p = it.next();
  				dummy.add((p!=null) ? p.clone() : null);
  			}
  		}
  		else{
  			dummy = null;
  		}
  	}
  
  
  	
  	public ArrayList<PointND> getHits(AbstractCurve other) {
  		SimpleVector originVec = origin.getAbstractVector();
  		StraightLine line = (StraightLine)other;
  		SimpleVector lineOrigin = line.getPoint().getAbstractVector();
  		SimpleVector direction = line.getDirection();
  		
  		if (constMatrix == null) {
  			throw new RuntimeException("Please initialize constMatrix");
  		}
  		ArrayList<PointND> hits = new ArrayList<PointND>();			
  		
  		double a = SimpleOperators.multiplyInnerProd(direction, SimpleOperators.multiply(constMatrix, direction));		
  		double b = 2*SimpleOperators.multiplyInnerProd(direction,	SimpleOperators.multiply(constMatrix, SimpleOperators.add(originVec,lineOrigin)));
  		double c1 = SimpleOperators.multiplyInnerProd(lineOrigin,SimpleOperators.multiply(constMatrix, lineOrigin))- constant;
  		double c2 = SimpleOperators.multiplyInnerProd(originVec, SimpleOperators.multiply(constMatrix, originVec));
  		double c3 = 2*SimpleOperators.multiplyInnerProd(originVec, SimpleOperators.multiply(constMatrix, lineOrigin));
  		double c = c1 + c2 + c3;
  		
  		double buff = b * b - 4 * a * c ;
  		if (buff > -CONRAD.FLOAT_EPSILON) {
  			if(buff < 0) buff =0;
  			double leftVal = -b/(2*a);
  			double rightVal = Math.sqrt(buff)/(2*a);
  
  			SimpleVector buffvec = direction.multipliedBy(rightVal + leftVal);
  			buffvec.add(lineOrigin);
  			hits.add(new PointND(buffvec));
  			buffvec = direction.multipliedBy(leftVal - rightVal);
  			buffvec.add(lineOrigin);
  			hits.add(new PointND(buffvec));			
  		}
  
  		return hits;
  	}
  
  	public abstract  boolean isBounded();
  
  	public int getDimension(){
  		return 3;
  	}
  
  	@Override
  	public boolean isMember(PointND point, boolean pointTransformed) {
  		if (!pointTransformed)
  			point= transform.transform(point);
  		SimpleVector vec = point.getAbstractVector();
  		double eval = SimpleOperators.multiplyInnerProd(vec,SimpleOperators.multiply(constMatrix, vec));
  		if(eval <= constant){
  			return true;
  		}
  		return false;
  	}
  	
  
  	@Override
  	public ArrayList<PointND> getHitsOnBoundingBox(AbstractCurve other){
  		if(dummy.size() == 0){
  			dummy.add(origin);
  		}
  		return dummy;
  	}
  
  	@Override
  	public PointND[] getRasterPoints(int number) {
  		// TODO Auto-generated method stub
  		return null;
  	}
  
  
  
  	@Override
  	public PointND evaluate(double u, double v) {
  		// TODO Auto-generated method stub
  		return null;
  	}	
  	
  }
  /*
   * Copyright (C) 2010-2014 Andreas Maier, Rotimi X Ojo 
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */