content: package edu.stanford.rsl.conrad.geometry.shapes;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Iterator;
  
  import edu.stanford.rsl.conrad.geometry.AbstractCurve;
  import edu.stanford.rsl.conrad.geometry.AbstractShape;
  import edu.stanford.rsl.conrad.geometry.Axis;
  import edu.stanford.rsl.conrad.geometry.bounds.AbstractBoundingCondition;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.SimpleSurface;
  import edu.stanford.rsl.conrad.geometry.transforms.Transform;
  
  /**
   * Models an arbitrary shape centered at the origin using a base shape and bounding conditions
   * An affine transform class is used to translate and orient shapes from object space in world space
   * The affine transform of an arbitrary shape is always the same as that of its base shape;
   * 
   * @author Rotimi X Ojo
   */
  public class ArbitrarySurface extends SimpleSurface {
  
  	private static final long serialVersionUID = -3286378502393392770L;
  	private ArrayList<AbstractBoundingCondition> boundingClips = new ArrayList<AbstractBoundingCondition>();
  	private SimpleSurface baseSurface;
  
  	public ArbitrarySurface(SimpleSurface baseSurface,Collection<? extends AbstractBoundingCondition> clipSurfaces){
  		this.baseSurface = baseSurface;
  		this.boundingClips.addAll(boundingClips);
  		transform = baseSurface.getTransform();
  	}
  
  	public ArbitrarySurface(ArbitrarySurface surf) {
  		super(surf);
  		
  		// deep copy the bounding clips
  		if (surf.boundingClips != null){
  			Iterator<AbstractBoundingCondition> it = surf.boundingClips.iterator();
  			boundingClips = new ArrayList<AbstractBoundingCondition>();
  			while (it.hasNext()) {
  				AbstractBoundingCondition cond = it.next();
  				boundingClips.add((cond!=null) ? cond.clone() : null);
  			}
  		}
  		else {
  			boundingClips = null;
  		}
  		
  		// deep copy the base surface
  		baseSurface = (surf.baseSurface!=null) ? (SimpleSurface) surf.baseSurface.clone() : null;
  	}
  
  	@Override
  	public boolean isMember(PointND hit, boolean pointTransformed) {
  		if(!baseSurface.isMember(hit, pointTransformed)){
  			return false;
  		}
  
  		Iterator<AbstractBoundingCondition> clips = boundingClips.iterator();
  		while(clips.hasNext()){
  			if(!clips.next().isSatisfiedBy(hit)){
  				return false;
  			}
  		}		
  		return true;		
  	}
  
  	public ArrayList<PointND> getHits(AbstractCurve other){
  		return baseSurface.intersect(other);
  	}
  
  
  	@Override
  	public boolean isBounded() {
  		return true;
  	}
  
  	@Override
  	public PointND evaluate(PointND u) {
  		return u;
  	}
  
  	@Override
  	public int getDimension() {
  		return baseSurface.getDimension();
  	}
  
  	@Override
  	public int getInternalDimension() {
  		return baseSurface.getInternalDimension();
  	}
  
  
  	@Override
  	public void applyTransform(Transform t) {
  		baseSurface.applyTransform(t);
  		transform = baseSurface.getTransform();
  	}
  
  	@Override
  	public PointND[] getRasterPoints(int number) {
  		return null;
  	}
  
  	@Override
  	public Axis getPrincipalAxis() {
  		return baseSurface.getPrincipalAxis();
  	}
  
  	@Override
  	public PointND evaluate(double u, double v) {
  		return baseSurface.evaluate(u, v);
  	}
  
  	@Override
  	public AbstractShape tessellate(double accuracy) {
  		// TODO Auto-generated method stub
  		return null;
  	}
  
  	@Override
  	public AbstractShape clone() {
  		return new ArbitrarySurface(this);
  	}
  
  
  }
  /*
   * Copyright (C) 2010-2014 Andreas Maier, Rotimi X Ojo 
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
   */