public class Mesh implements Iterable<Mesh.T> {
- private KDTree kd = new KDTree(3);
-
public static float EPSILON = (float)0.0001;
public static Random random = new Random();
- private HashMap<Point,Vert> ps = new HashMap<Point,Vert>();
- public HashSet<E> es = new HashSet<E>();
+ private PointSet<Vert> pointset = new PointSet<Vert>();
+ public Vert nearest(Point p) { return pointset.nearest(p); }
+ private HashMap<Point,Vert> verts = new HashMap<Point,Vert>();
+
+ public Iterable<E> edges() {
+ return
+ new Iterable<E>() {
+ public Iterator<E> iterator() {
+ // HACK
+ HashSet<E> hse = new HashSet<E>();
+ for(T t : Mesh.this) {
+ hse.add(t.e1());
+ hse.add(t.e2());
+ hse.add(t.e3());
+ hse.add(t.e1().pair);
+ hse.add(t.e2().pair);
+ hse.add(t.e3().pair);
+ }
+ return hse.iterator();
+ } };
+ }
public Iterator<T> iterator() {
- if (es.size() == 0) return new FaceIterator();
- return new FaceIterator(es.iterator().next().p1);
+ for(Vert v : pointset)
+ if (v.e != null && v.e.t != null)
+ return new FaceIterator(v);
+ return new FaceIterator();
}
public Point origin() { return new Point(0, 0, 0); }
done.add(p);
p.rescore();
}
+ /*
for(T t : this)
for(Vert p : new Vert[] { t.v1(), t.v2(), t.v3() })
p.kdremove();
- kd = new KDTree(3);
+ pointset.clear();
for(T t : this)
for(Vert p : new Vert[] { t.v1(), t.v2(), t.v3() })
p.kdinsert();
+ */
return (float)(dist/num);
}
public void transform(Matrix m) {
ArrayList<Vert> set = new ArrayList<Vert>();
- set.addAll(ps.values());
+ for (Vert v : pointset)
+ set.add(v);
for(Vert v : set) v.transform(m);
}
- public Vec diagonal() {
- float min_x = Float.MAX_VALUE;
- float min_y = Float.MAX_VALUE;
- float min_z = Float.MAX_VALUE;
- float max_x = Float.MIN_VALUE;
- float max_y = Float.MIN_VALUE;
- float max_z = Float.MIN_VALUE;
- for(Point p : ps.keySet()) {
- if (p.x < min_x) min_x = p.x;
- if (p.y < min_y) min_y = p.y;
- if (p.z < min_z) min_z = p.z;
- if (p.x > max_x) max_x = p.x;
- if (p.y > max_y) max_y = p.y;
- if (p.z > max_z) max_z = p.z;
- }
- return new Vec(max_x - min_x, max_y - min_y, max_z - min_z);
- }
-
- public Point centroid() {
- float min_x = Float.MAX_VALUE;
- float min_y = Float.MAX_VALUE;
- float min_z = Float.MAX_VALUE;
- float max_x = Float.MIN_VALUE;
- float max_y = Float.MIN_VALUE;
- float max_z = Float.MIN_VALUE;
- for(Point p : ps.keySet()) {
- if (p.x < min_x) min_x = p.x;
- if (p.y < min_y) min_y = p.y;
- if (p.z < min_z) min_z = p.z;
- if (p.x > max_x) max_x = p.x;
- if (p.y > max_y) max_y = p.y;
- if (p.z > max_z) max_z = p.z;
- }
- return new Point((float)(max_x + min_x)/2,
- (float)(max_y + min_y)/2,
- (float)(max_z + min_z)/2);
- }
+ public Vec diagonal() { return pointset.diagonal(); }
+ public Point centroid() { return pointset.centroid(); }
public float volume() {
double total = 0;
return (float)total;
}
- public Vert nearest(Point p) {
- Object[] results;
- try { results = kd.nearest(new double[]{p.x,p.y,p.z},1); } catch (Exception e) { throw new Error(e); }
- return (Vert)results[0];
- }
public class BindingGroup {
public HashSet<E> es = new HashSet<E>();
}
}
- public Vert register(Point p) { Vert v = ps.get(p); return v==null ? new Vert(p) : v; }
- public final class Vert {
+ public Vert register(Point p) { Vert v = verts.get(p); return v==null ? new Vert(p) : v; }
+ public final class Vert extends HasPoint {
public Point p;
+ public Point getPoint() { return p; }
private Vert(Point p) {
this.p = p;
- if (ps.get(p) != null) throw new Error();
- ps.put(this.p, this);
+ if (verts.get(p) != null) throw new Error();
+ verts.put(this.p, this);
+ pointset.add(this);
+ }
+ public void reinsert() {
+ pointset.remove(this);
+ pointset.add(this);
}
public void kdremove() {
if (!inserted) return;
inserted = false;
- try { kd.delete(new double[]{p.x,p.y,p.z}); } catch (Exception e) { }
+ pointset.remove(this);
}
public void kdinsert() {
if (inserted) return;
inserted = true;
- try { kd.insert(new double[]{p.x,p.y,p.z},this); } catch (Exception e) { throw new Error(e); }
+ pointset.add(this);
}
public float score() { return oldscore; }
watch = score_against.nearest(po.p);
// don't attract to vertices that face the other way
- if (watch.norm().dot(norm()) < 0) {
+ if (watch.e == null || watch.norm().dot(norm()) < 0) {
watch = null;
} else {
watch.watch_x += po.p.x;
// FIXME: screws up hashmap
unscore();
try {
- if (ps.get(this.p)==null) throw new Error();
- ps.remove(this.p);
+ if (verts.get(this.p)==null) throw new Error();
+ verts.remove(this.p);
+ pointset.remove(this);
float newx = m.a*p.x + m.b*p.y + m.c*p.z + m.d;
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?
- ps.put(this.p,(Vert)this);
+ pointset.add(this);
+ verts.put(this.p,(Vert)this);
} catch (Exception e) {
throw new RuntimeException(e);
}
pair.next = prev;
if (p1.e == this) p1.e = prev.next;
if (pair.p1.e == pair) pair.p1.e = pair.prev.next;
- es.remove(this);
- es.remove(pair);
avgedge -= this.length();
avgedge -= pair.length();
numedges--;
if (this.next.p1 != p2) throw new Error();
if (this.prev.p2 != p1) throw new Error();
if (this.p1.e == null) this.p1.e = this;
- es.add(this);
if (!added) {
added = true;
numedges++;
if (norm != null) {
Vec norm2 = p3.p.minus(p1.p).cross(p2.p.minus(p1.p));
float dot = norm.dot(norm2);
- //if (Math.abs(dot) < EPointSILON) throw new Error("dot products within epsilon of each other: "+norm+" "+norm2);
+ //if (Math.abs(dot) < EPointSILON) throw new Error("dot products within evertsilon of each other: "+norm+" "+norm2);
if (dot < 0) { Vert p = p1; p1=p2; p2 = p; }
}
E e12 = p1.makeE(p2);