- if (verts.get(p) != null) throw new Error();
- verts.put(this.p, this);
- }
- public void kdremove() {
- if (!inserted) return;
- inserted = false;
- try { kd.delete(new double[]{p.x,p.y,p.z}); } catch (Exception e) { }
- }
- 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); }
- }
-
- 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;
- }
- watch = null;
- }
- public Vert partner() { return watch==null ? this : watch; }
- public Vert watchback() { return watch_count==0 ? partner() :
- register(new Point(watch_x/watch_count, watch_y/watch_count, watch_z/watch_count)); }
- public void rescore() {
- if (score_against == null) return;
-
- score -= oldscore;
- oldscore = 0;
-
- if (watch != null) unscore();
- Vert po = this;
- if (watch == null) {
- watch = score_against.nearest(po.p);
-
- // don't attract to vertices that face the other way
- if (watch.norm().dot(norm()) < 0) {
- watch = null;
+ this.goodp = p;
+ this.oldp = p;
+ if (vertices.get(p) != null) throw new Error();
+ vertices.add(this);
+ }
+
+ public void reinsert() {
+ vertices.remove(this);
+ vertices.add(this);
+ for(E e = this.e; e!=null; e=e.pair.next==this.e?null:e.pair.next) e.t.reinsert();
+ }
+
+ // the average of all adjacent points
+ public Point recenter() {
+ int count = 0;
+ Vec vec = Vec.ZERO;
+ for(E e = this.e; e!=null; e=e.pair.next==this.e?null:e.pair.next) {
+ vec = vec.plus(e.getOther(this).getPoint().minus(Point.ZERO));
+ count++;
+ }
+ return Point.ZERO.plus(vec.div(count));
+ }
+
+ public float olderror = 0;
+ public void setError(float nerror) {
+ error -= olderror;
+ olderror = nerror;
+ error += olderror;
+ }
+
+ /*
+ public Vertex hack(GL gl, Point mouse) {
+ double dist = Double.MAX_VALUE;
+ Vertex cur = null;
+ for(E e = this.e; e!=null; e=e.pair.next==this.e?null:e.pair.next) {
+ Vertex v = e.getOther(this);
+ double dist2 = v.getPoint().glProject(gl).distance(mouse);
+ if ((cur==null || dist2 < dist) && v.visible) {
+ dist = dist2;
+ cur = v;
+ }
+ }
+ return cur;
+ }
+ */
+
+ public float averageTriangleArea() {
+ int count = 0;
+ float ret = 0;
+ for(E e = this.e; e!=null; e=e.pair.next==this.e?null:e.pair.next) {
+ ret += e.t.area();
+ count++;
+ }
+ return ret/count;
+ }
+ public float averageEdgeLength() {
+ int count = 0;
+ float ret = 0;
+ for(E e = this.e; e!=null; e=e.pair.next==this.e?null:e.pair.next) {
+ ret += e.length();
+ count++;
+ }
+ return ret/count;
+ }
+
+ public Matrix _recomputeFundamentalQuadric() {
+ Matrix m = Matrix.ZERO;
+ int count = 0;
+ for(E e = this.e; e!=null; e=e.pair.next==this.e?null:e.pair.next) {
+ m = m.plus(e.t.norm().fundamentalQuadric(e.t.centroid()));
+ count++;
+ }
+ if (count > 0) {
+ m = m.plus(norm().fundamentalQuadric(this.p).times(count));
+ count *= 2;
+ }
+ return m.times(1/(float)count);
+ }
+
+ public HasQuadric nearest() { return error_against==null ? null : error_against.vertices.nearest(p, this); }
+ public void computeError() {
+ if (error_against==null) return;
+ if (nearest_in_other_mesh == null && nearest()==null) return;
+ float nerror =
+ nearest_in_other_mesh != null
+ ? nearest_in_other_mesh.fundamentalQuadric().preAndPostMultiply(p)
+ : nearest().fundamentalQuadric().preAndPostMultiply(p);
+ if (quadric_count != 0)
+ nerror = (nerror + quadric.preAndPostMultiply(p))/(quadric_count+1);
+
+ if (!immutableVertices && quadric_count == 0) {
+ //nerror = Math.max(nerror, 0.4f);
+ //nerror *= 2;
+ }
+ //System.out.println(nerror);
+ for(E e = this.e; e!=null; e=e.pair.next==this.e?null:e.pair.next) {
+ double ang = e.dihedralAngle();
+ if (ang > Math.PI) throw new Error();
+ if (ang < -Math.PI) throw new Error();
+ float minangle = (float)(Math.PI * 0.8);
+ //nerror += ((ang / Math.PI)*(ang/Math.PI)) * e.length() * 0.05;
+
+ //nerror += (1-e.t.quality())*0.0001;
+ if (ang > minangle) nerror += (ang - minangle);
+
+ //System.out.println(((ang / Math.PI)*(ang/Math.PI)) * 0.000001);
+ /*
+ if (e.t.aspect() < 0.2) {
+ nerror += (0.2-e.t.aspect()) * 10;
+ }
+ */
+ }
+ if (!immutableVertices) {
+ Vertex n = (Vertex)nearest();
+ float d = norm().dot(n.norm());
+ if (d > 1 || d < -1) throw new Error();
+ if (d >= 0) {
+ nerror *= (2.0f - d);