package ddddbb.comb;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Vector;
import ddddbb.math.Camera4d;
import ddddbb.math.OHalfSpace;
public class CellComplex {
public Vector<Cell> cells;
public CellComplex() {
cells = new Vector<Cell>();
}
public CellComplex(Vector<Cell> _cells) {
cells = _cells;
}
public CellComplex(Iterable<DCell> dcells, Camera4d camera4d) {
cells = new Vector<Cell>();
for (DCell dc:dcells) {
initDCopy(dc);
}
for (DCell df: dcells) {
//get 3d projection of df
OCell oc = new OCell(df, true);
cells.add(oc.cell());
oc.cell().computeSpacesIN();
}
for (Cell c : cells) {
c.referrers.clear();
for (OCell oc: c.facets)
oc.adjustSnapAfterDCopy();
}
}
private static void initDCopy(DCell dc) {
dc.location._dst = null;
dc.dst = null;
for (DCell dc2:dc.facets()) {
initDCopy(dc2);
}
}
public boolean checkSnap() {
for ( Cell c : cells ) {
if ( ! c.checkSnap() ) { return false; }
}
return true;
}
public void cutOut(Iterable<OHalfSpace> planes) {
Vector<Cell> res = new Vector<Cell>();
Vector<Cell> affected = new Vector<Cell>();
for (Cell c:cells) {
//if c is outside one of the planes put it into res
boolean aff = true;
for (OHalfSpace e:planes) {
if (e.side(c) == Cell.OUTER) {
res.add(c);
aff = false;
break;
}
}
if (aff) { affected.add(c); }
}
// Vector<Cell> dc = new Vector<Cell>();
// dc.clear();dc.addAll(res);dc.addAll(affected);
// System.out.println(outsideReferrers(dc).size() + " before splits.");
Vector<Cell> innerCells = new Vector<Cell>(affected);
Vector<Cell> innerCells2;
for (OHalfSpace e:planes) {
innerCells2 = new Vector<Cell>();
for (Cell innerCell:innerCells) {
innerCell.split(e,null);
if ( innerCell.isSplitted() ) {
res.add(innerCell.outer);
innerCells2.add(innerCell.inner);
}
if ( innerCell.isInner()) {
innerCells2.add(innerCell);
}
if ( innerCell.isOuter()) {
res.add(innerCell);
}
}
innerCells = innerCells2;
}
// dc.clear();dc.addAll(res);dc.addAll(innerCells);
// System.out.println(outsideReferrers(dc).size() + " before rm.");
for (Cell innerCell:innerCells) {
innerCell.remove();
}
// dc.clear();dc.addAll(res);
// System.out.println(outsideReferrers(dc).size() + " after rm.");
cells = res;
}
public void cutOut(Cell c) {
assert c.spaceDim() == 3;
assert c.dim() == 3;
Vector<OHalfSpace> hyperPlanes = new Vector<OHalfSpace>();
for (OCell f:c.facets ) {
OHalfSpace s = new OHalfSpace(f.cell().spaceId,f.orientation);
hyperPlanes.add(s);
}
cutOut(hyperPlanes);
}
public static CellComplex occlusionCreate(Vector<DCell> dcells, Camera4d camera4d) {
Comparator<ACell> comp = new ACell.CompareByOcclusion();
Vector<Cell> cells1 = new CellComplex(dcells,camera4d).cells;
Vector<Cell> cells2 = new CellComplex(dcells,camera4d).cells;
Vector<CellComplex> singleComplexes = new Vector<CellComplex>();
for (Cell c: cells1) {
CellComplex singleton = new CellComplex();
singleton.cells.add(c);
singleComplexes.add(singleton);
}
for (int i=0;i<dcells.size();i++) {
for (int j=0;j<dcells.size();j++) {
if (i==j) continue;
if (comp.compare(dcells.get(i),dcells.get(j)) < 0) {
singleComplexes.get(i).cutOut(cells2.get(j));
}
}
}
CellComplex res = new CellComplex();
for (CellComplex sc : singleComplexes) {
res.cells.addAll(sc.cells);
}
return res;
}
/**
* Suppose the list of cells is d-dimensional.
* The result is again a list of cells.
*/
public void occlude() {
CellComplex res = new CellComplex(new Vector<Cell>());
for (Cell c : cells) {
assert c.checkCellrefs();
assert c.checkPointRefs();
res.cutOut(c);
res.cells.add(c);
}
assert res.checkSnap();
cells = res.cells;
}
/**
* Gets all faces of dimension d from this Complex
*/
public HashSet<Cell> getFacesOfDim(int d, boolean withInternalFaces) {
HashSet<Cell> res = new HashSet<Cell>();
for (Cell c:cells) {
for (Cell f:c.getFaces(d, withInternalFaces))
res.add(f);
}
return res;
}
private static HashSet<OCell> outsideReferrers(Vector<Cell> cells) {
HashSet<OCell> ocells = new HashSet<OCell>();
HashSet<Cell> faces = new HashSet<Cell>();
HashSet<OCell> res = new HashSet<OCell>();
for (Cell c: cells) {
faces.addAll(c.getFacesDownTo(0, true));
}
for (Cell c: faces) {
for (OCell o: c.facets) {
ocells.add(o);
}
}
for (Cell c: faces) {
for (OCell r: c.referrers) {
if (! ocells.contains(r)) {
//System.out.print(r.dim());
res.add(r);
}
}
}
return res;
}
public HashSet<OCell> outsideReferrers() {
return outsideReferrers(cells);
}
}