Search in sources :

Example 6 with LinearForm3D

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

the class GreebleEdge method toLF.

private static LinearForm3D toLF(Face f, double tol) {
    if (f == null)
        return null;
    Vector3d normal = f.edge.getPlaneNormal();
    normal = new Vector3d(normal.x, normal.z, normal.y);
    Point3d thro = f.definingSE.iterator().next().getStart(f);
    thro = new Point3d(thro.x, thro.z, thro.y);
    LinearForm3D out = new LinearForm3D(normal, thro);
    out.D += tol;
    return out;
}
Also used : Vector3d(javax.vecmath.Vector3d) Point3d(javax.vecmath.Point3d) LinearForm3D(org.twak.utils.geom.LinearForm3D)

Example 7 with LinearForm3D

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

the class GreebleEdge method roofGreeble.

public static boolean roofGreeble(Face f, MeshBuilder roof) {
    boolean isWall = isWall(f);
    for (Loop<SharedEdge> sl : f.edges) {
        for (Loopable<SharedEdge> sel : sl.loopableIterator()) {
            SharedEdge se = sel.get();
            boolean otherIsWall = isWall(se.getOther(f));
            if (!isWall && !otherIsWall) {
                Face oF = se.getOther(f);
                if (oF == null || order(f, oF) || f.edge.getPlaneNormal().angle(oF.edge.getPlaneNormal()) < 0.4)
                    continue;
                List<LinearForm3D> start = new ArrayList(), end = new ArrayList<>();
                {
                    SharedEdge fPrev = se.getAdjEdge(f, false), fNext = se.getAdjEdge(f, true), ofPrev = se.getAdjEdge(oF, false), ofNext = se.getAdjEdge(oF, true);
                    if (fNext == null || fPrev == null || ofNext == null || ofPrev == null)
                        continue;
                    double overHang = -0.03;
                    if (isWall(fNext.getOther(f)))
                        end.add(toLF(fNext.getOther(f), overHang));
                    else
                        end.add(roofTween(fNext, se, f));
                    if (isWall(ofPrev.getOther(oF)))
                        end.add(toLF(ofPrev.getOther(oF), overHang));
                    else
                        end.add(roofTween(se, ofPrev, oF));
                    if (isWall(fPrev.getOther(f)))
                        start.add(toLF(fPrev.getOther(f), overHang));
                    else
                        start.add(roofTween(se, fPrev, f));
                    if (isWall(ofNext.getOther(oF)))
                        start.add(toLF(ofNext.getOther(oF), overHang));
                    else
                        start.add(roofTween(ofNext, se, oF));
                }
                Point3d s = se.getStart(f), e = se.getEnd(f);
                if (end.contains(null) || start.contains(null))
                    continue;
                Tube.tube(roof, end, start, new Line3d(new Point3d(s.x, s.z, s.y), new Point3d(e.x, e.z, e.y)), toLF(f, 0), toLF(oF, 0), new CrossGen() {

                    @Override
                    public List<Point2d> gen(Vector2d left, Vector2d right) {
                        Vector2d l = new Vector2d(left);
                        l.normalize();
                        Vector2d lP = new Vector2d(l.y, -l.x);
                        Vector2d r = new Vector2d(right);
                        r.normalize();
                        Vector2d rP = new Vector2d(-r.y, r.x);
                        List<Point2d> out = new ArrayList();
                        double width = 0.15, height = 0.03;
                        Vector2d rn = new Vector2d(r);
                        rn.negate();
                        // height / Math.sin ( ( Math.PI - l.angle( rn ) ) /2 );
                        double cenOffset = 0.02;
                        Vector2d cen = new Vector2d(lP);
                        cen.add(rP);
                        cen.normalize();
                        for (double[] coords : new double[][] { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, -width }, { 0, 0, 0, height, -width }, { 0, 0, cenOffset, 0, 0 }, { -width, height, 0, 0, 0 }, { -width, 0, 0, 0, 0 } }) {
                            Point2d tmp = new Point2d(l), tmp2;
                            tmp.scale(coords[0]);
                            tmp2 = new Point2d(lP);
                            tmp2.scale(coords[1]);
                            tmp.add(tmp2);
                            tmp2 = new Point2d(cen);
                            tmp2.scale(coords[2]);
                            tmp.add(tmp2);
                            tmp2 = new Point2d(rP);
                            tmp2.scale(coords[3]);
                            tmp.add(tmp2);
                            tmp2 = new Point2d(r);
                            tmp2.scale(coords[4]);
                            tmp.add(tmp2);
                            out.add(tmp);
                        }
                        return out;
                    }
                });
            }
        }
    }
    return true;
}
Also used : ArrayList(java.util.ArrayList) LinearForm3D(org.twak.utils.geom.LinearForm3D) Line3d(org.twak.utils.geom.Line3d) SharedEdge(org.twak.camp.Output.SharedEdge) Vector2d(javax.vecmath.Vector2d) Point2d(javax.vecmath.Point2d) Point3d(javax.vecmath.Point3d) CrossGen(org.twak.viewTrace.facades.Tube.CrossGen) ArrayList(java.util.ArrayList) List(java.util.List) Face(org.twak.camp.Output.Face)

Example 8 with LinearForm3D

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

the class Prof method climb.

private static void climb(List<Line3d> lines, Line3d first, Prof monotonic, double max, boolean isUp) {
    Point3d end = isUp ? highestEnd(first) : lowestEnd(first), extrema = end;
    monotonic.add(isUp ? monotonic.size() : 0, end);
    Map<Line3d, Object> ends = new IdentityHashMap();
    BetterThan bt = new BetterThan() {

        @Override
        public boolean betterThan(double h1, double h2) {
            return isUp ? h1 > h2 : h1 < h2;
        }

        @Override
        public boolean betterThanOrEqualTo(double h1, double h2) {
            return isUp ? h1 >= h2 : h1 <= h2;
        }
    };
    Line3d next = null;
    boolean worseThanExtrema = false;
    double BIG_JUMP = TweedSettings.settings.meshHoleJumpSize;
    do {
        double bestDist = 1;
        int startOrEnd = -1;
        next = null;
        for (Line3d l : lines) {
            if ((bt.betterThan(l.end.y, extrema.y) || bt.betterThan(l.start.y, extrema.y)) && !ends.containsKey(l)) {
                for (int i = 0; i < 2; i++) {
                    double dist = l.points()[i].distance(worseThanExtrema ? extrema : end);
                    if (dist < bestDist) {
                        bestDist = dist;
                        startOrEnd = i;
                        next = l;
                    }
                }
            }
        }
        if (next == null) {
            // nothing strictly montonic, try near...limit search to near extrema (balcony width)
            bestDist = BIG_JUMP;
            for (Line3d l : lines) {
                if (!ends.containsKey(l)) {
                    for (int i = 0; i < 2; i++) {
                        double dist = l.points()[i].distance(extrema);
                        if (dist < bestDist) {
                            // 
                            bestDist = dist;
                            startOrEnd = i;
                            next = l;
                        }
                    }
                }
            }
        }
        if (next != null) {
            ends.put(next, next);
            end = next.points()[1 - startOrEnd];
            if (bt.betterThanOrEqualTo(end.y, extrema.y)) {
                if (worseThanExtrema) {
                    // add intermediate point
                    double angle = next.angle(UP);
                    if (angle < Math.PI / 2 - 0.2 || angle > Math.PI / 2 + 0.2) {
                        // intersecting with horizontal lines is messy.
                        Point3d pt = new LinearForm3D(UP, extrema).collide(end, next.dir(), next.length());
                        if (bt.betterThan(max, pt.y))
                            monotonic.add(isUp ? monotonic.size() : 0, pt);
                    }
                }
                extrema = end;
                Point3d toAdd = end;
                if (bt.betterThan(end.y, max)) {
                    // trim to max
                    toAdd = new LinearForm3D(UP, new Vector3d(0, max, 0)).collide(next.points()[startOrEnd], next.dir(), next.length());
                    if (// intersection failed
                    toAdd.getClass() != Point3d.class && bt.betterThan(max, toAdd.y))
                        toAdd = new Point3d(end.x, max, end.z);
                    else
                        toAdd = null;
                    next = null;
                }
                if (toAdd != null)
                    monotonic.add(isUp ? monotonic.size() : 0, toAdd);
                worseThanExtrema = false;
            } else
                worseThanExtrema = true;
        }
    } while (next != null);
}
Also used : Vector3d(javax.vecmath.Vector3d) Point3d(javax.vecmath.Point3d) IdentityHashMap(java.util.IdentityHashMap) LinearForm3D(org.twak.utils.geom.LinearForm3D) Line3d(org.twak.utils.geom.Line3d)

Example 9 with LinearForm3D

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

the class Prof method buildProfile.

public static Prof buildProfile(ObjRead mesh, Line3d oLine, Point3d cen, double minH, double maxH, double minD, double maxD, Tweed tweed, Node dbg) {
    Prof monotonic = buildProfile(oLine, cen);
    Vector3d dir = oLine.dir();
    dir.normalize();
    Vector3d sliceNormal = new Vector3d(dir.x, 0, dir.z);
    LinearForm3D lf = new LinearForm3D(sliceNormal, cen);
    List<Line3d> lines = ObjSlice.sliceTri(mesh, lf, 0.5, new Vector3d(-dir.z, 0, dir.x), Math.PI / 2 + 0.1);
    // dbg.attachChild( Jme3z.lines( tweed, lines, ColorRGBA.Blue, 2 ) );
    Line3d first = null;
    double closestStart = Double.MAX_VALUE;
    for (Line3d l : lines) {
        if (l.start.y > l.end.y)
            l.reverse();
        double dist = l.distanceSquared(cen);
        if (dist < closestStart) {
            closestStart = dist;
            first = l;
        }
    }
    if (first == null) {
        return null;
    // lines.clear();
    // monotonic.add( cen );
    // monotonic.add( new Point3d( cen.x, cen.y - 500, cen.z ) );
    } else {
        climb(lines, first, monotonic, maxH, true);
        climb(lines, first, monotonic, minH, false);
    }
    {
        double tol = 0.2;
        minD -= tol;
        maxD += tol;
        LinearForm min = new LinearForm(Mathz.UP).findC(new Point2d(minD, 0));
        LinearForm max = new LinearForm(Mathz.UP).findC(new Point2d(maxD, 0));
        for (int i = 0; i < monotonic.size() - 1; i++) {
            Point2d a = monotonic.get(i), b = monotonic.get(i + 1);
            if (a.x < minD && b.x < minD) {
                monotonic.remove(i);
                i--;
            } else if (a.x < minD) {
                monotonic.set(i, new LinearForm(new Line(a, b)).intersect(min));
            } else if (b.x < minD) {
                monotonic.set(i + 1, new LinearForm(new Line(a, b)).intersect(min));
                b.x = minD + Math.ulp(minD);
            }
            if (a.x > maxD && b.x > maxD) {
                monotonic.remove(i);
                i--;
            } else if (a.x > maxD) {
                monotonic.set(i, new LinearForm(new Line(a, b)).intersect(max));
            } else if (b.x > maxD) {
                monotonic.set(i + 1, new LinearForm(new Line(a, b)).intersect(max));
                b.x = maxD - Math.ulp(maxD);
            }
        }
    }
    return monotonic;
}
Also used : Line(org.twak.utils.Line) SuperLine(org.twak.viewTrace.SuperLine) Vector3d(javax.vecmath.Vector3d) Point2d(javax.vecmath.Point2d) LinearForm(org.twak.utils.geom.LinearForm) LinearForm3D(org.twak.utils.geom.LinearForm3D) Line3d(org.twak.utils.geom.Line3d)

Example 10 with LinearForm3D

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

the class Tube method angle.

private static double angle(Collection<LinearForm3D> lfs, Line3d line) {
    double min = Double.MAX_VALUE;
    for (LinearForm3D lf : lfs) {
        Point3d s = lf.project(line.start), e = lf.project(line.end);
        min = Math.min(min, line.angle(new Line3d(s, e).dir()));
    }
    return min;
}
Also used : Point3d(javax.vecmath.Point3d) LinearForm3D(org.twak.utils.geom.LinearForm3D) Line3d(org.twak.utils.geom.Line3d)

Aggregations

LinearForm3D (org.twak.utils.geom.LinearForm3D)17 Point3d (javax.vecmath.Point3d)14 Vector3d (javax.vecmath.Vector3d)10 Line3d (org.twak.utils.geom.Line3d)9 ArrayList (java.util.ArrayList)7 Point2d (javax.vecmath.Point2d)6 List (java.util.List)5 Map (java.util.Map)3 Vector2d (javax.vecmath.Vector2d)3 Loop (org.twak.utils.collections.Loop)3 MultiMap (org.twak.utils.collections.MultiMap)3 IOException (java.io.IOException)2 Collectors (java.util.stream.Collectors)2 Matrix4d (javax.vecmath.Matrix4d)2 Face (org.twak.camp.Output.Face)2 SharedEdge (org.twak.camp.Output.SharedEdge)2 MeshBuilder (org.twak.siteplan.jme.MeshBuilder)2 Line (org.twak.utils.Line)2 LinearForm (org.twak.utils.geom.LinearForm)2 CrossGen (org.twak.viewTrace.facades.Tube.CrossGen)2