Search in sources :

Example 6 with LinearForm

use of org.twak.utils.geom.LinearForm in project chordatlas by twak.

the class FindLines method forClique.

private void forClique(Set<Line> remaining, List<Line> out, int debugLine, int clique) {
    Iterator<Line> filter = remaining.iterator();
    while (filter.hasNext()) {
        Line l = filter.next();
        // double l = filter.next().length();
        if (l.lengthSquared() == 0 || l.hasNaN())
            filter.remove();
    }
    if (remaining.isEmpty())
        return;
    int count = 0;
    while (!remaining.isEmpty()) {
        double angle = nextAngle(remaining, count);
        // offset bin
        Bin.Builder<Line> oBBin = new Bin.Builder<>();
        LinearForm lfPerp = new LinearForm(Math.cos(angle), Math.sin(angle));
        for (Line l : remaining) {
            if (Anglez.dist(l.aTan2(), angle) < Math.PI / 2) {
                // and line angle near angle+-180
                oBBin.add(lfPerp.findPParam(l.start), l.length(), l);
                oBBin.add(lfPerp.findPParam(l.end), l.length(), l);
            }
        }
        // we're super sensitive to the number of orientation bins :(
        Bin<Line> oBin = oBBin.done(P.FL_BINS * 2, false);
        int oBinI = oBin.maxI();
        int[] oBinM = oBin.maxMode(1, 10);
        LinearForm lfDir = new LinearForm(lfPerp.y, -lfPerp.x);
        lfDir.findC(lfPerp.fromPParam(oBin.val(oBinI)));
        RangeMerge<Line> rm = new RangeMerge(P.FL_GAP_TOL, P.FL_GAP_TOL / 2);
        for (Line w : oBin.getThings(oBinI, oBinM)) {
            if (lfDir.distance(w.start) < getTolNearLine(w.start) && lfDir.distance(w.end) < getTolNearLine(w.end) && // and line angle near angle+-180
            Anglez.dist(w.aTan2(), angle) < Math.PI / 2.5) {
                rm.add(lfDir.findPParam(w.start), lfDir.findPParam(w.end), w);
            }
        }
        List<Result<Line>> merged = rm.getResults();
        if (merged.isEmpty()) {
            for (Line w : oBin.getThings(oBinI, oBinM)) remaining.remove(w);
        } else {
            double maxP = merged.stream().map(x -> x.max - x.min).max(Double::compare).get();
            for (Result<Line> r : merged) {
                if (r.max - r.min < 0.2 * maxP)
                    continue;
                Line line = null;
                if (P.FL_REGRESS)
                    line = regress(r.things, lfDir);
                if (line == null)
                    line = new Line(lfDir, r.min, r.max);
                Iterator<Line> rit = remaining.iterator();
                boolean removed = false;
                Bin<Line> counts = null;
                if (P.MIN_LINES > 1)
                    counts = new Bin<>(0, 1, 50, false);
                while (rit.hasNext()) {
                    Line rine = rit.next();
                    if (line.distance(rine.start, true) < getTolNearLine2(rine.start) && line.distance(rine.end, true) < getTolNearLine2(rine.end) && Anglez.dist(line.aTan2(), rine.aTan2()) < getTolRemoveAngle(rine)) {
                        if (counts != null)
                            counts.addRange(line.findPPram(rine.start), line.findPPram(rine.end), 1, rine);
                        removed = true;
                        rit.remove();
                    }
                }
                if (counts != null) {
                    // for (Pair<Double, Double > d : new ConsecutiveItPairs<>( counts.getRegionAbove( P.MIN_LINES ) )) {
                    // 
                    // Point2d start = line.fromPPram( counts.getFirst( P.MIN_LINES ) ),
                    // end   = line.fromPPram( counts.getLast( P.MIN_LINES ) );
                    // 
                    // if ( start != null && end != null ) {
                    // out.add( new Line(start, end) );
                    // }
                    // }
                    Point2d start = line.fromPPram(counts.getFirst(P.MIN_LINES)), end = line.fromPPram(counts.getLast(P.MIN_LINES));
                    if (start != null && end != null) {
                        line.start = start;
                        line.end = end;
                    } else
                        line = null;
                }
                if (!removed)
                    for (Line l : r.things) {
                        if (remaining.contains(l)) {
                            remaining.remove(l);
                        }
                    }
                if (line != null) {
                    if (bias != null) {
                        Point2d cen = line.fromPPram(0.5);
                        Double toGIS = bias.getAngle(line, cen);
                        if (toGIS != null)
                            line = rotateToAngle(line, cen, toGIS);
                    }
                    if (debugFilter(count, debugLine) && line.start.distanceSquared(line.end) > 0.001) {
                        out.add(line);
                        cliques.put(line, clique);
                    }
                }
            }
        }
        count++;
    }
}
Also used : LinearForm(org.twak.utils.geom.LinearForm) Result(org.twak.viewTrace.RangeMerge.Result) Line(org.twak.utils.Line) Point2d(javax.vecmath.Point2d)

Example 7 with LinearForm

use of org.twak.utils.geom.LinearForm in project chordatlas by twak.

the class GreebleSkel method mapTo2d.

protected void mapTo2d(Face f, Loop<LPoint3d> ll, MiniFacade mf, WallTag wallTag, Set<QuadF> features, MatMeshBuilder faceMaterial) {
    Matrix4d to2dXY = new Matrix4d();
    Vector3d up = f.edge.uphill, along = f.edge.direction(), out = f.edge.getPlaneNormal();
    along.normalize();
    to2dXY.setRow(2, up.x, up.y, up.z, 0);
    to2dXY.setRow(1, out.x, out.y, out.z, 0);
    to2dXY.setRow(0, -along.x, -along.y, -along.z, 0);
    Point3d bottomS = f.definingSE.iterator().next().getStart(f), bottomE = f.definingSE.iterator().next().getEnd(f);
    Point3d start = new Point3d(bottomS);
    Point3d end = new Point3d(bottomE);
    to2dXY.m33 = 1;
    to2dXY.transform(start);
    to2dXY.m03 = -start.x;
    to2dXY.m13 = -start.y;
    to2dXY.m23 = -start.z;
    start = new Point3d(bottomS);
    to2dXY.transform(start);
    to2dXY.transform(end);
    Loop<LPoint2d> flat = GreebleHelper.to2dLoop(GreebleHelper.transform(ll, to2dXY), 1);
    Matrix4d to3d = new Matrix4d(to2dXY);
    to3d.invert();
    {
        // face in z-up, we're in y-up
        double[] one = new double[4], two = new double[4];
        to3d.getRow(1, one);
        to3d.getRow(2, two);
        to3d.setRow(1, two);
        to3d.setRow(2, one);
    }
    // now in jme space
    Matrix4d to2d = new Matrix4d(to3d);
    to2d.invert();
    MiniFacade forFace = null;
    if (mf != null) {
        forFace = new MiniFacade(mf);
        forFace.rects.clear();
    }
    LinearForm3D facePlane = new LinearForm3D(new Vector3d(out.x, out.z, out.y), new Point3d(bottomS.x, bottomS.z, bottomS.y));
    LoopL<Point2d> sides = null;
    DRectangle facadeRect = null;
    if (wallTag != null) {
        sides = findRectagle(flat, Pointz.to2(start), Pointz.to2(end));
        if (sides != null)
            facadeRect = findRect(sides.remove(0));
    }
    List<DRectangle> floors = new ArrayList();
    List<MeshBuilder> materials = new ArrayList();
    if (wallTag != null && facadeRect != null && mf != null && wallTag.isGroundFloor && mf.groundFloorHeight > 0 && wallTag.groundFloorColor != null && facadeRect.x < mf.groundFloorHeight && facadeRect.getMaxX() > mf.groundFloorHeight) {
        floors.addAll(facadeRect.splitY(mf.groundFloorHeight));
        MatMeshBuilder gfm = greebleGrid.mbs.get("brick", wallTag.groundFloorColor);
        for (Loop<Point2d> loop : sides) {
            Loop<Point2d>[] cut = Loopz.cutConvex(loop, new LinearForm(0, 1, mf.groundFloorHeight));
            faceMaterial.add(cut[1].singleton(), to3d);
            gfm.add(cut[0].singleton(), to3d);
        }
        materials.add(gfm);
        materials.add(faceMaterial);
    } else {
        floors.add(facadeRect);
        materials.add(faceMaterial);
        if (sides != null)
            faceMaterial.add(sides, to3d);
    }
    for (int j = 0; j < floors.size(); j++) {
        DRectangle floorRect = floors.get(j);
        MeshBuilder m = materials.get(j);
        Iterator<QuadF> quit = features.iterator();
        while (quit.hasNext()) {
            QuadF n = quit.next();
            if (n.project(to2d, to3d, flat, facePlane, new Vector3d(along.y, 0, -along.x)) && wallTag != null && floorRect != null && forFace != null) {
                // set the vertical bounds, so we can just render in 2d
                FRect bounds = new FRect(n.original);
                n.setBounds(to2d, bounds);
                if (floorRect.contains(bounds)) {
                    forFace.rects.put(n.original.f, bounds);
                    quit.remove();
                }
            }
        }
        if (wallTag == null || forFace == null || floorRect == null) {
            m.add(flat.singleton(), to3d);
            return;
        }
        List<DRectangle> occlusions = new ArrayList<>();
        for (LineHeight lh : wallTag.occlusions) {
            Point3d s = new Point3d(lh.start.x, lh.start.y, lh.min), e = new Point3d(lh.end.x, lh.end.y, lh.max);
            to2dXY.transform(s);
            to2dXY.transform(e);
            occlusions.add(new DRectangle(Math.min(s.x, e.x), s.z, Math.abs(e.x - s.x), Math.abs(e.z - s.z)));
        }
        if (mf.texture == null)
            greebleGrid.buildGrid(floorRect, to3d, forFace, m, wallTag);
        else
            greebleGrid.textureGrid(floorRect, to3d, mf);
    }
}
Also used : Loop(org.twak.utils.collections.Loop) DRectangle(org.twak.utils.geom.DRectangle) LPoint2d(org.twak.viewTrace.facades.GreebleHelper.LPoint2d) ArrayList(java.util.ArrayList) LinearForm(org.twak.utils.geom.LinearForm) LinearForm3D(org.twak.utils.geom.LinearForm3D) Matrix4d(javax.vecmath.Matrix4d) Vector3d(javax.vecmath.Vector3d) LPoint2d(org.twak.viewTrace.facades.GreebleHelper.LPoint2d) Point2d(javax.vecmath.Point2d) Point3d(javax.vecmath.Point3d) LPoint3d(org.twak.viewTrace.facades.GreebleHelper.LPoint3d) MeshBuilder(org.twak.siteplan.jme.MeshBuilder)

Example 8 with LinearForm

use of org.twak.utils.geom.LinearForm in project chordatlas by twak.

the class GreebleSkel method setToHeight.

private static PtInChain setToHeight(List<Point2d> chain, boolean left, double x2, double y2) {
    double bestX = chain.get(0).x;
    for (int i = 1; i < chain.size(); i++) {
        Point2d p = chain.get(i - 1), n = chain.get(i);
        bestX = left ? Math.max(p.x, bestX) : Math.min(p.x, bestX);
        PtInChain first = new PtInChain(new Point2d(n), i, 0);
        first.x = bestX;
        if (Math.abs(n.y - y2) < 0.001) {
            first.x = left ? Math.max(n.x, first.x) : Math.min(n.x, first.x);
            return first;
        }
        Line pn = new Line(p, n);
        if (n.y > y2) {
            Point2d sec = new LinearForm(pn).intersect(new LinearForm(0, 1, y2));
            if (sec == null)
                return first;
            sec.x = left ? Math.max(bestX, sec.x) : Math.min(bestX, sec.x);
            return new PtInChain(sec, i - 1, pn.findPPram(sec));
        }
    }
    return null;
}
Also used : Line(org.twak.utils.Line) LPoint2d(org.twak.viewTrace.facades.GreebleHelper.LPoint2d) Point2d(javax.vecmath.Point2d) LinearForm(org.twak.utils.geom.LinearForm)

Example 9 with LinearForm

use of org.twak.utils.geom.LinearForm 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 10 with LinearForm

use of org.twak.utils.geom.LinearForm in project chordatlas by twak.

the class Prof method parameterize.

public Prof parameterize() {
    // find and subtract vertical lines
    Set<Line> lines = new HashSet<>();
    for (int i = 1; i < size(); i++) lines.add(new Line(get(i - 1), get(i)));
    double avgMinY = get(0).y;
    SliceParameters P = new SliceParameters(5);
    P.FL_REGRESS = false;
    P.FL_BINS = 20;
    // simple = 0.4
    double A = 0.4;
    // simple = 1;
    double B = 1;
    lines = new FindLines(lines, P) {

        protected double nextAngle(Set<Line> remaining, int iteration) {
            double delta = Math.PI / P.FL_BINS;
            // angle bin
            Bin<Line> aBin = new Bin(-Math.PI - delta, Math.PI + delta, P.FL_BINS * 2, true);
            for (Line l : remaining) {
                double len = l.length();
                double angle = l.aTan2();
                aBin.add(angle, len, l);
            }
            // return MUtils.PI2;
            if (iteration < 1 && aBin.getWeight(Mathz.PI2) >= 5)
                return Mathz.PI2;
            int aBinI = aBin.maxI();
            return aBin.val(aBinI);
        }

        protected double getTolNearLine(Point2d p) {
            return P.FL_NEAR_LINE * (p.y < avgMinY + 5 ? 5 : B);
        }

        protected double getTolNearLine2(Point2d p) {
            return P.FL_NEAR_LINE_2 * (p.y < avgMinY + 5 ? 10 : B);
        }
    }.result.all;
    clean = new Prof(this);
    clean.clear();
    if (lines.isEmpty()) {
        clean.add(new Point2d(0, 0));
        clean.add(new Point2d(0, 1));
        return clean;
    }
    List<Line> llines = new ArrayList(lines);
    llines.stream().filter(l -> l.start.y > l.end.y).forEach(l -> l.reverseLocal());
    Collections.sort(llines, new Comparator<Line>() {

        public int compare(Line o1, Line o2) {
            return Double.compare(o1.start.y + o1.end.y, o2.start.y + o2.end.y);
        }
    });
    for (int i = 0; i < llines.size(); i++) {
        Line l = llines.get(i);
        double angle = l.aTan2();
        if (angle < Mathz.PI2 + 0.1 && angle > Mathz.PI2 - 0.4)
            llines.set(i, FindLines.rotateToAngle(l, l.fromPPram(0.5), Mathz.PI2));
    }
    Line bottomLine = llines.get(0);
    llines.add(0, new Line(new Point2d(bottomLine.start.x, get(0).y), new Point2d(bottomLine.start.x, get(0).y)));
    double lastY = -Double.MAX_VALUE, lastX = Double.MAX_VALUE;
    for (Line l : llines) {
        boolean startAbove = l.start.y >= lastY && l.start.x <= lastX, endAbove = l.end.y >= lastY && l.end.x <= lastX;
        if (startAbove && endAbove) {
            clean.add(l.start);
            clean.add(l.end);
        } else if (!startAbove && endAbove) {
            if (l.start.y < lastY) {
                Point2d sec = new LinearForm(new Vector2d(1, 0)).findC(new Point2d(0, lastY)).intersect(new LinearForm(l));
                if (sec != null)
                    l.start = sec;
            }
            if (l.start.x > lastX) {
                Point2d sec = new LinearForm(new Vector2d(0, 1)).findC(new Point2d(lastX, 0)).intersect(new LinearForm(l));
                if (sec != null)
                    l.start = sec;
            }
            if (l.end.distanceSquared(l.start) < 100)
                clean.add(l.start);
            clean.add(l.end);
        } else {
            Vector2d dir = l.dir();
            if (Math.abs(dir.x) > Math.abs(dir.y)) {
                LinearForm x = new LinearForm(new Vector2d(1, 0)).findC(new Point2d(0, lastY));
                l.start = x.project(l.start);
                l.end = x.project(l.end);
                l.start.x = Math.min(l.start.x, lastX);
                l.end.x = Math.min(l.end.x, lastX);
            } else {
                LinearForm y = new LinearForm(new Vector2d(0, 1)).findC(new Point2d(lastX, 0));
                l.start = y.project(l.start);
                l.end = y.project(l.end);
                l.start.y = Math.max(l.start.y, lastY);
                l.end.y = Math.max(l.end.y, lastY);
            }
            clean.add(l.start);
            clean.add(l.end);
        }
        lastY = l.end.y;
        lastX = l.end.x;
    }
    clean.clean(0.2);
    return clean;
}
Also used : ConsecutivePairs(org.twak.utils.collections.ConsecutivePairs) Matrix4d(javax.vecmath.Matrix4d) ConsecutiveItPairs(org.twak.utils.collections.ConsecutiveItPairs) SliceParameters(org.twak.viewTrace.SliceParameters) Arrayz(org.twak.utils.collections.Arrayz) Node(com.jme3.scene.Node) ObjRead(org.twak.utils.geom.ObjRead) Map(java.util.Map) Cache(org.twak.utils.Cache) Material(com.jme3.material.Material) Point3d(javax.vecmath.Point3d) VertexBuffer(com.jme3.scene.VertexBuffer) IdentityHashMap(java.util.IdentityHashMap) Collection(java.util.Collection) Line(org.twak.utils.Line) FindLines(org.twak.viewTrace.FindLines) Set(java.util.Set) Vector2d(javax.vecmath.Vector2d) LinearForm(org.twak.utils.geom.LinearForm) Collectors(java.util.stream.Collectors) List(java.util.List) Rainbow(org.twak.utils.ui.Rainbow) Line3d(org.twak.utils.geom.Line3d) Mesh(com.jme3.scene.Mesh) Geometry(com.jme3.scene.Geometry) DBSCANClusterer(org.apache.commons.math3.ml.clustering.DBSCANClusterer) LinearForm3D(org.twak.utils.geom.LinearForm3D) Bin(org.twak.viewTrace.Bin) Pair(org.twak.utils.Pair) Vector3d(javax.vecmath.Vector3d) Clusterable(org.apache.commons.math3.ml.clustering.Clusterable) Tweed(org.twak.tweed.Tweed) ArrayList(java.util.ArrayList) TweedSettings(org.twak.tweed.TweedSettings) HashSet(java.util.HashSet) PanMouseAdaptor(org.twak.utils.PanMouseAdaptor) Graphics2D(java.awt.Graphics2D) ICanPaintU(org.twak.utils.PaintThing.ICanPaintU) Mathz(org.twak.utils.Mathz) PaintThing(org.twak.utils.PaintThing) Iterator(java.util.Iterator) Point2d(javax.vecmath.Point2d) SuperLine(org.twak.viewTrace.SuperLine) Cluster(org.apache.commons.math3.ml.clustering.Cluster) ColorRGBA(com.jme3.math.ColorRGBA) Comparator(java.util.Comparator) InAxDoubleArray(org.twak.utils.streams.InAxDoubleArray) Collections(java.util.Collections) ObjSlice(org.twak.viewTrace.ObjSlice) FindLines(org.twak.viewTrace.FindLines) Bin(org.twak.viewTrace.Bin) ArrayList(java.util.ArrayList) LinearForm(org.twak.utils.geom.LinearForm) Line(org.twak.utils.Line) SuperLine(org.twak.viewTrace.SuperLine) Vector2d(javax.vecmath.Vector2d) SliceParameters(org.twak.viewTrace.SliceParameters) Point2d(javax.vecmath.Point2d) HashSet(java.util.HashSet)

Aggregations

LinearForm (org.twak.utils.geom.LinearForm)10 Point2d (javax.vecmath.Point2d)9 Line (org.twak.utils.Line)9 ArrayList (java.util.ArrayList)5 HashSet (java.util.HashSet)4 Iterator (java.util.Iterator)4 List (java.util.List)4 Map (java.util.Map)4 Set (java.util.Set)4 Vector2d (javax.vecmath.Vector2d)4 Vector3d (javax.vecmath.Vector3d)4 Pair (org.twak.utils.Pair)4 LinearForm3D (org.twak.utils.geom.LinearForm3D)4 Collection (java.util.Collection)3 Collections (java.util.Collections)3 HashMap (java.util.HashMap)3 Collectors (java.util.stream.Collectors)3 Matrix4d (javax.vecmath.Matrix4d)3 Point3d (javax.vecmath.Point3d)3 Mathz (org.twak.utils.Mathz)3