Search in sources :

Example 1 with InAxDoubleArray

use of org.twak.utils.streams.InAxDoubleArray in project chordatlas by twak.

the class FindLines method regress.

private Line regress(Set<Line> things, LinearForm lfDir) {
    SimpleRegression fit = new SimpleRegression();
    // regression isn't happy on lines with infinite slope: so swap params!
    boolean flip = Math.abs(lfDir.x) > Math.abs(lfDir.y);
    for (Line l : things) if (flip) {
        fit.addData(l.start.y, l.start.x);
        fit.addData(l.end.y, l.end.x);
    } else {
        fit.addData(l.start.x, l.start.y);
        fit.addData(l.end.x, l.end.y);
    }
    double intercept = fit.getIntercept(), slope = fit.getSlope();
    if (Double.isNaN(intercept))
        return null;
    LinearForm lf;
    if (flip)
        lf = new LinearForm(1, -slope);
    else
        lf = new LinearForm(-slope, 1);
    if (lf.unitVector().angle(lfDir.unitVector()) > Math.PI / 2) {
        // if regression is pointing wrong way, flip
        lf.x = -lf.x;
        lf.y = -lf.y;
    }
    if (flip)
        lf.findC(intercept, 0);
    else
        lf.findC(0, intercept);
    double[] minMax = things.stream().map(x -> new double[] { lf.findPParam(x.start), lf.findPParam(x.end) }).collect(new InAxDoubleArray());
    // do regression
    return new Line(lf, minMax[0], minMax[1]);
}
Also used : Line(org.twak.utils.Line) Iterator(java.util.Iterator) Line(org.twak.utils.Line) Set(java.util.Set) MultiMapSet(org.twak.utils.collections.MultiMapSet) HashMap(java.util.HashMap) Vector2d(javax.vecmath.Vector2d) Pair(org.twak.utils.Pair) LinearForm(org.twak.utils.geom.LinearForm) ConsecutiveItPairs(org.twak.utils.collections.ConsecutiveItPairs) ArrayList(java.util.ArrayList) Point2d(javax.vecmath.Point2d) List(java.util.List) SimpleRegression(org.apache.commons.math3.stat.regression.SimpleRegression) Map(java.util.Map) Anglez(org.twak.utils.geom.Anglez) InAxDoubleArray(org.twak.utils.streams.InAxDoubleArray) Result(org.twak.viewTrace.RangeMerge.Result) InAxDoubleArray(org.twak.utils.streams.InAxDoubleArray) SimpleRegression(org.apache.commons.math3.stat.regression.SimpleRegression) LinearForm(org.twak.utils.geom.LinearForm)

Example 2 with InAxDoubleArray

use of org.twak.utils.streams.InAxDoubleArray 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)

Aggregations

ArrayList (java.util.ArrayList)2 Iterator (java.util.Iterator)2 List (java.util.List)2 Map (java.util.Map)2 Set (java.util.Set)2 Point2d (javax.vecmath.Point2d)2 Vector2d (javax.vecmath.Vector2d)2 Line (org.twak.utils.Line)2 Pair (org.twak.utils.Pair)2 ConsecutiveItPairs (org.twak.utils.collections.ConsecutiveItPairs)2 LinearForm (org.twak.utils.geom.LinearForm)2 InAxDoubleArray (org.twak.utils.streams.InAxDoubleArray)2 Material (com.jme3.material.Material)1 ColorRGBA (com.jme3.math.ColorRGBA)1 Geometry (com.jme3.scene.Geometry)1 Mesh (com.jme3.scene.Mesh)1 Node (com.jme3.scene.Node)1 VertexBuffer (com.jme3.scene.VertexBuffer)1 Graphics2D (java.awt.Graphics2D)1 Collection (java.util.Collection)1