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). */