package org.chesmapper.view.cluster;
import java.util.BitSet;
import java.util.List;
import java.util.Vector;
import javax.vecmath.Vector3f;
import org.chesmapper.view.gui.Zoomable;
import org.mg.javalib.util.ArrayUtil;
import org.mg.javalib.util.Vector3fUtil;
public class ZoomableCompoundGroup implements Zoomable
{
private Vector<Compound> origCompounds;
private Vector<Compound> filteredCompounds;
private BitSet bitSet;
private BitSet dotModeDisplayBitSet;
private boolean superimposed = false;
private float superimposeDiameter;
private float nonSuperimposeDiameter;
private Vector3f superimposeCenter;
private Vector3f nonSuperimposeCenter;
private boolean allCompoundsHaveSamePosition = false;
protected void setCompounds(List<Compound> compounds)
{
this.origCompounds = new Vector<Compound>(compounds);
this.filteredCompounds = new Vector<Compound>(compounds);
}
public int getIndex(Compound compound)
{
return filteredCompounds.indexOf(compound);
}
public Compound getCompound(int index)
{
return filteredCompounds.get(index);
}
public int getNumCompounds()
{
return filteredCompounds.size();
}
public int getOrigSize()
{
return origCompounds.size();
}
public boolean contains(Compound compound)
{
return filteredCompounds.contains(compound);
}
public List<Compound> getCompounds()
{
return filteredCompounds;
}
public boolean isSuperimposed()
{
return superimposed;
}
public boolean isSpreadable()
{
return !allCompoundsHaveSamePosition;
}
@Override
public Vector3f getCenter(boolean superimposed)
{
if (superimposed)
return superimposeCenter;
else
return nonSuperimposeCenter;
}
@Override
public float getDiameter(boolean superimposed)
{
if (superimposed)
return superimposeDiameter;
else
return nonSuperimposeDiameter;
}
public void setSuperimposed(boolean superimposed)
{
this.superimposed = superimposed;
}
public boolean isFilteredOut(CompoundFilter filter)
{
for (Compound c : origCompounds)
if (filter == null || filter.accept(c))
return false;
return true;
}
public void setFilter(CompoundFilter filter)
{
filteredCompounds = new Vector<Compound>();
for (Compound c : origCompounds)
if (filter == null || filter.accept(c))
filteredCompounds.add(c);
update();
}
protected void update()
{
bitSet = new BitSet();
for (Compound m : filteredCompounds)
bitSet.or(m.getBitSet());
dotModeDisplayBitSet = new BitSet();
for (Compound m : filteredCompounds)
dotModeDisplayBitSet.or(m.getDotModeDisplayBitSet());
if (bitSet.cardinality() == 0)
return;
// updating (unscaled!) cluster position
// this is only needed in case a compound was removed
Vector3f[] positions = ArrayUtil.toArray(ClusteringUtil.getCompoundPositions(this));
superimposeCenter = Vector3fUtil.center(positions);
nonSuperimposeCenter = Vector3fUtil.centerConvexHull(positions);
superimposeDiameter = -1;
for (Compound m : filteredCompounds)
if (m.isVisible())
superimposeDiameter = Math.max(superimposeDiameter, m.getDiameter());
// recompute diameter, depends on the scaling
positions = ArrayUtil.toArray(ClusteringUtil.getCompoundPositions(this));
float maxCompoundDist = Vector3fUtil.maxDist(positions);
allCompoundsHaveSamePosition = maxCompoundDist == 0;
// nonSuperimposeDiameter ignores size of compounds, just uses the compound positions
// for very small diameter: should be at least as big as superimposed one
nonSuperimposeDiameter = Math.max(superimposeDiameter, maxCompoundDist);
}
public BitSet getBitSet()
{
return bitSet;
}
public BitSet getDotModeDisplayBitSet()
{
return dotModeDisplayBitSet;
}
public boolean containsCompoundWithJmolIndex(int compoundIndex)
{
return getCompoundWithJmolIndex(compoundIndex) != null;
}
public Compound getCompoundWithJmolIndex(int compoundIndex)
{
for (Compound m : filteredCompounds)
if (m.getJmolIndex() == compoundIndex)
return m;
return null;
}
}