Commits

Karsten Schmidt committed 1d63a72

added HoleMountStrategy and color support for all elements, major refactoring of edge handling & label drawing is now aligned to edge direction

Comments (0)

Files changed (7)

src/flatworld/EdgeRenderStrategy.java

 package flatworld;
 
 import processing.core.PGraphics;
+import toxi.color.ReadonlyTColor;
+import toxi.color.TColor;
+import toxi.geom.Line2D;
 import toxi.geom.Vec2D;
 
 public abstract class EdgeRenderStrategy {
 
+    protected float labelInset = 15;
+
+    protected ReadonlyTColor labelColor = TColor.RED;
+    protected ReadonlyTColor edgeColor = TColor.BLACK;
+
     public abstract void drawEdge(PGraphics g, UnwrappedFace face,
             UnwrapEdge edge, Vec2D a, Vec2D b, boolean useLabels);
 
-    public void drawLabel(PGraphics g, UnwrapEdge edge, Vec2D pos) {
-        g.fill(0);
-        g.text(edge.getID() + "/" + edge.getUseCount(), pos.x, pos.y);
+    public void drawLabel(PGraphics g, UnwrappedFace face, UnwrapEdge edge,
+            Vec2D a, Vec2D b) {
+        Line2D l = new Line2D(a.copy(), b.copy());
+        l.offsetAndGrowBy(-labelInset, 1, face.sheetPos);
+        float theta = l.getDirection().heading();
+        Vec2D pos = l.getMidPoint();
+        g.fill(labelColor.toARGB());
+        g.pushMatrix();
+        g.translate(pos.x, pos.y);
+        g.rotate(theta);
+        g.text(edge.getID(), 0, 0);
+        g.popMatrix();
     }
 
-    public abstract float getWidthForEdge(UnwrapEdge edge);
+    /**
+     * @return the edgeColor
+     */
+    public ReadonlyTColor getEdgeColor() {
+        return edgeColor;
+    }
+
+    /**
+     * @return the labelColor
+     */
+    public ReadonlyTColor getLabelColor() {
+        return labelColor;
+    }
+
+    /**
+     * @return the labelInset
+     */
+    public float getLabelInset() {
+        return labelInset;
+    }
+
+    public abstract float getOffsetWidthForEdge(UnwrapEdge edge);
+
+    /**
+     * @param edgeColor
+     *            the edgeColor to set
+     */
+    public void setEdgeColor(ReadonlyTColor edgeColor) {
+        this.edgeColor = edgeColor;
+    }
+
+    /**
+     * @param labelColor
+     *            the labelColor to set
+     */
+    public void setLabelColor(ReadonlyTColor labelColor) {
+        this.labelColor = labelColor;
+    }
+
+    /**
+     * @param labelInset
+     *            the labelInset to set
+     */
+    public void setLabelInset(float labelInset) {
+        this.labelInset = labelInset;
+    }
+
 }

src/flatworld/GlueTabEdgeStrategy.java

 package flatworld;
 
 import processing.core.PGraphics;
+import toxi.color.NamedColor;
+import toxi.color.ReadonlyTColor;
 import toxi.geom.Line2D;
 import toxi.geom.Vec2D;
 
     public float width;
     public float insetPos;
 
+    public ReadonlyTColor tabColor = NamedColor.GRAY;
+
     public GlueTabEdgeStrategy(int w, float inset) {
         this.width = w;
         this.insetPos = inset;
         if (m.sub(face.sheetPos).dot(n) < 0) {
             n.invert();
         }
-        g.stroke(0);
         if (1 == edge.getUseCount() % 2) {
             Vec2D off = n.normalizeTo(width);
             g.noFill();
+            g.stroke(tabColor.toARGB());
             g.beginShape();
             g.vertex(a.x, a.y);
             Vec2D aa = a.interpolateTo(b, insetPos);
             g.vertex(b.x, b.y);
             g.endShape();
         }
+        g.stroke(edgeColor.toARGB());
         g.line(a.x, a.y, b.x, b.y);
         if (useLabels) {
-            m.subSelf(n.normalizeTo(8));
-            drawLabel(g, edge, m);
+            drawLabel(g, face, edge, a, b);
         }
     }
 
+    /**
+     * @return the insetPos
+     */
+    public float getInsetPos() {
+        return insetPos;
+    }
+
     @Override
-    public float getWidthForEdge(UnwrapEdge edge) {
+    public float getOffsetWidthForEdge(UnwrapEdge edge) {
         return 1 == edge.getUseCount() % 2 ? width : 0;
     }
 
+    /**
+     * @return the tabColor
+     */
+    public ReadonlyTColor getTabColor() {
+        return tabColor;
+    }
+
+    /**
+     * @return the width
+     */
+    public float getWidth() {
+        return width;
+    }
+
+    /**
+     * @param insetPos
+     *            the insetPos to set
+     */
+    public void setInsetPos(float insetPos) {
+        this.insetPos = insetPos;
+    }
+
+    /**
+     * @param tabColor
+     *            the tabColor to set
+     */
+    public void setTabColor(ReadonlyTColor tabColor) {
+        this.tabColor = tabColor;
+    }
+
+    /**
+     * @param width
+     *            the width to set
+     */
+    public void setWidth(float width) {
+        this.width = width;
+    }
+
 }

src/flatworld/HoleMountStrategy.java

+package flatworld;
+
+import processing.core.PConstants;
+import processing.core.PGraphics;
+import toxi.color.NamedColor;
+import toxi.color.ReadonlyTColor;
+import toxi.geom.Line2D;
+import toxi.geom.Vec2D;
+
+public class HoleMountStrategy extends EdgeRenderStrategy {
+
+    protected float radius;
+    protected float inset;
+    protected float distance;
+
+    protected ReadonlyTColor holeColor = NamedColor.CYAN;
+
+    public HoleMountStrategy(float radius, float inset, float distance) {
+        this.radius = radius;
+        this.inset = inset;
+        this.distance = distance;
+    }
+
+    @Override
+    public void drawEdge(PGraphics g, UnwrappedFace face, UnwrapEdge edge,
+            Vec2D a, Vec2D b, boolean useLabels) {
+        g.noFill();
+        g.ellipseMode(PConstants.RADIUS);
+        g.stroke(edgeColor.toARGB());
+        g.line(a.x, a.y, b.x, b.y);
+        Line2D l = new Line2D(a.copy(), b.copy());
+        float len = l.getLength();
+        float innerLen = (int) ((len - 2 * distance) / distance) * distance;
+        l.offsetAndGrowBy(-inset, -(len - innerLen) / 2, face.sheetPos);
+        Vec2D prev = null;
+        float minDist = (distance * 0.5f);
+        minDist *= minDist;
+        g.stroke(holeColor.toARGB());
+        for (Vec2D p : l.splitIntoSegments(null, distance, true)) {
+            if (prev == null
+                    || (prev != null && p.distanceToSquared(prev) > minDist)) {
+                g.ellipse(p.x, p.y, radius, radius);
+                prev = p;
+            }
+        }
+        if (useLabels) {
+            drawLabel(g, face, edge, a, b);
+        }
+    }
+
+    /**
+     * @return the holeColor
+     */
+    public ReadonlyTColor getHoleColor() {
+        return holeColor;
+    }
+
+    @Override
+    public float getOffsetWidthForEdge(UnwrapEdge edge) {
+        return 0;
+    }
+
+    /**
+     * @param holeColor
+     *            the holeColor to set
+     */
+    public void setHoleColor(ReadonlyTColor holeColor) {
+        this.holeColor = holeColor;
+    }
+
+}

src/flatworld/UnwrapEdge.java

     }
 
     public float getOffset() {
-        return strategy.getWidthForEdge(this);
+        return strategy.getOffsetWidthForEdge(this);
     }
 
     public int getUseCount() {

src/flatworld/UnwrapSheet.java

 
     protected Rect bounds;
 
+    protected List<UnwrappedFace> faces = new ArrayList<UnwrappedFace>();
+
+    protected float usedArea;
+
+    protected float totalArea;
+    protected float bleed = 10;
+
+    protected float faceBleed = 20;
+
     public UnwrapSheet(int w, int h) {
-        this.bounds = new Rect(bleed, bleed, w-2*bleed, h-2*bleed);
+        this.bounds = new Rect(bleed, bleed, w - 2 * bleed, h - 2 * bleed);
         this.totalArea = w * h;
     }
 
-    protected List<UnwrappedFace> faces = new ArrayList<UnwrappedFace>();
+    public void add(UnwrappedFace face) {
+        faces.add(face);
+        usedArea += face.getArea();
+    }
 
-    protected float usedArea;
-    protected float totalArea;
-
-    protected float bleed=10;
-    protected float faceBleed = 20;
-
-    public float getFreeArea() {
-        return totalArea - usedArea;
+    public void draw(PGraphics g, boolean showFaceLabels, boolean showEdgeLabels) {
+        for (UnwrappedFace f : faces) {
+            f.draw(g, showFaceLabels, showEdgeLabels);
+        }
     }
 
     public float getFillRatio() {
         return usedArea / totalArea;
     }
 
+    public float getFreeArea() {
+        return totalArea - usedArea;
+    }
+
     public Vec2D getRandomPos() {
         return new Vec2D(MathUtils.random(bounds.width),
                 MathUtils.random(bounds.height));
         if (bounds.containsPoint(b.getTopLeft())
                 && bounds.containsPoint(b.getBottomRight())) {
             for (UnwrappedFace f : faces) {
-                if (f.intersectsFace(face))
+                if (f.intersectsFace(face)) {
                     return false;
+                }
             }
             return true;
         } else {
             return false;
         }
     }
-
-    public void add(UnwrappedFace face) {
-        faces.add(face);
-        usedArea += face.getArea();
-    }
-
-    public void draw(PGraphics g, boolean useLabels) {
-        for (UnwrappedFace f : faces) {
-            f.draw(g,useLabels);
-        }
-    }
 }

src/flatworld/UnwrappedFace.java

         area = origTri.getArea();
     }
 
-    public void draw(PGraphics g, boolean useLabels) {
-        edgeAB.draw(g, this, tri.a, tri.b, useLabels);
-        edgeBC.draw(g, this, tri.b, tri.c, useLabels);
-        edgeCA.draw(g, this, tri.c, tri.a, useLabels);
+    public void draw(PGraphics g, boolean showFaceLabels, boolean showEdgeLabels) {
+        edgeAB.draw(g, this, tri.a, tri.b, showEdgeLabels);
+        edgeBC.draw(g, this, tri.b, tri.c, showEdgeLabels);
+        edgeCA.draw(g, this, tri.c, tri.a, showEdgeLabels);
+        // drawCollisionTriangle(g);
+        if (showFaceLabels) {
+            g.fill(0);
+            g.text(id, sheetPos.x, sheetPos.y);
+        }
+    }
+
+    private void drawCollisionTriangle(PGraphics g) {
         g.stroke(255, 0, 0);
         g.noFill();
         g.beginShape(PConstants.TRIANGLES);
         g.vertex(collTri.b.x, collTri.b.y);
         g.vertex(collTri.c.x, collTri.c.y);
         g.endShape();
-        if (useLabels) {
-            g.fill(0);
-            g.text(id, sheetPos.x, sheetPos.y);
-        }
     }
 
     public float getArea() {

src/flatworld/Unwrapper.java

         return edge;
     }
 
+    /**
+     * @return the edgeStrategy
+     */
+    public EdgeRenderStrategy getEdgeStrategy() {
+        return edgeStrategy;
+    }
+
+    /**
+     * @return the maxSearchIterations
+     */
+    public int getMaxSearchIterations() {
+        return maxSearchIterations;
+    }
+
     private float getMinDistanceOnSheet(UnwrappedFace face, UnwrapSheet sheet) {
         float minDist = Float.MAX_VALUE;
         for (UnwrappedFace f : sheet.faces) {
         return sheets;
     }
 
-    public void unwrapMesh(WETriangleMesh mesh, float scale,
-            EdgeRenderStrategy edgeStrategy) {
+    /**
+     * @param edgeStrategy
+     *            the edgeStrategy to set
+     */
+    public void setEdgeStrategy(EdgeRenderStrategy edgeStrategy) {
         this.edgeStrategy = edgeStrategy;
+    }
+
+    /**
+     * @param maxSearchIterations
+     *            the maxSearchIterations to set
+     */
+    public void setMaxSearchIterations(int maxSearchIterations) {
+        this.maxSearchIterations = maxSearchIterations;
+    }
+
+    public void unwrapMesh(WETriangleMesh mesh, float scale) {
         sheets.clear();
         int id = 1;
         usedEdges = new int[mesh.edges.size()];
             Vec2D bb = matrix.applyToSelf(fb.sub(centroid)).to2DXY();
             Vec2D cc = matrix.applyToSelf(fc.sub(centroid)).to2DXY();
             Triangle2D tri = new Triangle2D(aa, bb, cc);
+            // 2d triangle needs to be anti-clockwise for area & intersection
+            // tests
             if (tri.isClockwise()) {
                 tri.flipVertexOrder();
                 Vec3D t = fa;