/**
*
*/
package fr.unistra.pelican.util.connectivityTrees;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import fr.unistra.pelican.util.ArrayToolbox;
import fr.unistra.pelican.util.Point3D;
import fr.unistra.pelican.util.connectivityTrees.attributes.ComponentAttribute;
/**
* This class represents a connected component of an image.
* It represents root, nodes and leaves of the tree.
*
* It is furnished with default attributes : level, area, highest level.
* You can add more attributes using the addAttribute method of class ComponentTree
*
* @author Benjamin Perret
*
*/
public class ComponentNode <T>{
/**
* A field free to use, useful to mark nodes before deletion for example.
*/
public int flag;
public int flag2;
public int flag3;
/**
* 3 fields free to use...
*/
public T helper1;
public T helper2;
public T helper3;
public Object helper4;
/**
* THIS FIELD IS USED BY ITERATOR PROVIDED BY CLASS COMPONENT TREE DO NOT USE IT WHILE USING SUCH ITERATORS !!!
*/
public int iteratorFlag;
/**
* Location of canonical element
*/
public Point3D location;
public UnionFindParametre locator;
/**
* Level of given node
*/
private T level;
/**
* Area of node (number of pixels in it and in its children)
*/
private int area;
public int perimeter;
/**
* highest level of pixels in it and in its children
*/
private T highest;
/**
* Parent of component node (null if root)
*/
public ComponentNode<T> parent;
/**
* Map of all attributes added to this node
*/
private Map<Class<? extends ComponentAttribute>,ComponentAttribute> attributes = new HashMap<Class<? extends ComponentAttribute>,ComponentAttribute>();
/**
* List of children nodes
*/
private ArrayList<ComponentNode<T>> children=new ArrayList<ComponentNode<T>>();
/**
* Build node with canonical element at given location at given level
* @param location
* @param level
*/
public ComponentNode(Point3D location,T level)
{
this.level=level;
this.highest=level;
this.area=1;
this.location=location;
}
/**
* Add a child node
* @param e
* @return
*/
public boolean addChild(ComponentNode<T> e) {
e.setParent(this);
return children.add(e);
}
/**
* Add a collection of children to node
* @param c
* @return
*/
public boolean addAllChildren(Collection<? extends ComponentNode<T>> c) {
for(ComponentNode<T> child:c)
{
child.setParent(this);
}
return children.addAll(c);
}
/**
* delete all children
*/
public void clearChildren() {
children.clear();
}
/**
* get child number index
* @param index
* @return
*/
public ComponentNode<T> getChild(int index) {
return children.get(index);
}
/**
* get collection of all children (warning unsafe, collection is a reference to the one managed by the node)
* @return
*/
public Collection<? extends ComponentNode<T>> getChildren() {
return children;
}
/**
* get collection of all children (safe you get a copy)
* @return
*/
public Collection<? extends ComponentNode<T>> getChildrenSafe() {
return (Collection<? extends ComponentNode<T>>)children.clone();
}
/**
* Test if node is a leaf (numberOfChildren()==0)
* @return
*/
public boolean isLeaf() {
return children.isEmpty();
}
/**
* Delete given child
* @param e
* @return
*/
public boolean removeChild(ComponentNode<T> e) {
return children.remove(e);
}
/**
* get the number of children of the node
* @return
*/
public int numberOfChildren() {
return children.size();
}
/**
* get level of the node
* @return
*/
public T getLevel() {
return level;
}
public void setLevel(T level) {
this.level = level;
}
public int getArea() {
return area;
}
public void setArea(int area) {
this.area = area;
}
public T getHighest() {
return highest;
}
public void setHighest(T highest) {
this.highest = highest;
}
public String toString()
{
return toString(0);
}
private String toString(int depth)
{
String op="";
for(int i=0;i<depth;i++)
op+="|";
op+="-> " + location +" Level: " + ArrayToolbox.printString(level) + " area " + area + "\n";
for(ComponentNode<T> c: children)
op+=c.toString(depth+1);
return op;
}
public ComponentNode<T> getParent() {
return parent;
}
public void setParent(ComponentNode<T> parent) {
this.parent = parent;
}
/**
* NOT IMPLEMENTED merge attributes of two nodes
* @TODO do it
* @param c
* @param comp
*/
public void mergeAttributsWith(ComponentNode<T> c, Comparator<ComponentNode<T>> comp)
{
this.level = (comp.compare(this, c)<=0)?this.getLevel():c.getLevel();
}
/**
* Add an attributes to this node
* @param e
*/
public <E> void add(ComponentAttribute<E> e) {
attributes.put(e.getClass(),e);
}
/**
* Add an attributes to this node
* @param e
*/
public <E> void remove(Class<? extends ComponentAttribute<E>> clazz) {
attributes.remove(clazz);
}
/**
* Get attribute of this node
*
* Requesting an attribute of an unknown class of attributes for this node will produce a class cast exception
*
* @param <T>
* @param clazz class of the attribute to return
* @return
*/
public <T> T get(Class<T> clazz) {
return (T)attributes.get(clazz);
}
/**
* Get attribute of given class
* @param <Q>
* @param clazz
* @return
*/
public <Q extends ComponentAttribute<?>> Q getAttribute(Class<Q> clazz)
{
return (Q)attributes.get(clazz);
}
/**
* Get value of attribute designed by given class
* @param <Q>
* @param clazz
* @return
*/
public <Q> Q getAttributeValue(Class<? extends ComponentAttribute<Q>> clazz)
{
Q res=null;
ComponentAttribute<Q> o=attributes.get(clazz);
if(o!=null) {
res=o.getValue();
}
return res;
}
}