package ddddbb.math;
import java.util.Collection;
import java.util.List;
import ddddbb.comb.ACell;
import ddddbb.comb.ALocation;
import ddddbb.comb.Cell;
public class HalfSpace {
public Point normal;
public double length; // length from (0,0,0) to plane along the normal, can be negative
// parent is 3d space
protected HalfSpace() {}
public HalfSpace(Point _normal, double _length) {
normal = _normal;
length = _length;
}
public HalfSpace(Point orig, Point _normal) {
normal = _normal;
length = normal.sc(orig);
}
// /** s is on the inner side of the plane spanned by a,b,c */
// public Space2d init(Point3d a, Point3d b, Point3d c) {
// normal = Gop.X((Point3d)b.minus(a).normalize(), (Point3d)c.minus(a).normalize());
// length = a.sc(normal);
// return this;
// }
public HalfSpace(List<Cell> facets) {
assert facets.size() >= 2;
int i=0;
Point[] d= new Point[2];
Point a = null;
for (Cell f1:facets) {
assert f1.location().dim() == 1;
Point f1a,f1b;
f1a = f1.a().location().o().clone();
f1b = f1.b().location().o().clone();
if (i>=2) { break; }
if (i==0) { a = f1a; }
d[i] = f1b.subtract(f1a).normalize();
i++;
}
//TODO normal = Gop.X(d[0],d[1]); //for spacedim 3d
normal.multiply(normal.positivity());
length = a.sc(normal);
}
public void flip() {
normal.multiply(-1);
length *= -1;
}
public Point origin() {
return normal.clone().multiply(length);
}
public Point proj(Point p) {
return p.clone().subtract(normal.proj(p.clone().subtract(origin())));
}
public double dist(Point p) {
return p.clone().subtract(proj(p)).len();
}
/*
* 1 outer
* 0 on
* -1 inner
*/
public int side(Point p) {
assert normal.dim() == origin().dim() : normal.dim() + "!=" + origin().dim();
assert normal.dim() == p.dim() : normal.dim() + "!=" + p.dim();
double proj = normal.sc(p.clone().subtract(origin()));
if ( proj >= AOP.ERR ) { return 1; }
if ( proj <= -AOP.ERR ) { return -1; }
return 0;
}
public boolean equals(HalfSpace e) {
return AOP.eq(normal.clone().subtract(e.normal).len(),0) &&
AOP.eq(length,e.length);
}
/** returns one of Cell.CONTAINED, Cell.INNER, Cell.OUTER, Cell.SPLITTED */
public int side(ACell c) {
return side(c,1);
}
/** returns one of Cell.CONTAINED, Cell.INNER, Cell.OUTER, Cell.SPLITTED */
public int side(ACell c, int positivity) {
Collection<ALocation> locations = c.getPointLocations(false);
int side = Cell.PRISTINE;
for ( ALocation l : locations ) {
int pointSide = side(l.o())*positivity; //-1 inner, 0 contained, +1 outer
if ( pointSide == -1 ) {
if ( side == Cell.PRISTINE ) { side = Cell.INNER; continue; }
if ( side == Cell.CONTAINED ) { side = Cell.INNER; continue; }
if ( side == Cell.OUTER ) { return Cell.SPLITTED; }
// unchanged for side==INNER
continue;
}
if ( pointSide == +1 ) {
if ( side == Cell.PRISTINE ) { side = Cell.OUTER; continue; }
if ( side == Cell.CONTAINED ) { side = Cell.OUTER; continue; }
if ( side == Cell.INNER) { return Cell.SPLITTED; }
// unchanged for side==OUTER
continue;
}
if ( pointSide == 0 ) {
if ( side == Cell.PRISTINE ) { side = Cell.CONTAINED; continue; }
//unchanged for side == INNER, OUTER, CONTAINED
continue;
}
}
return side;
}
}