Search in sources :

Example 31 with Point2d

use of javax.vecmath.Point2d 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 32 with Point2d

use of javax.vecmath.Point2d in project chordatlas by twak.

the class Prof method findProfileLines.

/**
 * We find an initial base offset. Then we cluster the start point of all
 * (clean) profiles. If any are a good distance from the initial base, we
 * add those as their own profile lines.
 *
 * The original line is offset by the remaiing data.
 */
public static List<SuperLine> findProfileLines(Collection<Prof> profiles, Line3d line) {
    List<SuperLine> out = new ArrayList();
    // PaintThing.debug.clear();
    SuperLine superLine = new SuperLine(line.start.x, line.start.z, line.end.x, line.end.z);
    double outLen = superLine.length();
    double min = Double.MAX_VALUE, max = -Double.MAX_VALUE;
    Cache<Prof, Double> vLength = new Cache<Prof, Double>() {

        @Override
        public Double create(Prof i) {
            return i.verticalLength(0.5);
        }
    };
    double vLen = profiles.stream().mapToDouble(p -> vLength.get(p)).sum();
    boolean useVertical = vLen / profiles.size() > 1;
    class Wrapper implements Clusterable {

        double[] pt;

        public Wrapper(Point2d pt) {
            this.pt = new double[] { pt.x, pt.y };
        }

        @Override
        public double[] getPoint() {
            return pt;
        }
    }
    List<Wrapper> toCluster = new ArrayList();
    List<Double> baseLineOffset = new ArrayList();
    for (Prof p : profiles) {
        if (// vLen / (5*profiles.size()))
        useVertical && vLength.get(p) < 1)
            continue;
        Prof clean = p.parameterize();
        Point2d pt = clean.get(0);
        Point3d pt3 = clean.to3d(pt);
        double ppram = superLine.findPPram(new Point2d(pt3.x, pt3.z));
        baseLineOffset.add(pt.x);
        toCluster.add(new Wrapper(new Point2d(pt.x, ppram * outLen)));
        min = Math.min(min, ppram);
        max = Math.max(max, ppram);
    }
    if (min == max || toCluster.isEmpty())
        return out;
    if (true) {
        baseLineOffset.sort(Double::compareTo);
        double modeBaselineOffset = baseLineOffset.get(baseLineOffset.size() / 2);
        DBSCANClusterer<Wrapper> cr = new DBSCANClusterer<>(1.5, 0);
        List<Cluster<Wrapper>> results = cr.cluster(toCluster);
        Iterator<Cluster<Wrapper>> cit = results.iterator();
        while (cit.hasNext()) {
            Cluster<Wrapper> cw = cit.next();
            if (cw.getPoints().size() < 2 / TweedSettings.settings.profileHSampleDist) {
                cit.remove();
                double cMeanY = cw.getPoints().stream().mapToDouble(x -> x.pt[1]).average().getAsDouble();
                double bestDist = Double.MAX_VALUE;
                Cluster<Wrapper> bestWrapper = null;
                for (Cluster<Wrapper> near : results) {
                    double meanY = near.getPoints().stream().mapToDouble(x -> x.pt[1]).average().getAsDouble();
                    double dist = Math.abs(meanY - cMeanY);
                    if (dist < bestDist) {
                        bestDist = dist;
                        bestWrapper = near;
                    }
                }
                if (bestWrapper != null)
                    bestWrapper.getPoints().addAll(cw.getPoints());
            }
        }
        {
            baseLineOffset.clear();
            int c = 0;
            for (Cluster<Wrapper> cw : results) {
                double[] minMax = cw.getPoints().stream().map(p -> new double[] { p.pt[1] }).collect(new InAxDoubleArray());
                double[] offsetA = cw.getPoints().stream().mapToDouble(p -> p.pt[0]).sorted().toArray();
                double offset = offsetA[offsetA.length / 2];
                if (offset - modeBaselineOffset < 1) {
                    for (Wrapper w : cw.getPoints()) baseLineOffset.add(w.pt[0]);
                    continue;
                }
                SuperLine sl = new SuperLine(superLine.fromPPram(minMax[0] / outLen), superLine.fromPPram(minMax[1] / outLen));
                sl.moveLeft(offset);
                out.add(sl);
                List<Point2d> pts = cw.getPoints().stream().map(w -> new Point2d(w.pt[0], w.pt[1])).collect(Collectors.toList());
                PaintThing.debug(Rainbow.getColour(c++), 1, pts);
            }
        }
    }
    Point2d nStart = superLine.fromPPram(min), nEnd = superLine.fromPPram(max);
    superLine.start = nStart;
    superLine.end = nEnd;
    baseLineOffset.sort(Double::compare);
    if (!baseLineOffset.isEmpty())
        superLine.moveLeft(baseLineOffset.get(baseLineOffset.size() / 2));
    out.add(0, superLine);
    return out;
}
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) ArrayList(java.util.ArrayList) Cluster(org.apache.commons.math3.ml.clustering.Cluster) Clusterable(org.apache.commons.math3.ml.clustering.Clusterable) InAxDoubleArray(org.twak.utils.streams.InAxDoubleArray) Point2d(javax.vecmath.Point2d) Point3d(javax.vecmath.Point3d) SuperLine(org.twak.viewTrace.SuperLine) List(java.util.List) ArrayList(java.util.ArrayList) DBSCANClusterer(org.apache.commons.math3.ml.clustering.DBSCANClusterer) Cache(org.twak.utils.Cache)

Example 33 with Point2d

use of javax.vecmath.Point2d in project chordatlas by twak.

the class Prof method findRoofLine.

public Point2d findRoofLine() {
    double nonVertRun = 0;
    Line up = new Line(0, 0, 0, 1);
    Point2d runStart = null;
    for (Pair<Point2d, Point2d> line : new ConsecutivePairs<>(this, false)) {
        Line l = new Line(line.first(), line.second());
        double angle = l.absAngle(up);
        if (angle > Math.PI / 6 && angle < Math.PI) {
            if (nonVertRun == 0)
                runStart = l.start;
            nonVertRun += l.length();
        } else {
            if (nonVertRun > 2 && runStart != null)
                return runStart;
            nonVertRun = 0;
        }
    }
    return runStart == null ? get(size() - 1) : runStart;
}
Also used : Line(org.twak.utils.Line) SuperLine(org.twak.viewTrace.SuperLine) ConsecutivePairs(org.twak.utils.collections.ConsecutivePairs) Point2d(javax.vecmath.Point2d)

Example 34 with Point2d

use of javax.vecmath.Point2d in project chordatlas by twak.

the class Prof method retarget.

public static Prof retarget(Prof p, SuperLine profileLine) {
    Line3d l = new Line3d(Pointz.to3(profileLine));
    Prof out = buildProfile(new Line3d(Pointz.to3(profileLine)), l.closestPointOn(p.to3d(p.get(0)), false));
    for (Point2d p2 : p) out.add(p.to3d(p2));
    return out;
}
Also used : Point2d(javax.vecmath.Point2d) Line3d(org.twak.utils.geom.Line3d)

Example 35 with Point2d

use of javax.vecmath.Point2d in project chordatlas by twak.

the class Prof method createCap.

public void createCap(double height) {
    {
        Line last = new Line(get(size() - 2), get(size() - 1));
        if (last.start.y == last.end.y && last.end.y < height)
            return;
    }
    for (int i = 0; i < size() - 1; i++) {
        Line l = new Line(get(i), get(i + 1));
        if (l.start.y > height) {
            remove(i);
            i--;
            continue;
        } else if (l.end.y > height) {
            l.end.x = l.xAtY(height);
            l.end.y = height;
        }
    }
    Point2d end = get(size() - 1);
    if (end.y != height) {
        end.x = new Line(get(size() - 2), get(size() - 1)).xAtY(height);
        end.y = height;
    }
    add(new Point2d(end.x - 1, height));
}
Also used : Line(org.twak.utils.Line) SuperLine(org.twak.viewTrace.SuperLine) Point2d(javax.vecmath.Point2d)

Aggregations

Point2d (javax.vecmath.Point2d)84 Line (org.twak.utils.Line)37 ArrayList (java.util.ArrayList)29 Point3d (javax.vecmath.Point3d)27 List (java.util.List)18 Vector2d (javax.vecmath.Vector2d)17 SuperLine (org.twak.viewTrace.SuperLine)17 File (java.io.File)15 Vector3d (javax.vecmath.Vector3d)15 Map (java.util.Map)14 HalfEdge (org.twak.utils.geom.HalfMesh2.HalfEdge)14 HashMap (java.util.HashMap)13 Loop (org.twak.utils.collections.Loop)13 Collectors (java.util.stream.Collectors)12 IOException (java.io.IOException)11 HashSet (java.util.HashSet)11 Set (java.util.Set)11 Tweed (org.twak.tweed.Tweed)11 Matrix4d (javax.vecmath.Matrix4d)10 LinearForm (org.twak.utils.geom.LinearForm)10