Search in sources :

Example 11 with Loop

use of org.twak.utils.collections.Loop in project chordatlas by twak.

the class CutHoles method cutHoles.

public static void cutHoles(LoopL<Point2d> out, double tol, Map<Point2d, Line> created) {
    MultiMap<Boolean, Loop<Point2d>> holeToLoop = new MultiMap<>();
    Iterator<Loop<Point2d>> lit = out.iterator();
    while (lit.hasNext()) {
        // a hole can be a backwards loop...
        Loop<Point2d> loop = lit.next();
        double area = Loopz.area(loop);
        if (Math.abs(area) < tol * tol)
            lit.remove();
        boolean isHole = area > 0;
        holeToLoop.put(isHole, loop);
        for (Loop<Point2d> h : loop.holes) {
            if (Loopz.area(h) > 0)
                h.reverse();
            holeToLoop.put(false, h);
        }
    }
    for (Loop<Point2d> hole : holeToLoop.get(false)) {
        Point2d origin = new Point2d(Double.MAX_VALUE, 0);
        Loopable<Point2d> originL = null;
        for (Loopable<Point2d> p : hole.loopableIterator()) {
            if (p.get().x < origin.x) {
                originL = p;
                origin = originL.get();
            }
        }
        LinearForm ray = new LinearForm(0, 1);
        ray.findC(origin);
        double nearestD = Double.MAX_VALUE;
        Loopable<Point2d> nearestL = null;
        Point2d nearestH = null;
        for (Loop<Point2d> loop : out) {
            for (Loopable<Point2d> line : loop.loopableIterator()) {
                Point2d a = line.get(), b = line.getNext().get();
                if (a.y > origin.y && b.y < origin.y || a.y < origin.y && b.y > origin.y) {
                    Point2d hit = new Line(a, b).intersects(ray);
                    if (hit != null && hit.x < origin.x && (origin.x - hit.x < nearestD)) {
                        nearestD = origin.x - hit.x;
                        nearestL = line;
                        nearestH = hit;
                    }
                }
            }
        }
        if (nearestH == null)
            System.err.println("failed to find outer ring for hole");
        else {
            if (created != null)
                created.put(nearestH, new Line(nearestL.get(), nearestL.getNext().get()));
            Loopable<Point2d> hitPtF = new Loopable<Point2d>(nearestH), hitPtS = new Loopable<Point2d>(nearestH), originL2 = new Loopable(origin);
            hitPtS.setNext(nearestL.getNext());
            hitPtF.setPrev(nearestL);
            hitPtS.getNext().setPrev(hitPtS);
            hitPtF.getPrev().setNext(hitPtF);
            originL.getNext().setPrev(originL2);
            originL2.setNext(originL.getNext());
            originL.setNext(hitPtS);
            hitPtS.setPrev(originL);
            hitPtF.setNext(originL2);
            originL2.setPrev(hitPtF);
        }
        out.remove(hole);
    }
}
Also used : Loop(org.twak.utils.collections.Loop) LinearForm(org.twak.utils.geom.LinearForm) Line(org.twak.utils.Line) Loopable(org.twak.utils.collections.Loopable) MultiMap(org.twak.utils.collections.MultiMap) Point2d(javax.vecmath.Point2d)

Example 12 with Loop

use of org.twak.utils.collections.Loop 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 13 with Loop

use of org.twak.utils.collections.Loop in project chordatlas by twak.

the class GISGen method importMesh.

private void importMesh(int index) {
    LoopL<Point3d> polies = blocks.get(index);
    List<Vector2D> verts = polies.stream().flatMap(ll -> ll.streamAble()).map(x -> {
        Line3d l = new Line3d(x.get(), x.getNext().get());
        l.move(perp(l.dir(), EXPAND_MESH));
        return new Vector2D(l.start.x, l.start.z);
    }).collect(Collectors.toList());
    double tol = 0.0001;
    ConvexHull2D chull = null;
    while (tol < 10) {
        try {
            chull = new MonotoneChain(false, tol).generate(verts);
            tol = 1000;
        } catch (ConvergenceException e) {
            tol *= 10;
        }
    }
    if (chull == null) {
        System.out.println("unable to find hull");
        return;
    }
    Loop<Point3d> hull = new Loop<Point3d>((Arrays.stream(chull.getLineSegments()).map(x -> new Point3d(x.getStart().getX(), 0, x.getStart().getY())).collect(Collectors.toList())));
    File root = new File(Tweed.SCRATCH + "meshes" + File.separator);
    int i = 0;
    File l;
    while ((l = new File(root, "" + i)).exists()) i++;
    l.mkdirs();
    File croppedFile = new File(l, CROPPED_OBJ);
    boolean found = false;
    for (Gen gen : tweed.frame.gens(MiniGen.class)) {
        // minigen == optimised obj
        ((MiniGen) gen).clip(hull, croppedFile);
        found = true;
    }
    if (!found)
        for (Gen gen : tweed.frame.gens(MeshGen.class)) {
            // obj == just import whole obj
            ObjGen objg = (ObjGen) gen;
            try {
                Files.asByteSource(objg.getFile()).copyTo(Files.asByteSink(croppedFile));
                objg.setVisible(false);
                found = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    if (found) {
        Graph2D g2 = new Graph2D();
        polies.stream().flatMap(ll -> ll.streamAble()).forEach(x -> g2.add(new Point2d(x.get().x, x.get().z), new Point2d(x.getNext().get().x, x.getNext().get().z)));
        g2.removeInnerEdges();
        // new Plot (true, g2 );
        UnionWalker uw = new UnionWalker();
        for (Point2d p : g2.map.keySet()) for (Line line : g2.map.get(p)) uw.addEdge(line.end, line.start);
        // new Plot (true, new ArrayList( uw.map.keySet()) );
        Loopz.writeXZObj(uw.findAll(), new File(l, "gis.obj"), true);
        Loopz.writeXZObj(Loopz.to2dLoop(polies, 1, null), new File(l, "gis_footprints.obj"), false);
        BlockGen bg = new BlockGen(l, tweed, polies);
        lastMesh.put(index, bg);
        tweed.frame.addGen(bg, true);
        tweed.frame.setSelected(bg);
    } else
        JOptionPane.showMessageDialog(tweed.frame(), "Failed to find mesh from minimesh or gml layers");
}
Also used : FactoryException(org.opengis.referencing.FactoryException) Arrays(java.util.Arrays) CRS(org.geotools.referencing.CRS) NoSuchAuthorityCodeException(org.opengis.referencing.NoSuchAuthorityCodeException) Matrix4d(javax.vecmath.Matrix4d) Closer(org.twak.viewTrace.Closer) ConvexHull2D(org.apache.commons.math3.geometry.euclidean.twod.hull.ConvexHull2D) Loop(org.twak.utils.collections.Loop) ObjRead(org.twak.utils.geom.ObjRead) Complete(org.twak.utils.Parallel.Complete) Map(java.util.Map) Point3d(javax.vecmath.Point3d) LoopL(org.twak.utils.collections.LoopL) SuperLoop(org.twak.utils.collections.SuperLoop) Parallel(org.twak.utils.Parallel) ListDownLayout(org.twak.utils.ui.ListDownLayout) Line(org.twak.utils.Line) Set(java.util.Set) ConvergenceException(org.apache.commons.math3.exception.ConvergenceException) DefaultGeocentricCRS(org.geotools.referencing.crs.DefaultGeocentricCRS) Collectors(java.util.stream.Collectors) SatUtils(org.twak.footprints.SatUtils) FacadeFinder(org.twak.viewTrace.FacadeFinder) List(java.util.List) Optional(java.util.Optional) GMLReader(org.twak.viewTrace.GMLReader) Line3d(org.twak.utils.geom.Line3d) JPanel(javax.swing.JPanel) GenHandlesSelect(org.twak.tweed.GenHandlesSelect) FacadeTool(org.twak.tweed.tools.FacadeTool) HashMap(java.util.HashMap) Graph2D(org.twak.utils.geom.Graph2D) Pair(org.twak.utils.Pair) Vector3d(javax.vecmath.Vector3d) Vector2D(org.apache.commons.math3.geometry.euclidean.twod.Vector2D) Tweed(org.twak.tweed.Tweed) ArrayList(java.util.ArrayList) TweedSettings(org.twak.tweed.TweedSettings) HashSet(java.util.HashSet) Files(com.google.common.io.Files) SelectTool(org.twak.tweed.tools.SelectTool) NoSuchElementException(java.util.NoSuchElementException) JComponent(javax.swing.JComponent) UnionWalker(org.twak.utils.geom.UnionWalker) Work(org.twak.utils.Parallel.Work) MonotoneChain(org.apache.commons.math3.geometry.euclidean.twod.hull.MonotoneChain) IOException(java.io.IOException) JOptionPane(javax.swing.JOptionPane) File(java.io.File) Loopz(org.twak.utils.collections.Loopz) Point2d(javax.vecmath.Point2d) ConvexHull2D(org.apache.commons.math3.geometry.euclidean.twod.hull.ConvexHull2D) Line3d(org.twak.utils.geom.Line3d) MonotoneChain(org.apache.commons.math3.geometry.euclidean.twod.hull.MonotoneChain) Point3d(javax.vecmath.Point3d) ConvergenceException(org.apache.commons.math3.exception.ConvergenceException) UnionWalker(org.twak.utils.geom.UnionWalker) Loop(org.twak.utils.collections.Loop) SuperLoop(org.twak.utils.collections.SuperLoop) IOException(java.io.IOException) Graph2D(org.twak.utils.geom.Graph2D) Line(org.twak.utils.Line) Vector2D(org.apache.commons.math3.geometry.euclidean.twod.Vector2D) Point2d(javax.vecmath.Point2d) File(java.io.File)

Example 14 with Loop

use of org.twak.utils.collections.Loop in project chordatlas by twak.

the class LineGen3d method calculate.

@Override
public void calculate() {
    for (Spatial s : gNode.getChildren()) s.removeFromParent();
    {
        Geometry geom;
        Mesh m = new Mesh();
        m.setMode(Mesh.Mode.Lines);
        List<Float> coords = new ArrayList();
        List<Integer> inds = new ArrayList();
        for (Line3d l : getLines()) {
            inds.add(inds.size());
            inds.add(inds.size());
            coords.add((float) l.start.x);
            coords.add((float) l.start.y);
            coords.add((float) l.start.z);
            coords.add((float) l.end.x);
            coords.add((float) l.end.y);
            coords.add((float) l.end.z);
        }
        m.setBuffer(VertexBuffer.Type.Position, 3, Arrayz.toFloatArray(coords));
        m.setBuffer(VertexBuffer.Type.Index, 2, Arrayz.toIntArray(inds));
        geom = new Geometry(filename, m);
        geom.setCullHint(CullHint.Never);
        Material lineMaterial = new Material(tweed.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        lineMaterial.setColor("Color", new ColorRGBA(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1f));
        geom.setMaterial(lineMaterial);
        geom.setLocalTranslation(0, 0, 0);
        gNode.attachChild(geom);
    }
    // int c = 0;
    VertexBuffer emptyVB = new VertexBuffer(Type.Index);
    emptyVB.setupData(Usage.Static, 3, Format.UnsignedShort, BufferUtils.createShortBuffer(0));
    {
        Geometry geom;
        Random randy = new Random();
        for (Map.Entry<Loop<Point3d>, Integer> e : getFaces().entrySet()) {
            Loop<Point3d> p = e.getKey();
            final int callbackI = e.getValue();
            Mesh m = Jme3z.fromLoop(p);
            // m.setMode( Mesh.Mode.Triangles );
            // 
            // List<Integer> inds = new ArrayList<>();
            // List<Float> pos = new ArrayList<>();
            // List<Float> norms = new ArrayList<>();
            // 
            // Loopz.triangulate( p, true, inds, pos, norms );
            // 
            // m.set setVe( Type.Index, Arrayz.toIntArray(inds));
            geom = new Geometry(filename, m);
            geom.setCullHint(CullHint.Never);
            // ColorRGBA col = Jme3z.toJme( Rainbow.getColour( c++ ) );
            ColorRGBA col = new ColorRGBA(color.getRed() * randy.nextFloat() / 500f + 0.1f, color.getGreen() * randy.nextFloat() / 500f + 0.1f, color.getBlue() * randy.nextFloat() / 500f + 0.1f, 1f);
            Material mat = new Material(tweed.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
            mat.setColor("Diffuse", col);
            mat.setColor("Ambient", col);
            mat.setBoolean("UseMaterialColors", true);
            geom.setUserData(ClickMe.class.getSimpleName(), new Object[] { new ClickMe() {

                @Override
                public void clicked(Object data) {
                    polyClicked(callbackI);
                }
            } });
            geom.setUserData(Gen.class.getSimpleName(), new Object[] { this });
            geom.setMaterial(mat);
            geom.setLocalTranslation(0, 0, 0);
            if (TweedSettings.settings.LOD) {
                LodGenerator lod = new LodGenerator(geom);
                lod.bakeLods(LodGenerator.TriangleReductionMethod.COLLAPSE_COST, 10, 100);
                GISLodControl lc = new GISLodControl();
                lc.setTrisPerPixel(0.000001f);
                geom.addControl(lc);
            }
            gNode.attachChild(geom);
        }
    }
    gNode.updateModelBound();
    super.calculate();
}
Also used : Loop(org.twak.utils.collections.Loop) ClickMe(org.twak.tweed.ClickMe) VertexBuffer(com.jme3.scene.VertexBuffer) ArrayList(java.util.ArrayList) Mesh(com.jme3.scene.Mesh) Material(com.jme3.material.Material) Line3d(org.twak.utils.geom.Line3d) Geometry(com.jme3.scene.Geometry) LodGenerator(jme3tools.optimize.LodGenerator) ColorRGBA(com.jme3.math.ColorRGBA) Random(java.util.Random) Spatial(com.jme3.scene.Spatial) Point3d(javax.vecmath.Point3d) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

Loop (org.twak.utils.collections.Loop)14 Point2d (javax.vecmath.Point2d)8 Point3d (javax.vecmath.Point3d)8 ArrayList (java.util.ArrayList)6 Line (org.twak.utils.Line)4 Line3d (org.twak.utils.geom.Line3d)4 List (java.util.List)3 Matrix4d (javax.vecmath.Matrix4d)3 LoopL (org.twak.utils.collections.LoopL)3 Material (com.jme3.material.Material)2 ColorRGBA (com.jme3.math.ColorRGBA)2 Geometry (com.jme3.scene.Geometry)2 Spatial (com.jme3.scene.Spatial)2 File (java.io.File)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Vector3d (javax.vecmath.Vector3d)2 FactoryException (org.opengis.referencing.FactoryException)2 NoSuchAuthorityCodeException (org.opengis.referencing.NoSuchAuthorityCodeException)2 Face (org.twak.camp.Output.Face)2