public class Mesh implements Iterable<Mesh.T> {
- public static float EPSILON = (float)0.0001;
- public static Random random = new Random();
+ public static final float EPSILON = (float)0.0001;
+ public static final Random random = new Random();
private PointSet<Vert> pointset = new PointSet<Vert>();
return (float)total;
}
-
public class BindingGroup {
public HashSet<E> es = new HashSet<E>();
public BindingGroup() { }
public final class Vert extends HasPoint {
public Point p;
+ E e; // some edge *leaving* this point
+
+ Vert bound_to = this;
+ int nearest_vert_in_other_mesh_count;
+ float nearest_vert_in_other_mesh_x;
+ float nearest_vert_in_other_mesh_y;
+ float nearest_vert_in_other_mesh_z;
+ Vert nearest_vert_in_other_mesh;
+ Matrix binding = new Matrix();
+ float oldscore = 0;
+ boolean inserted = false;
+
+ public Matrix quadric() {
+ Matrix m = new Matrix(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+ E e = this.e;
+ do {
+ T t = e.t;
+ m = m.plus(t.norm().fundamentalQuadric(t.centroid()));
+ e = e.pair.next;
+ } while(e != this.e);
+ return m;
+ }
+
public Point getPoint() { return p; }
- private Vert(Point p, E e) { this(p); }
private Vert(Point p) {
this.p = p;
if (pointset.get(p) != null) throw new Error();
}
public float score() { return oldscore; }
public void unscore() {
- if (watch == null) return;
- watch.watch_x -= p.x;
- watch.watch_y -= p.y;
- watch.watch_z -= p.z;
- watch.watch_count--;
- if (watch.watch_count==0) {
- watch.watch_x = 0;
- watch.watch_y = 0;
- watch.watch_z = 0;
+ if (nearest_vert_in_other_mesh == null) return;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_x -= p.x;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_y -= p.y;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_z -= p.z;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_count--;
+ if (nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_count==0) {
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_x = 0;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_y = 0;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_z = 0;
}
- watch = null;
+ nearest_vert_in_other_mesh = null;
}
- public Vert partner() { return watch==null ? this : watch; }
- public Point watchback() { return watch_count==0 ? partner().p :
- new Point(watch_x/watch_count, watch_y/watch_count, watch_z/watch_count); }
+ public Vert partner() { return nearest_vert_in_other_mesh==null ? this : nearest_vert_in_other_mesh; }
+ public Point nearest_vert_in_other_mesh() { return nearest_vert_in_other_mesh_count==0 ? partner().p :
+ new Point(nearest_vert_in_other_mesh_x/nearest_vert_in_other_mesh_count, nearest_vert_in_other_mesh_y/nearest_vert_in_other_mesh_count, nearest_vert_in_other_mesh_z/nearest_vert_in_other_mesh_count); }
public void rescore() {
if (score_against == null) return;
score -= oldscore;
oldscore = 0;
- if (watch != null) unscore();
+ if (nearest_vert_in_other_mesh != null) unscore();
Vert po = this;
- if (watch == null) {
- watch = score_against.nearest(po.p);
+ if (nearest_vert_in_other_mesh == null) {
+ nearest_vert_in_other_mesh = score_against.nearest(po.p);
// don't attract to vertices that face the other way
- if (watch.e == null || watch.norm().dot(norm()) < 0) {
- watch = null;
+ if (nearest_vert_in_other_mesh.e == null || nearest_vert_in_other_mesh.norm().dot(norm()) < 0) {
+ nearest_vert_in_other_mesh = null;
} else {
- watch.watch_x += po.p.x;
- watch.watch_y += po.p.y;
- watch.watch_z += po.p.z;
- watch.watch_count++;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_x += po.p.x;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_y += po.p.y;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_z += po.p.z;
+ nearest_vert_in_other_mesh.nearest_vert_in_other_mesh_count++;
}
}
double s1, s2;
- if (watch_count==0) s1 = 0;
- else s1 = p.distance(watch_x/watch_count, watch_y/watch_count, watch_z/watch_count);
- s2 = watch==null ? 0 : po.p.distance(watch.p);
+ if (nearest_vert_in_other_mesh_count==0) s1 = 0;
+ else s1 = p.distance(nearest_vert_in_other_mesh_x/nearest_vert_in_other_mesh_count, nearest_vert_in_other_mesh_y/nearest_vert_in_other_mesh_count, nearest_vert_in_other_mesh_z/nearest_vert_in_other_mesh_count);
+ s2 = nearest_vert_in_other_mesh==null ? 0 : po.p.distance(nearest_vert_in_other_mesh.p);
oldscore = (float)(s1 + s2);
score += oldscore;
}
/** does NOT update bound pairs! */
public boolean transform(Matrix m) {
- // FIXME: screws up kdtree
- // FIXME: screws up hashmap
unscore();
try {
if (pointset.get(this.p)==null) throw new Error();
float newy = m.e*p.x + m.f*p.y + m.g*p.z + m.h;
float newz = m.i*p.x + m.j*p.y + m.k*p.z + m.l;
this.p = new Point(newx, newy, newz);
- // FIXME: what if we move onto exactly where another point is?
pointset.add(this);
} catch (Exception e) {
throw new RuntimeException(e);
} while(e != this.e);
return norm.norm();
}
-
- Vert bound_to = this;
- int watch_count;
- float watch_x;
- float watch_y;
- float watch_z;
- Vert watch;
- E e; // some edge *leaving* this point
- Matrix binding = new Matrix();
- float oldscore = 0;
- boolean inserted = false;
}
/** [UNIQUE] an edge */
E next; // next half-edge
E pair; // partner half-edge
public BindingGroup bg = new BindingGroup(this);
+ boolean shattered = false;
public int compareTo(E e) { return e.length() > length() ? 1 : -1; }
}
}
- boolean shattered = false;
public Point shatter() { return shatter(midpoint(), null, null); }
public Point shatter(Point mid, BindingGroup bg1, BindingGroup bg2) {
if (shattered) return mid;
public E(Point p1, Point p2) {
if (pointset.get(p1) != null) throw new Error();
if (pointset.get(p2) != null) throw new Error();
- this.p1 = new Vert(p1, this);
- this.p2 = new Vert(p2, this);
+ this.p1 = new Vert(p1);
+ this.p2 = new Vert(p2);
this.prev = this.next = this.pair = new E(this, this, this);
+ this.p1.e = this;
+ this.p2.e = this.pair;
sync();
}
public E(E prev, Point p) {
Vert p2;
p2 = pointset.get(p);
- if (p2 == null) p2 = new Vert(p, this);
+ if (p2 == null) p2 = new Vert(p);
this.p1 = prev.p2;
this.p2 = p2;
this.prev = prev;
this.prev.next = this;
this.pair = new E(q, this, z);
}
+ if (p2.e==null) p2.e = this.pair;
sync();
}
}
}
- private Vert register(Point p) {
- Vert v = pointset.get(p);
- return v==null ? new Vert(p) : v;
- }
public E makeE(Point p1, Point p2) {
Vert v1 = pointset.get(p1);
Vert v2 = pointset.get(p2);