/**
*
*/
package fr.unistra.pelican.util.connectivityTrees;
import java.util.HashMap;
import java.util.Map;
import fr.unistra.pelican.util.Point3D;
/**
* This class helps to maintain a collection of disjoint sets for union find algorithm
*
* @author Benjamin Perret
*
*/
public class UnionFindHelper {
/**
* Dimension of space
*/
private int xdim, ydim,zdim,xydim;
/**
* List of all points
*/
private UnionFindParametre [] map;
/**
* Create a union find helper for a space of given dimensions
* @param xdim
* @param ydim
* @param zdim
*/
public UnionFindHelper(int xdim, int ydim, int zdim)
{
this.xdim=xdim;
this.ydim=ydim;
this.zdim=zdim;
xydim=xdim*ydim;
map = new UnionFindParametre[zdim*xdim*ydim];
}
/**
* Compress path from all points to their canonical elements
*/
public void compressPathFinding(){
for(int z=0;z<zdim;z++)
for(int y=0;y<ydim;y++)
for(int x=0;x<xdim;x++)
find(x, y, z);
}
/**
* Build a new set containing only point p
* @param p
*/
public UnionFindParametre MakeSet(Point3D p)
{
return map[p.z*xydim+p.y*xdim+p.x] = new UnionFindParametre(p);
}
/**
* Find canonical element representing given pixel (x,y,z)
* @param x
* @param y
* @param z
* @return
*/
public Point3D find(int x, int y , int z)
{
UnionFindParametre params= find(map[z*xydim+y*xdim+x]);
return params.attachedPoint;
}
/**
* Find canonical element representing given pixel (x,y)
* @param x
* @param y
* @return
*/
public Point3D find(int x, int y )
{
return find(x,y,0);
}
/**
* Find canonical element representing given point
* @param p
* @return
*/
public Point3D find(Point3D p)
{
return find(p.x,p.y,p.z);
}
/**
* Find canonical element representing given pixel (x,y,z)
* @param x
* @param y
* @param z
* @return
*/
public UnionFindParametre find(UnionFindParametre params)
{
if(params.parent!=params)
{
params.parent=find(params.parent);
}
return params.parent;
}
/**
* Link sets associated to different points
* Linkage is done to minimize path length to canonical element (canonical element may change!)
*
* DO NOT USE THIS FUNCTION ONCE THE COMPONENT TREE IS BUILD AS THE CANONICAL ELEMENT OF A SET MUST BE CONSTANT AT THIS TIME
*
* @param p1
* @param p2
* @return point chosen to be the canonical element of the other
*/
public Point3D link(Point3D p1, Point3D p2)
{
UnionFindParametre px= map[p1.z*xydim+p1.y*xdim+p1.x];
UnionFindParametre py= map[p2.z*xydim+p2.y*xdim+p2.x];
if(px.rank>py.rank)
{
Point3D tmp=p1;
p1=p2;
p2=tmp;
UnionFindParametre tmp2=px;
px=py;
py=tmp2;
} else if(px.rank==py.rank)
py.rank++;
px.parent=py;
return p2;
}
/**
* Link sets associated to different points
* This function does not try to minimize path length to canonical element so it ensure that first point will be the canonical element of the second one
* @param root
* @param child
* @return
*/
public UnionFindParametre linkNoRankCheck(UnionFindParametre root, UnionFindParametre child)
{
//UnionFindParametre px= map[root.z*xydim+root.y*xdim+root.x];
//UnionFindParametre py= map[child.z*xydim+child.y*xdim+child.x];
/*if(px.rank<py.rank)
px.rank=py.rank;
else if(px.rank==py.rank)
px.rank++;*/
child.parent=root.parent;//root;
//find(child);
return root;
}
/**
* Print string representation of the set on the default output
*/
public void drop()
{
for(int y=0;y<ydim;y++)
{System.out.print("|");
for(int x=0;x<xdim;x++)
{
Point3D p =find(x,y);
if(p.x == x && p.y==y)
System.out.print("*(" +p.x + "," +p.y + ")r=" + + map[p.z*xydim+p.y*xdim+p.x].rank + " |");
else System.out.print(" (" +p.x + "," +p.y + ")r=" + + map[p.z*xydim+p.y*xdim+p.x].rank + " |");
}
System.out.println();
}
}
public UnionFindParametre changePointLink(Point3D p,UnionFindParametre parent)
{
// create a new unionfindparamtre, leave the old one as phantom to preserve links.
//UnionFindParametre parent= map[newParent.z*xydim+newParent.y*xdim+newParent.x];
//System.out.println(p + " " + parent);
UnionFindParametre pr=new UnionFindParametre(p);
pr.parent=parent;
map[p.z*xydim+p.y*xdim+p.x]=pr;
/*UnionFindParametre px= map[p.z*xydim+p.y*xdim+p.x];
if(px.parent==px)
{
System.out.println("grrrrr this is master node!");
}
px.parent=newParent;
px.rank=1;*/
return pr;
}
}