package org.andork.spatial;
import java.util.LinkedList;
public class SIBranch<T> implements SINode<T>
{
private SIBranch<T> parent;
private BBox bbox = new BBox( );
private boolean needsRecompute = false;
private boolean isValid = false;
private LinkedList<SINode<T>> children = new LinkedList<SINode<T>>( );
public SIBranch<T> getParent( )
{
return parent;
}
public void setParent( SIBranch<T> parent )
{
this.parent = parent;
}
public BBox getBBox( )
{
if( !isValid )
{
validate( );
}
return bbox;
}
public boolean isValid( )
{
return isValid;
}
public void invalidate( )
{
isValid = false;
if( parent != null )
{
parent.invalidate( );
}
}
public void validate( )
{
if( !needsRecompute )
{
for( SINode<T> child : children )
{
if( !child.isValid( ) )
{
BBox cbbox = child.getBBox( );
double lx = cbbox.getLow( 0 );
double ly = cbbox.getLow( 1 );
double lz = cbbox.getLow( 2 );
double ux = cbbox.getHigh( 0 );
double uy = cbbox.getHigh( 1 );
double uz = cbbox.getHigh( 2 );
child.validate( );
cbbox = child.getBBox( );
if( cbbox.getLow( 0 ) <= lx && cbbox.getLow( 1 ) <= ly && cbbox.getLow( 2 ) <= lz && cbbox.getHigh( 0 ) >= ux && cbbox.getHigh( 1 ) >= uy && cbbox.getHigh( 2 ) >= uz )
{
bbox.union( bbox , cbbox );
}
else
{
needsRecompute = true;
break;
}
}
}
}
if( needsRecompute )
{
bbox.setVoid( );
for( SINode<T> child : children )
{
bbox.union( bbox , child.getBBox( ) );
}
needsRecompute = false;
}
isValid = true;
}
public void addChild( SINode<T> child )
{
if( child.getParent( ) != null )
{
throw new IllegalArgumentException( "child already has a parent" );
}
child.setParent( this );
children.add( child );
invalidate( );
}
public void removeChild( SINode<T> child )
{
children.remove( child );
child.setParent( null );
needsRecompute = true;
invalidate( );
}
public LinkedList<SINode<T>> getChildren( )
{
return children;
}
}