package edu.stanford.rsl.conrad.rendering;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
import edu.stanford.rsl.conrad.physics.PhysicalObject;
public class PrioritizableScene extends AbstractScene {
/**
*
*/
private static final long serialVersionUID = -8239645378207352898L;
public static final boolean ADD_HIGHEST_PRIORITY = true;
public static final boolean ADD_LOWEST_PRIORITY = false;
private ArrayList<PhysicalObject> objects = new ArrayList<PhysicalObject>();
private HashMap<PhysicalObject, Integer> priorityMap = new HashMap<PhysicalObject, Integer>();
private boolean dirty = true;
private int highest = 0;
private int lowest = 0;
public int getPriority(PhysicalObject o){
//System.out.println(o.getNameString());
return priorityMap.get(o).intValue();
}
/**
* updates the values for the priority limits
*/
private void updateLimits(){
Collection<Integer> values = priorityMap.values();
Integer [] array = new Integer[values.size()];
if (array.length > 1){
array = values.toArray(array);
Arrays.sort(array);
highest = array[array.length-1];
lowest = array[0];
}
dirty = false;
}
/**
* Method is called after the collection changed, such that the minimum
* and maximum points of the overall scene are updated.
*/
protected void updateSceneLimits(){
for (PhysicalObject e : objects)
{
if (this.max == null)
this.max = new PointND(e.getShape().getMax());
if (this.min == null)
this.min = new PointND(e.getShape().getMin());
for (int i = 0; i < this.max.getDimension(); ++i){
if (e.getShape().getMax().get(i) > this.max.get(i))
this.max.set(i, e.getShape().getMax().get(i));
if (e.getShape().getMin().get(i) < this.min.get(i))
this.min.set(i, e.getShape().getMin().get(i));
}
}
}
public int getHighestPriority(){
if (dirty){
updateLimits();
}
return highest;
}
public int getLowestPriority(){
if(dirty){
updateLimits();
}
return lowest;
}
public boolean add(PhysicalObject e) {
return add(e, ADD_HIGHEST_PRIORITY);
}
public boolean add(PhysicalObject e, boolean addMode){
Integer priority;
if (addMode == ADD_HIGHEST_PRIORITY){
priority = new Integer(getHighestPriority() + 1);
} else {
priority = new Integer(getLowestPriority() - 1);
}
return add(e,priority);
}
/**
* This method is always called if an object is added to the scene.
* A call to this method updates the scene's limits (min, max).
*
* @param e The object to add
* @param priority The object's priority
* @return true if the collection changed due to this call
*/
public boolean add(PhysicalObject e, int priority){
boolean revan = objects.add(e);
priorityMap.put(e, priority);
dirty = true;
updateSceneLimits();
return revan;
}
public boolean addAll(Collection<? extends PhysicalObject> c) {
boolean revan = true;
for(PhysicalObject e:c){
if (!add(e)){
revan = false;
}
}
return revan;
}
public boolean addAll(PrioritizableScene c) {
boolean revan = true;
for(PhysicalObject e:c){
if (!add(e, c.getPriority(e))){
revan = false;
}
}
return revan;
}
public void clear() {
objects.clear();
priorityMap.clear();
this.max = null;
this.min = null;
}
public void clearObjectsOnly() {
objects.clear();
priorityMap.clear();
}
public boolean contains(Object o) {
return objects.contains(o);
}
public boolean containsAll(Collection<?> c) {
return objects.containsAll(c);
}
public boolean isEmpty() {
return objects.isEmpty();
}
public Iterator<PhysicalObject> iterator() {
return objects.iterator();
}
public PhysicalObject getObject(int i) {
if (i < objects.size() && i >= 0){
return objects.get(i);
}
return null;
}
public boolean remove(Object o) {
boolean revan = objects.remove(o);
priorityMap.remove(o);
dirty = true;
updateSceneLimits();
return revan;
}
public boolean removeAll(Collection<?> c) {
boolean revan = true;
for (Object e : c){
if (!remove(e)){
revan = false;
}
}
updateSceneLimits();
return revan;
}
public boolean retainAll(Collection<?> c) {
boolean revan = true;
for(Object o: this){
if (!c.contains(o)) {
if(!remove(o)){
revan = false;
}
}
}
updateSceneLimits();
return revan;
}
public int size() {
return objects.size();
}
public Object[] toArray() {
return objects.toArray();
}
public <T> T[] toArray(T[] a) {
return objects.toArray(a);
}
}
/*
* Copyright (C) 2010-2014 Andreas Maier
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/