Search in sources :

Example 1 with DumbCluster1D

use of org.twak.utils.DumbCluster1D in project chordatlas by twak.

the class Regularizer method cluster1.

private void cluster1(List<FRect> rects, double tol, double alpha, Bounds... axis) {
    class Wrapper {

        FRect rect;

        public Wrapper(FRect rect) {
            this.rect = rect;
        }

        public void set(double neu, Bounds b) {
            double old = rect.get(b);
            rect.set(b, neu * alpha + old * (1 - alpha));
        }
    }
    if (rects.isEmpty())
        return;
    for (Bounds b : axis) {
        List<Wrapper> toCluster = new ArrayList<>();
        for (FRect r : rects) toCluster.add(new Wrapper(r));
        DumbCluster1D<Wrapper> clusterer = new DumbCluster1D<Wrapper>(tol, toCluster) {

            @Override
            public double toDouble(Wrapper e) {
                return e.rect.get(b);
            }
        };
        for (DumbCluster1D.Cluster<Wrapper> e : clusterer) for (Wrapper w : e.things) w.set(e.mean, b);
    }
}
Also used : Bounds(org.twak.utils.geom.DRectangle.Bounds) ArrayList(java.util.ArrayList) DumbCluster1D(org.twak.utils.DumbCluster1D)

Example 2 with DumbCluster1D

use of org.twak.utils.DumbCluster1D in project chordatlas by twak.

the class GurobiSkelSolver method buildMini.

private void buildMini() throws GRBException {
    Cache<HalfEdge, GRBLinExpr> isMiniExpr = new Cach<HalfMesh2.HalfEdge, GRBLinExpr>(he -> new GRBLinExpr());
    if (minis == null)
        return;
    for (MegaFeatures mf : minis.keySet()) {
        List<MiniPtCluster> clusterVars = new ArrayList<>();
        mega2clusters.put(mf, clusterVars);
        double mLen = mf.megafacade.length();
        DumbCluster1D<MFPoint> clusters = clusterMinis(mf, minis);
        for (DumbCluster1D.Cluster<MFPoint> d : clusters) {
            // for each cluster, we pick a single MFPoint as the boundary
            MiniPtCluster miniPtVar = new MiniPtCluster();
            Cache<HalfEdge, GRBLinExpr> isEdgeBind = new Cach<HalfMesh2.HalfEdge, GRBLinExpr>(he -> new GRBLinExpr());
            GRBLinExpr selectHE = new GRBLinExpr();
            boolean one = false;
            for (MFPoint pt : d.things) {
                MiniSelectEdge miniSelectEdge = new MiniSelectEdge();
                miniPtVar.put(pt, miniSelectEdge);
                List<HalfEdge> nearCorners = findNear(mf.megafacade, pt, mesh);
                try {
                    for (HalfEdge he : nearCorners) {
                        GRBVar heVar = model.addVar(0.0, 1.0, 0, GRB.BINARY, MINI_TO_EDGE);
                        miniSelectEdge.edge.put(he, heVar);
                        selectHE.addTerm(1, heVar);
                        double cost = he.end.distance(pt);
                        if (he.over != null) {
                            if (pt.right != null)
                                cost += Math.abs(pt.right.height - ((SuperFace) he.face).height);
                            if (pt.left != null)
                                cost += Math.abs(pt.left.height - ((SuperFace) he.over.face).height);
                            isEdgeBind.get(he).addTerm(1, heVar);
                        } else
                            // bonus for being on a corner;
                            cost -= totalEdgeLength * 0.1;
                        target.addTerm(cost, heVar);
                        isMiniExpr.get(he).addTerm(1, heVar);
                        one = true;
                    }
                } catch (Throwable th) {
                    th.printStackTrace();
                }
            }
            if (one) {
                clusterVars.add(miniPtVar);
                model.addConstr(selectHE, GRB.EQUAL, 1, "pick one near " + d.things.iterator().next());
            } else
                print("warning skipping minifacade loction " + d.things.size());
            for (HalfEdge he : isEdgeBind.cache.keySet()) model.addConstr(isEdgeBind.get(he), GRB.EQUAL, edgeInfo.get(he).isEdge, "minifacade boundary must terminate on edge " + he);
            miniPtVar.mean = mf.megafacade.fromPPram(d.mean / mLen);
        }
    }
    double penalty = totalEdgeLength * 0.1;
    for (HalfEdge he : edges) {
        if (he.over != null && he.next.over == null) {
            // edge comes to boundary without minifacade --> penalty
            OptionalDouble miniDist = minis.keySet().stream().map(mf -> mf.megafacade).mapToDouble(line -> line.distance(he.end, true)).min();
            if (!miniDist.isPresent() || miniDist.getAsDouble() > 4)
                continue;
            EdgeVars ei = edgeInfo.get(he);
            ei.edgeNoMini = model.addVar(0.0, 1.0, 0, GRB.BINARY, EDGE_NO_MINI);
            if (isMiniExpr.cache.containsKey(he)) {
                ei.isMini = model.addVar(0.0, 1.0, 0, GRB.BINARY, IS_MINI);
                GRBLinExpr is = isMiniExpr.get(he);
                /* ei.isMini might take 0 or positive integer... assume it's below 10 (0.1 = 1/10) */
                model.addConstr(ei.isMini, GRB.LESS_EQUAL, is, "is minifacade on edge " + he);
                model.addConstr(scale(0.1, is), GRB.LESS_EQUAL, ei.isMini, "is minifacade on edge " + he);
                GRBLinExpr expr = new GRBLinExpr();
                expr.addTerm(1, ei.isEdge);
                expr.addTerm(1, ei.isMini);
                model.addConstr(ei.edgeNoMini, GRB.LESS_EQUAL, expr, null);
                expr = new GRBLinExpr();
                expr.addTerm(1, ei.edgeNoMini);
                expr.addTerm(1, ei.isMini);
                model.addConstr(expr, GRB.LESS_EQUAL, 1, null);
                expr = new GRBLinExpr();
                expr.addTerm(1, ei.isEdge);
                expr.addTerm(-1, ei.isMini);
                model.addConstr(ei.edgeNoMini, GRB.GREATER_EQUAL, expr, null);
            } else {
                // no mini, but easier debug
                model.addConstr(ei.edgeNoMini, GRB.EQUAL, ei.isEdge, null);
            }
            target.addTerm(penalty, ei.edgeNoMini);
        }
    }
}
Also used : Color(java.awt.Color) GRBQuadExpr(gurobi.GRBQuadExpr) DumbCluster1D(org.twak.utils.DumbCluster1D) GRBException(gurobi.GRBException) Cache2(org.twak.utils.Cache2) StringAttr(gurobi.GRB.StringAttr) OptionalDouble(java.util.OptionalDouble) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace) HashMap(java.util.HashMap) Random(java.util.Random) Cach(org.twak.utils.Cach) Tweed(org.twak.tweed.Tweed) ArrayList(java.util.ArrayList) TweedSettings(org.twak.tweed.TweedSettings) HashSet(java.util.HashSet) GRBModel(gurobi.GRBModel) Map(java.util.Map) Cache(org.twak.utils.Cache) Mathz(org.twak.utils.Mathz) PaintThing(org.twak.utils.PaintThing) ProgressMonitor(javax.swing.ProgressMonitor) GRBVar(gurobi.GRBVar) Iterator(java.util.Iterator) ImageFeatures(org.twak.tweed.gen.FeatureCache.ImageFeatures) GRBLinExpr(gurobi.GRBLinExpr) MultiMap(org.twak.utils.collections.MultiMap) Line(org.twak.utils.Line) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) Set(java.util.Set) HalfMesh2(org.twak.utils.geom.HalfMesh2) DoubleAttr(gurobi.GRB.DoubleAttr) MegaFeatures(org.twak.tweed.gen.FeatureCache.MegaFeatures) LinearForm(org.twak.utils.geom.LinearForm) Collectors(java.util.stream.Collectors) File(java.io.File) MFPoint(org.twak.tweed.gen.FeatureCache.MFPoint) Point2d(javax.vecmath.Point2d) List(java.util.List) Collections(java.util.Collections) GRBEnv(gurobi.GRBEnv) GRB(gurobi.GRB) GRBLinExpr(gurobi.GRBLinExpr) MegaFeatures(org.twak.tweed.gen.FeatureCache.MegaFeatures) ArrayList(java.util.ArrayList) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) DumbCluster1D(org.twak.utils.DumbCluster1D) OptionalDouble(java.util.OptionalDouble) MFPoint(org.twak.tweed.gen.FeatureCache.MFPoint) GRBVar(gurobi.GRBVar) Cach(org.twak.utils.Cach) HalfMesh2(org.twak.utils.geom.HalfMesh2)

Example 3 with DumbCluster1D

use of org.twak.utils.DumbCluster1D in project chordatlas by twak.

the class SolverState method miniPainter.

public ICanPaint miniPainter() {
    return new ICanPaint() {

        @Override
        public void paint(Graphics2D g, PanMouseAdaptor ma) {
            // for ( MegaFeatures f : SS.minis.keySet() ) {
            // 
            // for ( MFPoint mfp : SS.minis.get( f ) ) {
            // Line l = mfp.image.mega.megafacade;
            // 
            // spreadImages( g, ma, l, mfp,  Listz.from( mfp.left, mfp.right ) );
            // 
            // }
            // }
            // if (SS.minis == null)
            int brake = 100;
            for (HalfFace f : mesh) {
                for (HalfEdge e : f) {
                    if (e.over != null)
                        continue;
                    if (brake-- < 0)
                        break;
                    SuperEdge se = (SuperEdge) e;
                    if (se.mini == null)
                        continue;
                    List<MiniFacade> mfs = new ArrayList(se.mini);
                    // while (mfs .size() < 2)
                    // mfs.add(null);
                    spreadImages(g, ma, se.line(), se.line().fromPPram(0.5), mfs);
                }
            }
            int i = 0;
            if (minis != null)
                for (MegaFeatures f : minis.keySet()) {
                    // PaintThing.paint (f.megafacade, g, ma);
                    DumbCluster1D<MFPoint> res = GurobiSkelSolver.clusterMinis(f, minis);
                    Vector2d dir = f.megafacade.dir();
                    Vector2d out = new Vector2d(dir);
                    out.set(-out.y, out.x);
                    out.scale(ma.toZoom(2) / out.length());
                    for (Cluster<MFPoint> c : res) {
                        g.setColor(Rainbow.getColour(i++));
                        for (MFPoint mfp : c.things) {
                            Point2d pt = new Point2d(mfp);
                            pt.add(out);
                            g.setStroke(new BasicStroke(0.2f));
                            PaintThing.paint(pt, g, ma);
                            g.setStroke(new BasicStroke(0.2f));
                            for (HalfEdge e : GurobiSkelSolver.findNear(f.megafacade, mfp, mesh)) g.drawLine(ma.toX(pt.x), ma.toY(pt.y), ma.toX(e.end.x), ma.toY(e.end.y));
                            if (mfp.selectedEdge != null) {
                                g.setStroke(new BasicStroke(2f));
                                g.drawLine(ma.toX(pt.x), ma.toY(pt.y), ma.toX(mfp.selectedEdge.end.x), ma.toY(mfp.selectedEdge.end.y));
                            }
                        }
                    }
                }
            g.setStroke(new BasicStroke(1));
        }

        private void spreadImages(Graphics2D g, PanMouseAdaptor ma, Line sel, Point2d cen, List<MiniFacade> mfs) {
            Vector2d perp = sel.dir();
            perp.set(-perp.y, perp.x);
            perp.normalize();
            for (int i = 0; i < mfs.size(); i++) {
                MiniFacade mf = mfs.get(i);
                Vector2d p2 = new Vector2d(perp);
                p2.scale((i + 1) * 10);
                p2.add(cen);
                if (mf == null) {
                    g.setColor(Color.black);
                    g.fillRect(ma.toX(p2.x - 1), ma.toY(p2.y - 3), ma.toZoom(2), ma.toZoom(6));
                    continue;
                }
                double w = mf.width * 0.1;
                double h = mf.height * 0.1;
                mf.paintImage(g, ma, p2.x - w, p2.y - h, p2.x + w, p2.y + h);
            }
        }
    };
}
Also used : BasicStroke(java.awt.BasicStroke) MiniFacade(org.twak.viewTrace.facades.MiniFacade) MegaFeatures(org.twak.tweed.gen.FeatureCache.MegaFeatures) ArrayList(java.util.ArrayList) Cluster(org.twak.utils.DumbCluster1D.Cluster) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace) DumbCluster1D(org.twak.utils.DumbCluster1D) ICanPaint(org.twak.utils.PaintThing.ICanPaint) MFPoint(org.twak.tweed.gen.FeatureCache.MFPoint) ICanPaint(org.twak.utils.PaintThing.ICanPaint) Graphics2D(java.awt.Graphics2D) Line(org.twak.utils.Line) SuperLine(org.twak.viewTrace.SuperLine) Vector2d(javax.vecmath.Vector2d) Point2d(javax.vecmath.Point2d) PanMouseAdaptor(org.twak.utils.PanMouseAdaptor) MFPoint(org.twak.tweed.gen.FeatureCache.MFPoint) ArrayList(java.util.ArrayList) List(java.util.List)

Example 4 with DumbCluster1D

use of org.twak.utils.DumbCluster1D in project chordatlas by twak.

the class Regularizer method clusterDeltas.

private void clusterDeltas(List<FRect> rects, double tol, double alpha, Dir dir) {
    if (rects.isEmpty())
        return;
    List<FRect> toCluster = new ArrayList<>();
    for (FRect r : rects) {
        FRect da = r.getAdj(dir);
        if (// only strong adjacencies
        da != null && da.getAdj(dir.opposite) == r)
            toCluster.add(r);
    }
    DumbCluster1D<FRect> clusterer = new DumbCluster1D<FRect>(tol, toCluster) {

        @Override
        public double toDouble(FRect rect) {
            return rect.distanceToAdjacent(dir);
        }
    };
    Bounds b = (dir == Dir.L || dir == Dir.R) ? Bounds.XCEN : Bounds.YCEN;
    int moveDirection = dir == Dir.L || dir == Dir.D ? 1 : -1;
    Map<FRect, Double> desiredSpacings = new HashMap<>();
    for (DumbCluster1D.Cluster<FRect> e : clusterer) {
        for (FRect rect : e.things) desiredSpacings.put(rect, e.mean);
    }
    Collections.sort(rects, DRectangle.comparator(b, dir == Dir.L || dir == Dir.D ? false : true));
    for (FRect r : rects) {
        Double spacing = desiredSpacings.get(r);
        if (spacing == null)
            continue;
        DRectangle adj = r.getAdj(dir);
        adj.set(b, adj.get(b) - (spacing - r.distanceToAdjacent(dir)) * alpha * moveDirection);
    }
}
Also used : DRectangle(org.twak.utils.geom.DRectangle) HashMap(java.util.HashMap) Bounds(org.twak.utils.geom.DRectangle.Bounds) ArrayList(java.util.ArrayList) DumbCluster1D(org.twak.utils.DumbCluster1D) OptionalDouble(java.util.OptionalDouble) InAxDouble(org.twak.utils.streams.InAxDouble)

Aggregations

ArrayList (java.util.ArrayList)4 DumbCluster1D (org.twak.utils.DumbCluster1D)4 HashMap (java.util.HashMap)2 List (java.util.List)2 OptionalDouble (java.util.OptionalDouble)2 Point2d (javax.vecmath.Point2d)2 MFPoint (org.twak.tweed.gen.FeatureCache.MFPoint)2 MegaFeatures (org.twak.tweed.gen.FeatureCache.MegaFeatures)2 Line (org.twak.utils.Line)2 HalfEdge (org.twak.utils.geom.HalfMesh2.HalfEdge)2 HalfFace (org.twak.utils.geom.HalfMesh2.HalfFace)2 GRB (gurobi.GRB)1 DoubleAttr (gurobi.GRB.DoubleAttr)1 StringAttr (gurobi.GRB.StringAttr)1 GRBEnv (gurobi.GRBEnv)1 GRBException (gurobi.GRBException)1 GRBLinExpr (gurobi.GRBLinExpr)1 GRBModel (gurobi.GRBModel)1 GRBQuadExpr (gurobi.GRBQuadExpr)1 GRBVar (gurobi.GRBVar)1