package edu.berkeley.qfat;
import java.awt.*;
+import java.io.*;
import java.awt.event.*;
import javax.swing.*;
import javax.media.opengl.*;
// FIXME: re-orient goal (how?)
-public class Main extends MeshViewer {
+public class Main extends InteractiveMeshViewer {
public static int verts = 1;
HashSet<HalfSpace> halfSpaces = new HashSet<HalfSpace>();
HashSet<Polygon> polygons = new HashSet<Polygon>();
for(Matrix m : matrices) {
- Vec v = m.getTranslationalComponent();
- if (v.mag() < 0.0001) continue;
- v = v.times(0.5f);
- Point p = Point.ORIGIN.plus(v);
- Vec v0 = v;
- if (v.dot(Point.ORIGIN.minus(p)) < 0) v = v.times(-1);
-
- System.out.println(v);
- HalfSpace hs = new HalfSpace(p, v.norm());
- halfSpaces.add(hs);
- polygons.add(new Polygon(hs));
+ Vec v = m.getTranslationalComponent();
+ if (v.mag() < 0.0001) continue;
+ v = v.times(-1);
+ v = v.times(0.5f);
+ Point p = Point.ORIGIN.plus(v);
+ v = v.times(-1);
+
+ //System.out.println(v);
+ HalfSpace hs = new HalfSpace(p, v.norm());
+ halfSpaces.add(hs);
+ polygons.add(new Polygon(hs));
}
for(Polygon p : polygons) {
System.out.println(p.plane.norm + " " + p.plane.dvalue);
public void loadGoal(String file) {
try {
StlFile stlf = new StlFile();
- stlf.load(file);
+ InputStream res = this.getClass().getClassLoader().getResourceAsStream(file);
+ stlf.readBinaryFile(file, res);
goal = new Mesh(false);
for(int i=0; i<stlf.coordArray.length; i+=3) {
Point p0 = new Point(stlf.coordArray[i+0].x * MAG, stlf.coordArray[i+0].y * MAG, stlf.coordArray[i+0].z * MAG);
Point p1 = new Point(stlf.coordArray[i+1].x * MAG, stlf.coordArray[i+1].y * MAG, stlf.coordArray[i+1].z * MAG);
Point p2 = new Point(stlf.coordArray[i+2].x * MAG, stlf.coordArray[i+2].y * MAG, stlf.coordArray[i+2].z * MAG);
- Vec n = new Vec(stlf.normArray[i/3].x * MAG, stlf.normArray[i/3].y * MAG, stlf.normArray[i/3].z * MAG);
+ Vec n = new Vec(stlf.normArray[i/3].x * MAG, stlf.normArray[i/3].y * MAG, stlf.normArray[i/3].z * MAG);
Mesh.T t = goal.newT(p0, p1, p2, n, 0);
}
float goal_width = goal.diagonal().dot(new Vec(1, 0, 0));
} catch (Exception e) { throw new RuntimeException(e);}
}
- public void fixupGoal() {
+ public void fixupGoal() { fixupGoal(true, true); }
+ public void fixupGoal(boolean recenter, boolean lock) {
// translate to match centroid
- goal.transform(Matrix.translate(tile.centroid().minus(goal.centroid())));
- goal.makeVerticesImmutable();
- tile.error_against = goal;
- goal.error_against = tile;
+ if (recenter)
+ goal.transform(Matrix.translate(tile.centroid().minus(goal.centroid())));
+ if (lock) {
+ goal.makeVerticesImmutable();
+ tile.error_against = goal;
+ goal.error_against = tile;
+ }
}
public Main(JFrame f) { super(f); }
for(Mesh.T t2 : tile) {
Matrix m = m1.inverse().times(m2);
- if ((t1.v1().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
- (t1.v2().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON) &&
- (t1.v3().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON)) {
+ Point t1v1 = m.times(t1.v1().p);
+ Point t1v2 = m.times(t1.v2().p);
+ Point t1v3 = m.times(t1.v3().p);
+ if (t1v1.distance(t2.v1().p) < MATCHING_EPSILON &&
+ t1v2.distance(t2.v3().p) < MATCHING_EPSILON &&
+ t1v3.distance(t2.v2().p) < MATCHING_EPSILON) {
t2.e3().bindEdge(t1.e1(), m);
t2.e2().bindEdge(t1.e2(), m);
t2.e1().bindEdge(t1.e3(), m);
}
- if ((t1.v2().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
- (t1.v3().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON) &&
- (t1.v1().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON)) {
+ if (t1v2.distance(t2.v1().p) < MATCHING_EPSILON &&
+ t1v3.distance(t2.v3().p) < MATCHING_EPSILON &&
+ t1v1.distance(t2.v2().p) < MATCHING_EPSILON) {
t2.e3().bindEdge(t1.e2(), m);
t2.e2().bindEdge(t1.e3(), m);
t2.e1().bindEdge(t1.e1(), m);
}
- if ((t1.v3().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
- (t1.v1().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON) &&
- (t1.v2().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON)) {
+ if (t1v3.distance(t2.v1().p) < MATCHING_EPSILON &&
+ t1v1.distance(t2.v3().p) < MATCHING_EPSILON &&
+ t1v2.distance(t2.v2().p) < MATCHING_EPSILON) {
t2.e3().bindEdge(t1.e3(), m);
t2.e2().bindEdge(t1.e1(), m);
t2.e1().bindEdge(t1.e2(), m);
}
-
- if ((t1.v1().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
- (t1.v2().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON) &&
- (t1.v3().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON)) {
+ if (t1v1.distance(t2.v1().p) < MATCHING_EPSILON &&
+ t1v2.distance(t2.v2().p) < MATCHING_EPSILON &&
+ t1v3.distance(t2.v3().p) < MATCHING_EPSILON) {
t2.e1().bindEdge(t1.e1().pair, m);
t2.e2().bindEdge(t1.e2().pair, m);
t2.e3().bindEdge(t1.e3().pair, m);
}
- if ((t1.v2().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
- (t1.v3().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON) &&
- (t1.v1().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON)) {
+ if (t1v2.distance(t2.v1().p) < MATCHING_EPSILON &&
+ t1v3.distance(t2.v2().p) < MATCHING_EPSILON &&
+ t1v1.distance(t2.v3().p) < MATCHING_EPSILON) {
t2.e2().bindEdge(t1.e1().pair, m);
t2.e3().bindEdge(t1.e2().pair, m);
t2.e1().bindEdge(t1.e3().pair, m);
}
- if ((t1.v3().p.times(m).distance(t2.v1().p) < MATCHING_EPSILON) &&
- (t1.v1().p.times(m).distance(t2.v2().p) < MATCHING_EPSILON) &&
- (t1.v2().p.times(m).distance(t2.v3().p) < MATCHING_EPSILON)) {
+ if (t1v3.distance(t2.v1().p) < MATCHING_EPSILON &&
+ t1v1.distance(t2.v2().p) < MATCHING_EPSILON &&
+ t1v2.distance(t2.v3().p) < MATCHING_EPSILON) {
t2.e3().bindEdge(t1.e1().pair, m);
t2.e1().bindEdge(t1.e2().pair, m);
t2.e2().bindEdge(t1.e3().pair, m);
}
-
}
}
}
public void breakit() {
int oldverts = verts;
+ if (verts > 2000 && !force) return;
+ force = false;
System.out.println("doubling vertices.");
PriorityQueue<Mesh.E> es = new PriorityQueue<Mesh.E>();
for(Mesh.T t : tile) {
Thread.yield();
repaint();
}
+ System.out.println("now have " + verts + " vertices; max is 2000");
tile.rebindPoints();
}
//boolean doSwap = good && (tile_delta + goal_delta <= 0);
//if (temp < 0.000001) doSwap = good && (tile_delta <= 0 && goal_delta <= 0);
boolean doSwap = good && (Math.random() < swapProbability);
+
+ // always move uphill if possible -- potential idea
+ if (tile_delta <= 0 && goal_delta <= 0 && good) doSwap = true;
+ if (hillclimb)
+ doSwap = tile_delta <= 0 && goal_delta <= 0 && good;
+
if (doSwap) {
tile_error = new_tile_error;
goal_error = new_goal_error;
boolean seek_upward = false;
double acceptance = 1;
while(true) {
+ synchronized(this) {
synchronized(safeTriangles) {
safeTriangles.clear();
for(Mesh.T t : tile)
else if (acceptance > 0.3) gamma = 0.8f;
else if (acceptance > 0.15) gamma = 0.94f;
else if (acceptance > 0.10) gamma = 0.98f;
- else { breaks++; }
+
+ else if (acceptance < 0.01) breaks++;
if (seek_upward) {
if (acceptance > 0.25) seek_upward = false;
p.quadricStale = true;
p.recomputeFundamentalQuadricIfNeighborChanged();
}
+ }
}
}
hideMenu.add(new MyMenuItem("Show All Neighbors Wireframe") { public void hit() { neighborsWire = true; neighborsWireOne = false;}});
hideMenu.add(new MyMenuItem("Hide Neighbors") { public void hit() { neighborsWire = false; neighborsWireOne = false; neighbors = false; }});
+ goalMenu.add(new MyMenuItem("Fish with face") { public void hit() {
+ loadGoal("face.stl");
+ //goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
+ goal.transform(Matrix.rotate(new Vec(0, 0, 1), (float)(Math.PI/2)));
+ //goal.transform(Matrix.scale(1, 2.2f, 1));
+ float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
+ //factor = factor * 0.8f;
+ goal.transform(Matrix.scale(0.3f));
+ //goal.transform(Matrix.rotate(new Vec(0,1,0), (float)(Math.PI*1/3)));
+ goal.transform(Matrix.rotate(new Vec(1,0,0), (float)(Math.PI*1/3)));
+ fixupGoal(true, false);
+ //goal.transform(Matrix.translate(new Vec(0.145f, 0, 0)));
+ fixupGoal(false, true);
+ }});
goalMenu.add(new MyMenuItem("Fish") { public void hit() {
loadGoal("fish.stl");
//goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
goal.transform(Matrix.rotate(new Vec(0, 0, 1), (float)(Math.PI/2)));
+ goal.transform(Matrix.scale(1, 2.2f, 1));
+ float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
+ factor = factor * 0.8f;
+ goal.transform(Matrix.scale(factor));
+ fixupGoal(true, false);
+ //goal.transform(Matrix.translate(new Vec(0.145f, 0, 0)));
+ fixupGoal(false, true);
+ }});
+ goalMenu.add(new MyMenuItem("Hammerhead Fish") { public void hit() {
+ loadGoal("fish.stl");
+ goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
+ goal.transform(Matrix.rotate(new Vec(0, 0, 1), (float)(3*Math.PI/2)));
float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
+ factor *= 0.75f;
goal.transform(Matrix.scale(factor));
fixupGoal();
}});
goalMenu.add(new MyMenuItem("Torus") { public void hit() {
loadGoal("torus.stl");
float factor = (float)Math.pow(tile.volume() / goal.volume(), 1.0/3.0);
- goal.transform(Matrix.scale(factor/3.3f));
+ goal.transform(Matrix.scale(factor/2.5f));
goal.transform(Matrix.rotate(new Vec(0, 1, 0), (float)(Math.PI/2)));
fixupGoal();
}});
};
fixupTile();
} });
- tileMenu.add(new MyMenuItem("Dense Packing (Hex)") { public void hit() {
+ tileMenu.add(new MyMenuItem("Dense Packing (hex)") { public void hit() {
tile = new Mesh(false);
float width = (float)3.2;
float depth = (float)0.32;
generateTile(transforms, tile);
fixupTile();
} });
- tileMenu.add(new MyMenuItem("Slim Dense Packing (Hex)") { public void hit() {
+ tileMenu.add(new MyMenuItem("Slim Dense Packing (Cubic)") { public void hit() {
tile = new Mesh(false);
- float width = (float)3.2;
- float depth = (float)0.32;
- float height = (float)1.6;
float unit = 0.4f;
float r = unit/2;
float sin = (float)(unit * Math.sin(Math.PI/3));
float cos = (float)(unit * Math.cos(Math.PI/3));
float x = (float)(r*Math.tan(Math.PI/6));
float z = (float)(r/Math.cos(Math.PI/6));
- height = 2*r*(float)Math.sqrt(2f/3f);
-
+ float height = 2*r*(float)Math.sqrt(2f/3f);
- r *= 0.3f;
- cos *= 0.3f;
- unit *= 0.3f;
- height *= 1.5f;
-
- /*
- sin *= 0.3f;
- x *= 0.3f;
- z *= 0.3f;
- */
transforms = new Matrix[] {
Matrix.translate(new Vec(-unit, 0, 0)),
Matrix.translate(new Vec( unit, 0, 0)),
Matrix.translate(new Vec( cos, 0, sin)),
Matrix.translate(new Vec(-cos, 0, -sin)),
Matrix.translate(new Vec( cos, 0, -sin)),
- Matrix.translate(new Vec( 0, height, z)),
- Matrix.translate(new Vec(-r, height, -x)),
- Matrix.translate(new Vec( r, height, -x)),
- Matrix.translate(new Vec( 0, -height, -z)),
- Matrix.translate(new Vec(-r, -height, x)),
- Matrix.translate(new Vec( r, -height, x)),
- Matrix.ONE,
+
+ /*
+ Matrix.translate(new Vec( 0, height, -z)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+ Matrix.translate(new Vec(-r, height, x)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+ Matrix.translate(new Vec( r, height, x)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+ Matrix.translate(new Vec( 0, -height, -z)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+ Matrix.translate(new Vec(-r, -height, x)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+ Matrix.translate(new Vec( r, -height, x)).times(Matrix.rotate(new Vec(0,1,0), (float)Math.PI)),
+ */
+
+ Matrix.translate(new Vec( 0, height, -z)),
+ Matrix.translate(new Vec(-r, height, x)),
+ Matrix.translate(new Vec( r, height, x)),
+ Matrix.translate(new Vec( 0, -height, z)),
+ Matrix.translate(new Vec(-r, -height, -x)),
+ Matrix.translate(new Vec( r, -height, -x)),
+ //Matrix.rotate(new Vec(0,0,1), (float)Math.PI),
+
+ /*
+ Matrix.translate(new Vec( 0, height, -z)).times(Matrix.scale(-1,1,-1)),
+ Matrix.translate(new Vec(-r, height, x)).times(Matrix.scale(-1,1,-1)),
+ Matrix.translate(new Vec( r, height, x)).times(Matrix.scale(-1,1,-1)),
+ Matrix.translate(new Vec( 0, -height, -z)).times(Matrix.scale(-1,1,-1)),
+ Matrix.translate(new Vec(-r, -height, x)).times(Matrix.scale(-1,1,-1)),
+ Matrix.translate(new Vec( r, -height, x)).times(Matrix.scale(-1,1,-1)),
+ */
+ Matrix.ONE
};
generateTile(transforms, tile);
+ //for(int i=0; i<transforms.length; i++) transforms[i] = Matrix.translate(m.times(vecs[i]));
+ Matrix m = Matrix.scale(1.9f, 1f ,1);
+ //Matrix m = Matrix.scale(1f, 2.1f, 1f);
+ tile.transform(m);
+ for(int i=0; i<transforms.length; i++)
+ transforms[i] = transforms[i].preMultiplyTranslationalComponentBy(m);
fixupTile();
+
} });
tileMenu.add(new MyMenuItem("Genus-1") { public void hit() {
synchronized(this) {
tile = new Mesh(false);
+ Matrix mm = Matrix.scale(0.1f);
float height = 4;
float width = 4;
float depth = 1;
- Matrix mm = Matrix.scale(0.1f);
// top
quad(tile, mm,
new Point( 2, 2, 0),
};
fixupTile();
}}});
+ tileMenu.add(new MyMenuItem("Hammerhead") { public void hit() {
+ synchronized(this) {
+ tile = new Mesh(false);
+ Matrix mm = Matrix.ONE;
+ float height1 = .1f;
+ float height2 = .1f;
+ float width = .4f;
+ float depth = .1f;
+ // top
+ Point a1 = new Point( -width/2, height2/2, -depth/2);
+ Point b1 = new Point( 0, height2/2, -depth/2);
+ Point c1 = new Point( 0, height1+height2/2, -depth/2);
+ Point d1 = new Point( width/2, height1+height2/2, -depth/2);
+ Point e1 = new Point( width/2, height2/2, -depth/2);
+ Point f1 = new Point( width/2, -height2/2, -depth/2);
+ Point g1 = new Point( width/2,-height1-height2/2, -depth/2);
+ Point h1 = new Point( 0,-height1-height2/2, -depth/2);
+ Point i1 = new Point( 0, -height2/2, -depth/2);
+ Point j1 = new Point( -width/2, -height2/2, -depth/2);
+ Point a2 = new Point( -width/2, height2/2, depth/2);
+ Point b2 = new Point( 0, height2/2, depth/2);
+ Point c2 = new Point( 0, height1+height2/2, depth/2);
+ Point d2 = new Point( width/2, height1+height2/2, depth/2);
+ Point e2 = new Point( width/2, height2/2, depth/2);
+ Point f2 = new Point( width/2, -height2/2, depth/2);
+ Point g2 = new Point( width/2,-height1-height2/2, depth/2);
+ Point h2 = new Point( 0,-height1-height2/2, depth/2);
+ Point i2 = new Point( 0, -height2/2, depth/2);
+ Point j2 = new Point( -width/2, -height2/2, depth/2);
+
+ quad(tile, mm, a1, b1, i1, j1);
+ quad(tile, mm, c1, d1, e1, b1);
+ quad(tile, mm, b1, e1, f1, i1);
+ quad(tile, mm, i1, f1, g1, h1);
+
+ quad(tile, mm, j2, i2, b2, a2);
+ quad(tile, mm, b2, e2, d2, c2);
+ quad(tile, mm, i2, f2, e2, b2);
+ quad(tile, mm, h2, g2, f2, i2);
+
+ quad(tile, mm, d1, d2, e2, e1);
+ quad(tile, mm, e1, e2, f2, f1);
+ quad(tile, mm, f1, f2, g2, g1);
+ quad(tile, mm, h1, g1, g2, h2);
+ quad(tile, mm, i2, i1, h1, h2);
+ quad(tile, mm, j1, i1, i2, j2);
+ quad(tile, mm, a2, a1, j1, j2);
+ quad(tile, mm, a1, a2, b2, b1);
+ quad(tile, mm, c2, c1, b1, b2);
+ quad(tile, mm, c1, c2, d2, d1);
+
+ transforms = new Matrix[] {
+
+ mm.times(Matrix.translate(new Vec( width, 0, 0))),
+ mm.times(Matrix.translate(new Vec( -width, 0, 0))),
+ mm.times(Matrix.translate(new Vec(-width/2, height1+height2, 0))),
+ mm.times(Matrix.translate(new Vec( width/2, height1+height2, 0))),
+ mm.times(Matrix.translate(new Vec(-width/2,-height1-height2, 0))),
+ mm.times(Matrix.translate(new Vec( width/2,-height1-height2, 0))),
+
+ mm.times(Matrix.translate(new Vec( width/2, 0, depth))),
+ mm.times(Matrix.translate(new Vec( -width/2, 0, depth))),
+ mm.times(Matrix.translate(new Vec( 0, height1+height2, depth))),
+ mm.times(Matrix.translate(new Vec( 0,-height1-height2, depth))),
+
+ mm.times(Matrix.translate(new Vec( width/2, 0, -depth))),
+ mm.times(Matrix.translate(new Vec( -width/2, 0, -depth))),
+ mm.times(Matrix.translate(new Vec( 0, height1+height2, -depth))),
+ mm.times(Matrix.translate(new Vec( 0,-height1-height2, -depth))),
+
+ Matrix.ONE
+ };
+ fixupTile();
+ }}});
// Finally, add all the menus to the menu bar.
add(tileMenu);