package edu.stanford.rsl.conrad.geometry.shapes.compound; 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.shapes.simple.PointND; import edu.stanford.rsl.conrad.geometry.transforms.Transform; public class CompoundShape extends AbstractShape implements Collection<AbstractShape> { /** * */ private static final long serialVersionUID = 4296470814160586436L; private ArrayList<AbstractShape> list; protected boolean dirty = true; public CompoundShape(){ list = new ArrayList<AbstractShape>(); } public CompoundShape(CompoundShape cs){ super(cs); dirty = cs.dirty; if(cs.list != null){ Iterator<AbstractShape> it = cs.list.iterator(); list = new ArrayList<AbstractShape>(); while (it.hasNext()) { AbstractShape shape = it.next(); list.add((shape!=null) ? shape.clone() : null); } } else list = null; } @Override public int getDimension() { return list.get(0).getDimension(); } public AbstractShape get(int i){ return list.get(i); } protected synchronized void init(){ if (dirty){ min = new PointND(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); max = new PointND(-Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE); for (AbstractShape t: list){ min.updateIfLower(t.getMin()); max.updateIfHigher(t.getMax()); } super.generateBoundingPlanes(); dirty = false; } } @Override public ArrayList<PointND> getHitsOnBoundingBox(AbstractCurve curve){ if (dirty){ init(); } return super.getHitsOnBoundingBox(curve); } protected static ArrayList<PointND> intersect(AbstractShape t, AbstractCurve other){ ArrayList<PointND> pts = null; if (t instanceof CompoundShape){ CompoundShape compound = (CompoundShape) t; if (compound.getHitsOnBoundingBox(other).size() > 0){ pts = compound.intersect(other); } else { pts = new ArrayList<PointND>(); } } else { pts = t.intersect(other); } return pts; } protected static ArrayList<PointND> intersectWithHitOrientation(AbstractShape t, AbstractCurve other){ ArrayList<PointND> pts = null; if (t instanceof CompoundShape){ CompoundShape compound = (CompoundShape) t; if (compound.getHitsOnBoundingBox(other).size() > 0){ pts = compound.intersectWithHitOrientation(other); } else { pts = new ArrayList<PointND>(); } } else { pts = t.intersectWithHitOrientation(other); } return pts; } @Override public ArrayList<PointND> intersect(AbstractCurve other) { if (dirty){ init(); } ArrayList <PointND> hits = new ArrayList<PointND>(); for(AbstractShape t: list){ hits.addAll(intersect(t,other)); } return hits; } @Override public ArrayList<PointND> intersectWithHitOrientation(AbstractCurve other) { if (dirty){ init(); } ArrayList <PointND> hits = new ArrayList<PointND>(); for(AbstractShape t: list){ hits.addAll(intersectWithHitOrientation(t, other)); } return hits; } @Override public boolean isBounded() { return true; } @Override public PointND getMax(){ if (dirty){ init(); } return super.getMax(); } @Override public PointND getMin(){ if (dirty){ init(); } return super.getMin(); } public boolean add(AbstractShape shape){ boolean revan = list.add(shape); dirty = true; return revan; } public PointND[] getRasterPoints(int number){ ArrayList<PointND[]> lists = new ArrayList<PointND[]>(); int sum = 0; for (AbstractShape t : list){ PointND [] pts = t.getRasterPoints(number/ list.size()); sum += pts.length; lists.add(pts); } PointND [] points = new PointND[sum]; int increment = 0; for (PointND [] pts : lists){ System.arraycopy(pts, 0, points, increment, pts.length); increment += pts.length; } return points; } @Override public void applyTransform(Transform t) { for (AbstractShape s: list){ //System.out.println("CompundShape: applying Transform to " + s.toString()); s.applyTransform(t); //System.out.println("CompundShape: applied Transform to " + s.toString()); } dirty = true; } @Override public PointND evaluate(PointND u) { return null; } @Override public int getInternalDimension() { return list.size(); } @Override public boolean addAll(Collection<? extends AbstractShape> c) { dirty = true; return list.addAll(c); } @Override public void clear() { list.clear(); dirty = true; } @Override public boolean contains(Object o) { return list.contains(o); } @Override public boolean containsAll(Collection<?> c) { return list.containsAll(c); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public Iterator<AbstractShape> iterator() { return list.iterator(); } @Override public boolean remove(Object o) { dirty = true; return list.remove(o); } @Override public boolean removeAll(Collection<?> c) { dirty =true; return removeAll(c); } @Override public boolean retainAll(Collection<?> c) { dirty = true; return list.retainAll(c); } @Override public int size() { int size = 0; for (AbstractShape s: list){ if (s instanceof Collection<?>){ size += ((Collection<?>) s).size(); } else { size ++; } } return size; } @Override public Object[] toArray() { return list.toArray(); } @Override public <T> T[] toArray(T[] a) { return list.toArray(a); } @Override public String toString(){ return "CompoundShape with " + size() + " elements"; } @Override public AbstractShape clone() { return new CompoundShape(this); } } /* * Copyright (C) 2010-2014 Andreas Maier * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */