Search in sources :

Example 21 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class VizSkelGen method toHalf.

private SuperFace toHalf(Loop<Point3d> loop) {
    Cache<Point3d, Point2d> look = new Cach<>(x -> Pointz.to2(x));
    HalfEdge last = null, first = null;
    SuperFace out = new SuperFace();
    for (Loopable<Point3d> edge : loop.loopableIterator()) {
        SuperEdge e = new SuperEdge(look.get(edge.get()), look.get(edge.getNext().get()), null);
        if (first == null)
            first = e;
        if (last != null)
            last.next = e;
        e.face = out;
        // !
        e.prof = null;
        e.mini = Collections.EMPTY_LIST;
        if (mode == Mode.Profiles)
            for (Line l : footprint) {
                if (l.absAngle(e.line()) < 0.1 && l.distance(e.start, true) < 1.5 && l.distance(e.end, true) < 1.5) {
                    SuperLine sl = (SuperLine) l;
                    MegaFacade mf = sl.getMega();
                    e.prof = findProf(e.start, e.end, sl, mf);
                }
            }
        last = e;
    }
    last.next = first;
    out.e = first;
    SkelFootprint.meanModeHeightColor(Loopz.toXZLoop(loop), out, blockGen);
    if (mode == Mode.CE) {
        for (HalfEdge ee : out) {
            SuperEdge e = (SuperEdge) ee;
            Matrix4d m = new Matrix4d();
            m.setIdentity();
            e.prof = new Prof(m, new Vector3d());
            e.prof.add(new Point2d(0, 0));
            e.prof.add(new Point2d(0, out.height));
            e.prof.add(new Point2d(-1, out.height + 1));
        }
    }
    return out;
}
Also used : MegaFacade(org.twak.tweed.gen.ProfileGen.MegaFacade) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) Line(org.twak.utils.Line) SuperLine(org.twak.viewTrace.SuperLine) Matrix4d(javax.vecmath.Matrix4d) Point2d(javax.vecmath.Point2d) Vector3d(javax.vecmath.Vector3d) Point3d(javax.vecmath.Point3d) SuperLine(org.twak.viewTrace.SuperLine) Cach(org.twak.utils.Cach)

Example 22 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class GurobiSkelSolver method solve.

public void solve() {
    try {
        for (HalfFace f : mesh.faces) for (HalfEdge e : f.edges()) {
            edges.add(e);
            totalEdgeLength += e.length();
        }
        print("total edge length " + totalEdgeLength);
        progress.setProgress((int) (Math.random() * 90));
        buildProblem();
        model.getEnv().set(GRB.DoubleParam.TimeLimit, GRB.INFINITY);
        long time = System.currentTimeMillis();
        new Thread(() -> {
            while (!gurobiDone) {
                try {
                    Thread.sleep(300);
                    if ((System.currentTimeMillis() - time) / 1000 > maxTimeSecs) {
                        print("time's up");
                        model.terminate();
                        progress.close();
                        return;
                    }
                } catch (InterruptedException e1) {
                }
                progress.setProgress((int) (Math.random() * 90));
                if (progress.isCanceled()) {
                    print("user cancelled");
                    model.terminate();
                }
            }
            progress.setProgress(100);
        }).start();
        try {
            String file = Tweed.SCRATCH + "problem_" + System.currentTimeMillis() + ".mps";
            new File(file).getParentFile().mkdirs();
            model.write(file);
            model.optimize();
        } finally {
            gurobiDone = true;
            progress.setProgress(100);
        }
        print("time " + (System.currentTimeMillis() - time) / 1000. + " seconds");
        if (model.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) {
            print("Can't solve; won't solve");
            return;
        }
        for (HalfFace f : mesh.faces) ((SuperFace) f).classification = index(faceInfo.get(f).color);
        if (minis != null)
            for (MegaFeatures mf : minis.keySet()) {
                if (mega2clusters.containsKey(mf))
                    for (MiniPtCluster pt : mega2clusters.get(mf)) {
                        for (Map.Entry<MFPoint, MiniSelectEdge> selectPt : pt.entrySet()) {
                            for (Map.Entry<HalfEdge, GRBVar> selectEdge : selectPt.getValue().edge.entrySet()) {
                                if (selectEdge.getValue().get(GRB.DoubleAttr.X) > 0.5) {
                                    HalfEdge e = selectEdge.getKey();
                                    selectPt.getKey().selectedEdge = e;
                                    selectPt.getKey().sameCluster = pt.keySet();
                                    if (e.over != null && e.next.over == null) {
                                        for (MFPoint p : pt.keySet()) ((SuperEdge) e.next).addMini(p.right);
                                        for (MFPoint p : pt.keySet()) ((SuperEdge) e.over.findBefore()).addMini(p.left);
                                    }
                                    if (e.over == null && e.next.over == null) {
                                        Line parallel = selectPt.getKey().mega.megafacade;
                                        if (parallel.absAngle(e.line()) < parallel.absAngle(e.next.line()))
                                            for (MFPoint p : pt.keySet()) ((SuperEdge) e).addMini(p.left);
                                        else
                                            for (MFPoint p : pt.keySet()) ((SuperEdge) e.next).addMini(p.right);
                                    }
                                }
                            }
                        }
                    }
            }
        if (false)
            for (HalfEdge he : edges) {
                if (he.over != null && he.next.over == null) {
                    // face comes to boundary
                    boolean viz = false;
                    EdgeVars ei = edgeInfo.get(he);
                    if (ei.edgeNoMini != null) {
                        viz = true;
                    }
                    if (viz)
                        PaintThing.debug.put("dd", new Point2d(he.end));
                }
            }
        if (globalProfs != null)
            for (HalfEdge e : edges) {
                EdgeVars ei = edgeInfo.get(e);
                GRBVar plot = ei.debug;
                if (plot != null) {
                    // && plot.get(GRB.DoubleAttr.X) > 0.5 ) {
                    Point2d o = new Point2d(e.end);
                    PaintThing.debug.put(1, o);
                }
                int p = index(ei.profile);
                ((SuperEdge) e).profI = p;
                ((SuperEdge) e).prof = p < 0 ? null : globalProfs.get(p);
            }
        dumpModelStats(edges);
        model.getEnv().dispose();
        model.dispose();
    } catch (GRBException e) {
        print("Error code: " + e.getErrorCode() + ". " + e.getMessage());
        e.printStackTrace();
    }
}
Also used : MegaFeatures(org.twak.tweed.gen.FeatureCache.MegaFeatures) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace) GRBException(gurobi.GRBException) Line(org.twak.utils.Line) Point2d(javax.vecmath.Point2d) MFPoint(org.twak.tweed.gen.FeatureCache.MFPoint) GRBVar(gurobi.GRBVar) File(java.io.File) HashMap(java.util.HashMap) Map(java.util.Map) MultiMap(org.twak.utils.collections.MultiMap)

Example 23 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class GurobiSkelSolver method buildProfiles.

private void buildProfiles() throws GRBException {
    for (HalfEdge e : edges) {
        if (// when a profile ends, we assume it can't start again...
        ((SuperEdge) e).profLine == null)
            continue;
        EdgeVars ev = edgeInfo.get(e);
        ev.profile = new GRBVar[globalProfs.size()];
        for (int p = 0; p < globalProfs.size(); p++) {
            ev.profile[p] = model.addVar(0.0, 1.0, 0, GRB.BINARY, PROFILE_SELECT);
            set(ev.profile[p], p == 0 ? 1 : 0);
        }
    }
    Cache2<HalfEdge, HalfEdge, GRBVar> isProfileDifferent = new Cache2<HalfMesh2.HalfEdge, HalfMesh2.HalfEdge, GRBVar>() {

        @Override
        public GRBVar create(HalfEdge e1, HalfEdge e2) {
            try {
                GRBVar s = model.addVar(0.0, 1.0, 0.0, GRB.BINARY, PROFILE_DIFFERENT);
                buildIsDifferentColor(s, edgeInfo.get(e1).profile, edgeInfo.get(e2).profile, "profile");
                s.set(DoubleAttr.Start, 0);
                return s;
            } catch (GRBException e) {
                e.printStackTrace();
            }
            return null;
        }
    };
    for (HalfEdge e1 : edges) {
        // if (e1.over != null)
        // continue;
        EdgeVars ev = edgeInfo.get(e1);
        if (ev.profile == null)
            continue;
        double[] fit = profFit.get(e1);
        GRBLinExpr pickOneProfile = new GRBLinExpr();
        for (int p = 0; p < globalProfs.size(); p++) {
            GRBVar a = ev.profile[p];
            pickOneProfile.addTerm(1, a);
            target.addTerm(.001 * fit[p] * e1.length(), a);
        }
        model.addConstr(pickOneProfile, GRB.EQUAL, 1, /*ev.isEdge*/
        "pick only one profile for " + e1);
        List<HalfEdge> atEnd = e1.collectAroundEnd();
        for (HalfEdge e2 : atEnd) {
            if (e1 != e2 && edgeInfo.get(e2).profile != null && // only constrain if ~parallel
            e1.line().absAngle(e2.line()) < 0.1) {
                GRBVar s = isProfileDifferent.get(e1, e2);
                // ev.debug = s;
                // Point2d dbg = new Point2d(e1.end);
                // dbg.add(new Point2d(Math.random() * 0.1, Math.random() * 0.1));
                GRBLinExpr perpIsEdge = new GRBLinExpr();
                for (HalfEdge e3 : atEnd) {
                    if (e3 == e1 || e3 == e2 || e3 == e1.over || e3 == e2.over || (e3.over != null && (e3.over == e1.over || e3.over == e2.over)))
                        continue;
                    if (!e1.line().isOnLeft(e1.end.distanceSquared(e3.start) > e1.end.distanceSquared(e3.end) ? e3.start : e3.end))
                        continue;
                    perpIsEdge.addTerm(1, edgeInfo.get(e3).isEdge);
                // PaintThing.debug.put(e2, dbg);
                // Point2d d2 = new Point2d(e3.line().dir());
                // d2.scale (0.1/new Vector2d(d2).length());
                // d2.add(dbg);
                // PaintThing.debug.put(e2, new Line (dbg, d2));
                // model.addConstr( s, GRB.LESS_EQUAL, edgeInfo.get(e3).isEdge, "only change profile if no adjacent edge "+e1 );
                }
                model.addConstr(s, GRB.LESS_EQUAL, perpIsEdge, "dont' change profile over " + e1);
            // PaintThing.debug.put(e2, dbg);
            // Point2d d2 = new Point2d(e2.line().dir());
            // d2.scale (0.2/new Vector2d(d2).length());
            // d2.add(dbg);
            // PaintThing.debug.put(e2, new Line (dbg, d2));
            }
        }
    }
    countNearbyProfiles = 0;
    if (false)
        for (int i = 0; i < edges.size(); i++) {
            HalfEdge e1 = edges.get(i);
            if (edgeInfo.get(e1).profile == null)
                continue;
            print("building edge locality term " + i + " / " + edges.size());
            for (HalfEdge e2 : edges) if (lt(e1, e2) && edgeInfo.get(e2).profile != null) {
                if (e1.line().distance(e2.line()) < 2) {
                    GRBVar s = isProfileDifferent.get(e1, e2);
                    target.addTerm(0.1 * (e1.length() + e2.length()), s);
                    countNearbyProfiles++;
                }
            }
        }
}
Also used : GRBLinExpr(gurobi.GRBLinExpr) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) GRBVar(gurobi.GRBVar) Cache2(org.twak.utils.Cache2) MFPoint(org.twak.tweed.gen.FeatureCache.MFPoint) HalfMesh2(org.twak.utils.geom.HalfMesh2) GRBException(gurobi.GRBException)

Example 24 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class GurobiSkelSolver method buildBadGeom.

private void buildBadGeom(boolean isContraint) throws GRBException {
    countBadCorners = countBadEdges = 0;
    for (HalfEdge e1 : edges) {
        if (e1.over != null && e1.next.over != null)
            if (e1.line().absAngle(e1.next.line()) > Math.PI - TweedSettings.settings.badGeomAngle) {
                notBoth(e1, e1.next, isContraint, totalEdgeLength * 0.5);
                countBadCorners++;
            }
    }
    // if over both h
    for (HalfFace f : mesh) {
        Set<HalfEdge> togo = new HashSet<>();
        for (HalfEdge e : f) togo.add(e);
        while (!togo.isEmpty()) {
            HalfEdge start = togo.iterator().next();
            togo.remove(start);
            // if (start.over == null)
            // continue;
            boolean parallelHasOverProfile = start.over == null ? false : ((SuperEdge) start.over).profLine != null, oppositeHasOverProfile = false;
            Line sl = start.line();
            LinearForm slf = new LinearForm(sl);
            Map<HalfFace, HalfEdge> parallel = new HashMap<>();
            parallel.put(start.over == null ? null : start.over.face, start);
            Iterator<HalfEdge> tig = togo.iterator();
            while (tig.hasNext()) {
                HalfEdge e2 = tig.next();
                HalfFace f2 = e2.over == null ? null : e2.over.face;
                if (sl.absAngle(e2.line()) < 0.05) {
                    // one from each non-f face
                    parallel.put(f2, e2);
                    tig.remove();
                    parallelHasOverProfile |= (e2.over != null && ((SuperEdge) e2.over).profLine != null);
                }
            }
            Map<HalfFace, HalfEdge> opposite = new HashMap();
            tig = togo.iterator();
            while (tig.hasNext()) {
                HalfEdge e2 = tig.next();
                HalfFace f2 = e2.over == null ? null : e2.over.face;
                if (// e2l.lengthSquared() > 1 &&
                sl.absAngle(e2.line()) > Math.PI - 0.3 && (slf.distance(e2.start) < 0.3 || slf.distance(e2.end) < 0.3)) {
                    opposite.put(f2, e2);
                    tig.remove();
                    oppositeHasOverProfile |= (e2.over != null && ((SuperEdge) e2.over).profLine != null);
                }
            }
            if (parallelHasOverProfile && oppositeHasOverProfile)
                continue;
            for (HalfEdge e1 : parallel.values()) for (HalfEdge e2 : opposite.values()) {
                notBoth(e1, e2, isContraint, totalEdgeLength * 0.5);
                countBadEdges++;
            }
        }
    }
    print(countBadCorners + " " + countBadEdges);
}
Also used : Line(org.twak.utils.Line) HashMap(java.util.HashMap) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) LinearForm(org.twak.utils.geom.LinearForm) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace) HashSet(java.util.HashSet)

Example 25 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class ResultsGen method readMesh.

private MeshFile readMesh(File f, boolean plot) {
    System.out.println("reading solution " + f.getParentFile().getName());
    try {
        SolverState SS = (SolverState) new XStream().fromXML(f);
        for (HalfFace hf : SS.mesh) plansIn.incrementAndGet();
        SkelFootprint.postProcesss(SS);
        for (HalfFace hf : SS.mesh) {
            plansOut.incrementAndGet();
            for (HalfEdge e : hf) {
                SuperEdge se = (SuperEdge) e;
                if (se.proceduralFacade != null) {
                    meshFacades.getAndIncrement();
                }
            }
        }
        if (plot)
            SS.debugSolverResult();
        return new MeshFile(SS.mesh, f);
    } catch (Throwable t) {
        t.printStackTrace();
        return null;
    }
}
Also used : XStream(com.thoughtworks.xstream.XStream) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace)

Aggregations

HalfEdge (org.twak.utils.geom.HalfMesh2.HalfEdge)31 HalfFace (org.twak.utils.geom.HalfMesh2.HalfFace)25 Point2d (javax.vecmath.Point2d)15 MFPoint (org.twak.tweed.gen.FeatureCache.MFPoint)13 Line (org.twak.utils.Line)13 SuperLine (org.twak.viewTrace.SuperLine)11 ArrayList (java.util.ArrayList)10 HashMap (java.util.HashMap)8 HashSet (java.util.HashSet)8 MegaFeatures (org.twak.tweed.gen.FeatureCache.MegaFeatures)8 HalfMesh2 (org.twak.utils.geom.HalfMesh2)7 Color (java.awt.Color)6 LinkedHashSet (java.util.LinkedHashSet)6 List (java.util.List)6 Map (java.util.Map)6 MultiMap (org.twak.utils.collections.MultiMap)6 File (java.io.File)5 Set (java.util.Set)5 Vector2d (javax.vecmath.Vector2d)5 Cach (org.twak.utils.Cach)5