Search in sources :

Example 1 with SliceParameters

use of org.twak.viewTrace.SliceParameters in project chordatlas by twak.

the class Prof method parameterize.

public static // all profs from a single profile-edge are in the same 2D space, with strange x-origin
Prof parameterize(// all profs from a single profile-edge are in the same 2D space, with strange x-origin
List<Prof> in) {
    // double toProfileEdge;
    // {
    // Prof eg = in.iterator().next();
    // Point3d p = Pointz.to3( profileEdge.start );
    // toProfileEdge = eg.to2d( p ).x;
    // }
    double avgMinY = in.stream().filter(p -> p != null).mapToDouble(p -> p.get(0).y).average().getAsDouble();
    Set<Line> lines = new HashSet<>();
    for (Prof p : in) for (int i = 1; i < p.size(); i++) lines.add(new Line(p.get(i - 1), p.get(i)));
    SliceParameters P = new SliceParameters(5);
    P.FL_REGRESS = true;
    P.FL_BINS = 20;
    // double A = 0.4; // simple = 0.4
    // double B = 0.1; // simple = 1;
    // simple = 0.4
    double A = 0.2;
    // simple = 0.1;
    double B = 0.3;
    // simple = 0.1; rotate threshold, radians
    double C = 0.1;
    double firstFloorHeight = 2;
    P.MIN_LINES = Math.max(1, in.size() * A);
    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) >= 10)
                return Mathz.PI2;
            int aBinI = aBin.maxI();
            return aBin.val(aBinI);
        }

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

        protected double getTolNearLine2(Point2d p) {
            return P.FL_NEAR_LINE_2 * (p.y < avgMinY + firstFloorHeight ? 10 : B);
        }

        protected double getTolRemoveAngle(Line l) {
            return l.start.y < avgMinY + firstFloorHeight ? Math.PI * 0.5 : Math.PI * 0.2;
        }
    }.result.all;
    List<Line> llines = // is rubbish
    lines.stream().filter(l -> l.lengthSquared() > 0.001).filter(// is floor polygon
    l -> l.end.y > avgMinY + 1 || Math.abs(l.start.y - l.end.y) > 0.1).collect(Collectors.toList());
    Prof clean = new Prof(in.get(in.size() / 2));
    clean.clear();
    if (llines.isEmpty()) {
        clean.add(new Point2d(0, 0));
        clean.add(new Point2d(0, 1));
        return clean;
    }
    for (int i = 0; i < llines.size(); i++) {
        Line l = llines.get(i);
        double angle = l.aTan2();
        if (angle < Mathz.PI2 + C && angle > Mathz.PI2 - C)
            llines.set(i, FindLines.rotateToAngle(l, l.fromPPram(0.5), Mathz.PI2));
    }
    // 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.fromPPram(0.2).y, o2.fromPPram(0.2).y);
        }
    });
    // for (Line l : llines)
    // PaintThing.debug( new Color(170,0,255), 2f, new Line( l.start.x+5, -l.start.y, l.end.x+5, -l.end.y ) );
    Line lastL = null;
    Point2d lastP = new Point2d(0, -Double.MAX_VALUE);
    for (Line l : llines) {
        // if (c >= 6)
        // continue;
        // if ( c== 5)
        // System.out.println("here");
        // c++;
        Point2d mid = l.fromPPram(0.5);
        if (!(lastL != null && !lastL.isOnLeft(mid) || (lastP.y == -Double.MAX_VALUE || (mid.y >= lastP.y - 0.5 && mid.x <= lastP.x + 0.5))))
            continue;
        boolean startAbove = l.start.y >= lastP.y && l.start.x <= lastP.x, endAbove = l.end.y >= lastP.y && l.end.x <= lastP.x;
        if (l.end.y < l.start.y)
            l.end.y = l.start.y;
        if (startAbove && endAbove) {
        // okay
        } else {
            if (lastL != null && l.start.distanceSquared(lastP) < 9) {
                Point2d sec = lastL.intersects(l, false);
                if (sec != null && sec.distanceSquared(lastP) < 9 && sec.x <= lastL.start.x && sec.y >= lastL.start.y) {
                    clean.remove(clean.size() - 1);
                    clean.add(sec);
                    lastP = sec;
                    l.start = sec;
                } else if (l.start.x < lastP.x) {
                    sec = new LinearForm(new Vector2d(1, 0)).findC(l.start).intersect(new LinearForm(lastL));
                    if (sec != null && sec.distanceSquared(lastP) < 9) {
                        clean.remove(clean.size() - 1);
                        clean.add(sec);
                        lastP = sec;
                    }
                }
            }
            if (l.start.x > lastP.x + 0.01 || l.end.x > lastP.x + 0.01) {
                Point2d sec = new LinearForm(new Vector2d(0, 1)).findC(new Point2d(lastP.x, 0)).intersect(new LinearForm(l));
                if (sec != null && sec.distanceSquared(lastP) < 9 && sec.distanceSquared(l.start) < 9) {
                    if (l.start.x > lastP.x)
                        l.start = sec;
                    else
                        l.end = sec;
                }
            }
        }
        if (lastL != null && l.start.distanceSquared(lastP) < 4) {
            Point2d sec = lastL.intersects(l, false);
            if (sec != null && (sec.distanceSquared(lastP) < 4 || Math.abs(sec.y - lastP.y) < 1) && sec.x <= lastL.start.x && sec.y >= lastL.start.y) {
                clean.remove(clean.size() - 1);
                clean.add(sec);
                lastP = sec;
                l.start = sec;
            } else if (l.start.x < lastP.x) {
                sec = new LinearForm(new Vector2d(1, 0)).findC(l.start).intersect(new LinearForm(lastL));
                if (sec != null && (sec.distanceSquared(lastP) < 4 || Math.abs(sec.y - lastP.y) < 1)) {
                    clean.remove(clean.size() - 1);
                    clean.add(sec);
                    lastP = sec;
                // l.start = sec;
                }
            }
        }
        if (lastP.y - l.end.y < 3 && l.end.x - lastP.x < 3) {
            for (Point2d pt : l.points()) {
                pt.x = Math.min(pt.x, lastP.x);
                pt.y = Math.max(pt.y, lastP.y);
            }
            if (!l.start.equals(l.end))
                for (Point2d pt : l.points()) {
                    // if (c == 2)
                    // PaintThing.debug.put(1, new Point2d ( pt.x, -pt.y ) );
                    pt = new Point2d(pt);
                    pt.x = Math.min(pt.x, lastP.x);
                    pt.y = Mathz.max(0, pt.y, lastP.y);
                    if (clean.isEmpty() && pt.y > 0.2) {
                        clean.add(new Point2d(pt.x, 0));
                    }
                    if (lastP != null && pt.distanceSquared(lastP) > 0.02) {
                        clean.add(pt);
                    }
                    lastP = clean.get(clean.size() - 1);
                    if (clean.size() >= 3) {
                        Point2d a = clean.get(clean.size() - 1), b = clean.get(clean.size() - 2), c = clean.get(clean.size() - 3);
                        if (Math.abs(Mathz.area(c, b, a)) < 0.1 || Mathz.absAngleBetween(a, b, c) < 0.1)
                            clean.remove(clean.size() - 2);
                    }
                }
        }
        if (clean.size() >= 2)
            lastL = new Line(clean.get(clean.size() - 2), clean.get(clean.size() - 1));
    }
    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) 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)

Example 2 with SliceParameters

use of org.twak.viewTrace.SliceParameters 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)

Example 3 with SliceParameters

use of org.twak.viewTrace.SliceParameters in project chordatlas by twak.

the class ProfileGen method findMegaFaces.

private List<MegaFacade> findMegaFaces(double delta) {
    SliceParameters P = new SliceParameters(SLICE_SCALE);
    List<LineAtHeight> lines = new ArrayList();
    Map<Integer, LineSoup> slices = new HashMap<>();
    for (int hi = 0; getHeight(hi) < extent[3]; hi++) {
        int _i = hi;
        boolean error;
        int count = 0;
        do {
            error = false;
            try {
                LineSoup soup = new LineSoup(ObjSlice.sliceTri(blockGen.getCroppedMesh(), getHeight(hi), majorAxis));
                FindLines foundLines = new FindLines(soup, TweedSettings.settings.useGis ? gisBias : null, -1, null, P);
                foundLines.result.all.stream().forEach(x -> lines.add(new LineAtHeight(_i, delta, x, foundLines.result.all)));
                slices.put(hi, foundLines.result);
            } catch (Throwable th) {
                th.printStackTrace();
                error = true;
            }
        } while (error && count++ < 10);
    }
    Collections.sort(lines, new LAHComparator());
    // new Plot(lines.stream().map (lah -> lah.line).collect(Collectors.toList() ), gis);
    faces = new ArrayList<>();
    while (!lines.isEmpty()) {
        System.out.println("clustering megafacdes " + lines.size());
        // longest line
        LineAtHeight start = lines.get(0);
        lines.remove(start);
        MegaFacade face = new MegaFacade(start);
        Set<LineAtHeight> toProcess = new HashSet<>();
        toProcess.add(start);
        while (!toProcess.isEmpty()) {
            LineAtHeight lah = toProcess.iterator().next();
            toProcess.remove(lah);
            for (int _pmDelta : new int[] { -2, -1, 1, 2 }) {
                int hi = lah.height + _pmDelta;
                LineSoup ls = slices.get(hi);
                if (ls != null) {
                    for (Line l : ls.all) {
                        double lps = start.line.findPPram(l.start), lpe = start.line.findPPram(l.end);
                        double overlap = 0;
                        if (lpe < lps)
                            overlap = 0;
                        else if (lps > face.minP && lpe < face.maxP || lps < face.minP && lpe > face.maxP)
                            overlap = 1;
                        else if (lps < face.minP && lpe > face.minP)
                            overlap = (lpe - face.minP) / (lpe - lps);
                        else if (lps < face.maxP && lpe > face.maxP)
                            overlap = (face.maxP - lps) / (lpe - lps);
                        double angle = l.absAngle(start.line);
                        if (overlap > 0.8 && angle < 0.3 || overlap > 0.5 && /* 0.1 for aggressive clustering */
                        angle < 0.1) {
                            // if (overlap > 0.1 && angle < 0.5 ) {
                            if (l.distance(lah.line) < delta * TweedSettings.settings.megafacacadeClusterGradient) {
                                LineAtHeight toProc = new LineAtHeight(hi, l);
                                if (lines.contains(toProc)) {
                                    toProcess.add(toProc);
                                    face.put(hi, l);
                                    lines.remove(toProc);
                                    // bit strange: depends on the processing order of the set
                                    face.minP = Mathz.min(face.minP, lps);
                                    face.maxP = Mathz.max(face.maxP, lpe);
                                }
                            }
                        }
                    }
                }
            }
        }
        if (face.values().stream().flatMap(x -> x.stream()).count() > 5)
            faces.add(face);
        else
            System.out.println("skipping small megafacade");
    }
    Collections.sort(faces);
    processMegaFaces();
    return faces;
}
Also used : FindLines(org.twak.viewTrace.FindLines) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) CullHint(com.jme3.scene.Spatial.CullHint) Line(org.twak.utils.Line) SuperLine(org.twak.viewTrace.SuperLine) SliceParameters(org.twak.viewTrace.SliceParameters) LineSoup(org.twak.viewTrace.LineSoup) HashSet(java.util.HashSet)

Aggregations

ArrayList (java.util.ArrayList)3 HashSet (java.util.HashSet)3 Line (org.twak.utils.Line)3 Material (com.jme3.material.Material)2 ColorRGBA (com.jme3.math.ColorRGBA)2 Geometry (com.jme3.scene.Geometry)2 Mesh (com.jme3.scene.Mesh)2 Node (com.jme3.scene.Node)2 VertexBuffer (com.jme3.scene.VertexBuffer)2 Graphics2D (java.awt.Graphics2D)2 Collection (java.util.Collection)2 Collections (java.util.Collections)2 Comparator (java.util.Comparator)2 IdentityHashMap (java.util.IdentityHashMap)2 Iterator (java.util.Iterator)2 List (java.util.List)2 Map (java.util.Map)2 Set (java.util.Set)2 Collectors (java.util.stream.Collectors)2 Matrix4d (javax.vecmath.Matrix4d)2