X-Git-Url: http://git.megacz.com/?p=anneal.git;a=blobdiff_plain;f=src%2Fedu%2Fberkeley%2Fqfat%2FMesh.java;h=0a26699d8f7623ae87bb1a762a4016e24f24bca4;hp=aa2e9211b17950b7f47b99089adc10ba57cf52e2;hb=ef71dffc8c85bae1d65ca44cfaef8698f83ca1eb;hpb=f569231a23ceb2881c9720a8e8711c7aaaed05d4 diff --git a/src/edu/berkeley/qfat/Mesh.java b/src/edu/berkeley/qfat/Mesh.java index aa2e921..0a26699 100644 --- a/src/edu/berkeley/qfat/Mesh.java +++ b/src/edu/berkeley/qfat/Mesh.java @@ -16,11 +16,32 @@ public class Mesh implements Iterable { public static float EPSILON = (float)0.0001; public static Random random = new Random(); - private HashMap ps = new HashMap(); - public HashSet es = new HashSet(); - public ArrayList ts = new ArrayList(); + private HashMap verts = new HashMap(); + + public Iterable edges() { + return + new Iterable() { + public Iterator iterator() { + // HACK + HashSet hse = new HashSet(); + 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 iterator() { return ts.iterator(); } + public Iterator iterator() { + for(Vert v : verts.values()) + if (v.e != null && v.e.t != null) + return new FaceIterator(v); + return new FaceIterator(); + } public Point origin() { return new Point(0, 0, 0); } @@ -51,17 +72,17 @@ public class Mesh implements Iterable { int num = 0; double dist = 0; HashSet done = new HashSet(); - for(T t : ts) + for(T t : this) for(Vert p : new Vert[] { t.v1(), t.v2(), t.v3() }) { if (done.contains(p)) continue; done.add(p); p.rescore(); } - for(T t : ts) + for(T t : this) for(Vert p : new Vert[] { t.v1(), t.v2(), t.v3() }) p.kdremove(); kd = new KDTree(3); - for(T t : ts) + for(T t : this) for(Vert p : new Vert[] { t.v1(), t.v2(), t.v3() }) p.kdinsert(); return (float)(dist/num); @@ -69,7 +90,7 @@ public class Mesh implements Iterable { public void transform(Matrix m) { ArrayList set = new ArrayList(); - set.addAll(ps.values()); + set.addAll(verts.values()); for(Vert v : set) v.transform(m); } @@ -80,7 +101,7 @@ public class Mesh implements Iterable { float max_x = Float.MIN_VALUE; float max_y = Float.MIN_VALUE; float max_z = Float.MIN_VALUE; - for(Point p : ps.keySet()) { + for(Point p : verts.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; @@ -98,7 +119,7 @@ public class Mesh implements Iterable { float max_x = Float.MIN_VALUE; float max_y = Float.MIN_VALUE; float max_z = Float.MIN_VALUE; - for(Point p : ps.keySet()) { + for(Point p : verts.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; @@ -113,7 +134,7 @@ public class Mesh implements Iterable { public float volume() { double total = 0; - for(T t : ts) { + for(T t : this) { double area = t.area(); Vec origin_to_centroid = new Vec(new Point(0, 0, 0), t.centroid()); boolean facingAway = t.norm().dot(origin_to_centroid) > 0; @@ -148,13 +169,14 @@ public class Mesh implements Iterable { } } - 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); } public void kdremove() { if (!inserted) return; @@ -220,21 +242,21 @@ public class Mesh implements Iterable { // 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); 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); + verts.put(this.p,(Vert)this); } catch (Exception e) { throw new RuntimeException(e); } rescore(); boolean good = true; /* - for(T t : ts) { + for(T t : this) { for(E e = this.e; ;) { if (e.intersects(t)) { good = false; break; } e = e.pair.next; @@ -467,8 +489,6 @@ public class Mesh implements Iterable { pair.destroyed = true; if (next.t != null) next.t.destroy(); if (prev.t != null) prev.t.destroy(); - if (pair.next.t != null) ts.remove(pair.next.t); - if (pair.prev.t != null) ts.remove(pair.prev.t); next.t = null; prev.t = null; pair.next.t = null; @@ -481,8 +501,6 @@ public class Mesh implements Iterable { 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--; @@ -496,7 +514,6 @@ public class Mesh implements Iterable { 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++; @@ -581,7 +598,7 @@ public class Mesh implements Iterable { 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); @@ -599,32 +616,43 @@ public class Mesh implements Iterable { return ret; } + + public class FaceIterator implements Iterator { + private HashSet visited = new HashSet(); + private LinkedList next = new LinkedList(); + public FaceIterator() { } + public FaceIterator(Vert v) { next.addFirst(v.e.t); } + public boolean hasNext() { return next.peek()!=null; } + public void remove() { throw new Error(); } + public T next() { + T ret = next.removeFirst(); + if (ret == null) return null; + visited.add(ret); + T t1 = ret.e1().pair.t; + T t2 = ret.e2().pair.t; + T t3 = ret.e3().pair.t; + if (t1 != null && !visited.contains(t1)) next.addFirst(t1); + if (t2 != null && !visited.contains(t2)) next.addFirst(t2); + if (t3 != null && !visited.contains(t3)) next.addFirst(t3); + return ret; + } + } + /** [UNIQUE] a triangle (face) */ public final class T extends Triangle { public final E e1; public final int color; public void destroy() { - ts.remove(this); - } - - public Vert nearest(Point p) { - float d1 = v1().p.distance(p); - float d2 = v2().p.distance(p); - float d3 = v3().p.distance(p); - if (d1 < d2 && d1 < d3) return v1(); - if (d2 < d3) return v2(); - return v3(); } T(E e1) { this.e1 = e1; E e2 = e1.next; E e3 = e2.next; - if (e1==e2 || e1==e3) throw new Error(); + if (e1==e2 || e1==e3) throw new Error(); if (e3.next!=e1) throw new Error(); - if (e1.t!=null || e2.t!=null || e3.t!=null) - throw new Error("non-manifold surface or disagreeing normals"); + if (e1.t!=null || e2.t!=null || e3.t!=null) throw new Error("non-manifold surface or disagreeing normals"); e1.t = this; e1.next.t = this; e1.next.next.t = this; @@ -639,30 +667,23 @@ public class Mesh implements Iterable { if (e3().pair.t != null && color == e3().pair.t.color) { color++; continue; } break; } + this.color = color; - // FIXME unnecssary - ts.add(this); v1().kdinsert(); v2().kdinsert(); v3().kdinsert(); - - this.color = color; } + public E e1() { return e1; } + public E e2() { return e1.next; } + public E e3() { return e1.prev; } public Vert v1() { return e1.p1; } public Vert v2() { return e1.p2; } public Vert v3() { return e1.next.p2; } public Point p1() { return e1.p1.p; } public Point p2() { return e1.p2.p; } public Point p3() { return e1.next.p2.p; } - public E e1() { return e1; } - public E e2() { return e1.next; } - public E e3() { return e1.prev; } public boolean hasE(E e) { return e1==e || e1.next==e || e1.prev==e; } public boolean has(Vert v) { return v1()==v || v2()==v || v3()==v; } - - - } - }