Search in sources :

Example 11 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class SkelFootprint method mergeSameClassification.

public static void mergeSameClassification(HalfMesh2 mesh) {
    // goal is to encode a polygon with holes as a single perimeter loop that backtracks along itself....
    Set<HalfEdge> edges = new LinkedHashSet();
    for (HalfFace hf : mesh.faces) for (HalfEdge e2 : hf.edges()) if (e2.over != null && ((SuperFace) e2.face).classification == ((SuperFace) e2.over.face).classification)
        edges.add(e2);
    edges: while (!edges.isEmpty()) {
        HalfEdge e = edges.iterator().next();
        if (e.over == null) {
            // debug condition
            edges.remove(e);
            continue;
        }
        HalfFace a = e.face, b = e.over.face;
        if (a == b) {
            edges.remove(e);
            continue;
        }
        {
            HalfEdge start = null;
            while (// set a's edge to be one that we won't fuck with
            a.e.over != null && a.e.over.face == b) {
                if (a.e == start) {
                    for (HalfEdge f : a.edges()) {
                        edges.remove(f);
                        edges.remove(f.over);
                        if (f.next.over.next.over != f) {
                            HalfEdge beforeBreak = f.over.findBefore();
                            beforeBreak.next = f.next.over.next;
                            b.e = beforeBreak;
                        }
                    }
                    ((SuperFace) b).mergeFrom((SuperFace) a);
                    mesh.faces.remove(a);
                    continue edges;
                }
                if (start == null)
                    start = a.e;
                a.e = a.e.next;
            }
        }
        for (HalfEdge oeb : a.edges()) {
            HalfEdge oe = oeb.next;
            edges.remove(oe);
            if ((oeb.over == null || oeb.over.face != b) && oe.over != null && oe.over.face == b) {
                edges.remove(oe.over);
                HalfEdge le = oe;
                while (le.next.over != null && le.next.over.face == b && le.next.over.next == le.over) {
                    le = le.next;
                    edges.remove(le);
                    edges.remove(le.over);
                }
                le.over.findBefore().next = le.next;
                oeb.next = oe.over.next;
                ((SuperFace) a).mergeFrom((SuperFace) b);
                mesh.faces.remove(b);
                for (HalfEdge e2 : a.edges()) {
                    if (e2.over != null && e2.over.face == b) {
                        edges.remove(e2);
                        edges.remove(e2.over);
                    }
                    e2.face = a;
                }
                // only remove the first boundary between a and b
                break;
            }
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace)

Example 12 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class SkelFootprint method mergeSmallFaces.

private static void mergeSmallFaces(SolverState SS) {
    Set<HalfFace> togo = new LinkedHashSet(SS.mesh.faces);
    while (!togo.isEmpty()) {
        HalfFace f = togo.iterator().next();
        togo.remove(f);
        if (-f.area() < 5) {
            double bestLen = 0;
            HalfEdge longest = null;
            for (HalfEdge e : f) {
                double len = e.length();
                if (e.over != null && e.over.face != f && len > bestLen) {
                    bestLen = len;
                    longest = e;
                }
            }
            if (longest != null) {
                togo.remove(f);
                longest.dissolve(SS.mesh);
                togo.add(longest.face);
            }
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace)

Example 13 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class SkelFootprint method assignGreedyProfiles.

private static void assignGreedyProfiles(SolverState SS) {
    Prof defaultProf = defaultProf(null);
    for (HalfFace f : SS.mesh) for (List<HalfEdge> le : f.parallelFaces(0.1)) {
        List<Prof> profs = new ArrayList();
        for (HalfEdge he : le) {
            SuperLine sl = ((SuperEdge) he).profLine;
            if (sl != null) {
                MegaFacade mf = sl.getMega();
                if (mf != null)
                    profs.addAll(mf.getTween(he.start, he.end, 0));
            }
        }
        Prof p = null;
        if (!profs.isEmpty())
            p = Prof.parameterize(profs);
        else
            p = defaultProf;
        for (HalfEdge he : le) ((SuperEdge) he).prof = p;
    }
}
Also used : ArrayList(java.util.ArrayList) SuperLine(org.twak.viewTrace.SuperLine) MegaFacade(org.twak.tweed.gen.ProfileGen.MegaFacade) List(java.util.List) ArrayList(java.util.ArrayList) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace)

Example 14 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class SkelFootprint method cleanFootprints.

private static void cleanFootprints(HalfMesh2 mesh) {
    for (HalfFace hf : mesh.faces) for (HalfEdge e : hf.edges()) if (e.over != null && e.over.face != e.face)
        e.over = null;
    Map<HalfEdge, Double> mergePoint = new HashMap();
    Predicate<HalfEdge> badEdges = new Predicate<HalfMesh2.HalfEdge>() {

        @Override
        public boolean test(HalfEdge t) {
            if (// is edge within a single face
            t.over != null)
                // preserve as hole-marker
                return false;
            double len = t.length();
            if (t.length() < 0.2) {
                mergePoint.put(t, 0.5);
                return true;
            }
            double angleNext = t.line().absAngle(t.next.line());
            final double tol = 0.1;
            if (t.next.over == null && len < t.next.length() && angleNext > Math.PI - tol) {
                mergePoint.put(t, 0.);
                return true;
            }
            if (t.next.over == null && angleNext < tol) {
                mergePoint.put(t, 0.);
                return true;
            }
            HalfEdge prev = t.findBefore();
            double anglePrev = t.line().absAngle(prev.line());
            if (prev.over == null && len <= prev.length() && anglePrev > Math.PI - tol) {
                mergePoint.put(t, 1.);
                return true;
            }
            if (prev.over == null && anglePrev < tol) {
                mergePoint.put(t, 1.);
                return true;
            }
            return false;
        }
    };
    f: for (HalfFace f : new ArrayList<>(mesh.faces)) {
        Set<HalfEdge> togo = Streamz.stream(f.edges()).filter(badEdges).collect(Collectors.toSet());
        while (!togo.isEmpty()) {
            HalfEdge g = togo.iterator().next(), p = g.findBefore(), n = g.next;
            togo.remove(g);
            togo.remove(p);
            togo.remove(n);
            if (g.replaceByPoint(mesh, g.line().fromPPram(mergePoint.get(g))))
                continue f;
            HalfEdge pp = p.findBefore();
            Streamz.stream(pp, p, n, n.next).forEach(o -> togo.remove(o));
            Streamz.stream(pp, p, n, n.next).filter(badEdges).forEach(e -> togo.add(e));
        }
    }
    for (HalfFace f : mesh.faces) {
        Set<Point2d> seen = new HashSet<>();
        for (HalfEdge e : f) {
            if (seen.contains(e.end) && e.over == null && e.next.over == null) {
                HalfEdge n = e.next;
                Point2d edited;
                Vector2d b4 = e.line().dir(), af = n.line().dir();
                b4.normalize();
                af.normalize();
                b4.set(b4.y, -b4.x);
                af.set(af.y, -af.x);
                b4.add(af);
                b4.scale(1 / b4.length());
                edited = new Point2d(b4);
                edited.add(e.end);
                n.start = edited;
                e.end = new Point2d(edited);
            }
            seen.add(e.end);
        }
    }
}
Also used : Color(java.awt.Color) XStream(com.thoughtworks.xstream.XStream) Arrays(java.util.Arrays) FloatBuffer(java.nio.FloatBuffer) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace) Type(com.jme3.scene.VertexBuffer.Type) Arrayz(org.twak.utils.collections.Arrayz) Loop(org.twak.utils.collections.Loop) Node(com.jme3.scene.Node) SkelGen(org.twak.tweed.gen.skel.SkelGen) MutableDouble(org.twak.utils.MutableDouble) ColorRGBAPainter(org.twak.viewTrace.ColorRGBAPainter) Map(java.util.Map) Cache(org.twak.utils.Cache) Material(com.jme3.material.Material) ChangeListener(javax.swing.event.ChangeListener) Streamz(org.twak.utils.collections.Streamz) Point3d(javax.vecmath.Point3d) ChangeEvent(javax.swing.event.ChangeEvent) VertexBuffer(com.jme3.scene.VertexBuffer) LoopL(org.twak.utils.collections.LoopL) Predicate(java.util.function.Predicate) Line(org.twak.utils.Line) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) Set(java.util.Set) HalfMesh2(org.twak.utils.geom.HalfMesh2) CollisionResult(com.jme3.collision.CollisionResult) Vector2d(javax.vecmath.Vector2d) Collectors(java.util.stream.Collectors) FileNotFoundException(java.io.FileNotFoundException) MFPoint(org.twak.tweed.gen.FeatureCache.MFPoint) List(java.util.List) JSlider(javax.swing.JSlider) Optional(java.util.Optional) Rainbow(org.twak.utils.ui.Rainbow) CollisionResults(com.jme3.collision.CollisionResults) Mesh(com.jme3.scene.Mesh) Geometry(com.jme3.scene.Geometry) IntStream(java.util.stream.IntStream) ActionListener(java.awt.event.ActionListener) DBSCANClusterer(org.apache.commons.math3.ml.clustering.DBSCANClusterer) Vector2f(com.jme3.math.Vector2f) HashMap(java.util.HashMap) MiniFacade(org.twak.viewTrace.facades.MiniFacade) Cach(org.twak.utils.Cach) Plot(org.twak.utils.ui.Plot) SwingConstants(javax.swing.SwingConstants) TreeSet(java.util.TreeSet) Clusterable(org.apache.commons.math3.ml.clustering.Clusterable) Tweed(org.twak.tweed.Tweed) IndexBuffer(com.jme3.scene.mesh.IndexBuffer) ArrayList(java.util.ArrayList) TweedSettings(org.twak.tweed.TweedSettings) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) Mathz(org.twak.utils.Mathz) PaintThing(org.twak.utils.PaintThing) NoSuchElementException(java.util.NoSuchElementException) ProgressMonitor(javax.swing.ProgressMonitor) LinkedHashSet(java.util.LinkedHashSet) MatParam(com.jme3.material.MatParam) JButton(javax.swing.JButton) Texture2D(com.jme3.texture.Texture2D) Iterator(java.util.Iterator) MultiMap(org.twak.utils.collections.MultiMap) BufferUtils(com.jme3.util.BufferUtils) Vector3f(com.jme3.math.Vector3f) MeshBuilder(org.twak.siteplan.jme.MeshBuilder) MegaFacade(org.twak.tweed.gen.ProfileGen.MegaFacade) ModeCollector(org.twak.viewTrace.ModeCollector) JOptionPane(javax.swing.JOptionPane) MegaFeatures(org.twak.tweed.gen.FeatureCache.MegaFeatures) ActionEvent(java.awt.event.ActionEvent) File(java.io.File) Loopz(org.twak.utils.collections.Loopz) Point2d(javax.vecmath.Point2d) Jme3z(org.twak.siteplan.jme.Jme3z) Ray(com.jme3.math.Ray) SuperLine(org.twak.viewTrace.SuperLine) LineHeight(org.twak.viewTrace.facades.LineHeight) Format(com.jme3.scene.VertexBuffer.Format) Cluster(org.apache.commons.math3.ml.clustering.Cluster) ColorRGBA(com.jme3.math.ColorRGBA) FileReader(java.io.FileReader) ImageRaster(com.jme3.texture.image.ImageRaster) Comparator(java.util.Comparator) Collections(java.util.Collections) Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace) MutableDouble(org.twak.utils.MutableDouble) Predicate(java.util.function.Predicate) Vector2d(javax.vecmath.Vector2d) Point2d(javax.vecmath.Point2d) HalfMesh2(org.twak.utils.geom.HalfMesh2) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 15 with HalfEdge

use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.

the class SkelFootprint method mergeOnProfiles.

private void mergeOnProfiles(HalfMesh2 mesh, List<Line> footprint) {
    System.out.println("merging over profiles...");
    TreeSet<HalfFace> togo = new TreeSet<>((HalfFace o1, HalfFace o2) -> Double.compare(o1.area(), o2.area()));
    togo.addAll(mesh.faces);
    int count = 0;
    while (!togo.isEmpty()) {
        HalfFace f = togo.pollFirst();
        Cache<HalfEdge, MutableDouble> crossedBy = new Cach<>(e -> new MutableDouble(0));
        for (HalfEdge e : f) {
            SuperEdge se = (SuperEdge) e;
            if (se.profLine != null) {
                MegaFacade mf = ((SuperLine) se.profLine).mega;
                if (mf != null)
                    for (Prof p : mf.getTween(se.start, se.end, 0)) {
                        Line proj = new Line(Pointz.to2(p.to3d(p.get(0))), Pointz.to2(p.to3d(p.get(p.size() - 1))));
                        for (HalfEdge e2 : f) {
                            SuperEdge se2 = (SuperEdge) e2;
                            if (se2.profLine == null && (se2.over == null || ((SuperEdge) se2.over).profLine == null) && e2.over != null && e2.line().intersects(proj) != null && Mathz.inRange(e2.line().absAngle(proj), 0.25 * Math.PI, 0.75 * Math.PI)) {
                                crossedBy.get(e2).d += TweedSettings.settings.profileHSampleDist;
                            }
                        }
                    }
            }
        }
        count += crossedBy.cache.size();
        Optional<Map.Entry<HalfEdge, MutableDouble>> longestO = crossedBy.cache.entrySet().stream().filter(// 
        e1 -> ((SuperEdge) e1.getKey()).profLine == null && e1.getValue().d > 0).max((e1, e2) -> Double.compare(e1.getValue().d, e2.getValue().d));
        if (longestO.isPresent()) {
            Map.Entry<HalfEdge, MutableDouble> longest = longestO.get();
            if (longest.getValue().d > 0.6 * longest.getKey().length()) {
                HalfFace tgf = longest.getKey().over.face;
                togo.remove(tgf);
                longest.getKey().face.merge(mesh, tgf);
                ((SuperFace) longest.getKey().face).mergeFrom((SuperFace) tgf);
                togo.add(f);
            }
        }
    }
    System.out.println("found crossings " + count);
    killDoubleEdges(mesh);
}
Also used : Color(java.awt.Color) XStream(com.thoughtworks.xstream.XStream) Arrays(java.util.Arrays) FloatBuffer(java.nio.FloatBuffer) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace) Type(com.jme3.scene.VertexBuffer.Type) Arrayz(org.twak.utils.collections.Arrayz) Loop(org.twak.utils.collections.Loop) Node(com.jme3.scene.Node) SkelGen(org.twak.tweed.gen.skel.SkelGen) MutableDouble(org.twak.utils.MutableDouble) ColorRGBAPainter(org.twak.viewTrace.ColorRGBAPainter) Map(java.util.Map) Cache(org.twak.utils.Cache) Material(com.jme3.material.Material) ChangeListener(javax.swing.event.ChangeListener) Streamz(org.twak.utils.collections.Streamz) Point3d(javax.vecmath.Point3d) ChangeEvent(javax.swing.event.ChangeEvent) VertexBuffer(com.jme3.scene.VertexBuffer) LoopL(org.twak.utils.collections.LoopL) Predicate(java.util.function.Predicate) Line(org.twak.utils.Line) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) Set(java.util.Set) HalfMesh2(org.twak.utils.geom.HalfMesh2) CollisionResult(com.jme3.collision.CollisionResult) Vector2d(javax.vecmath.Vector2d) Collectors(java.util.stream.Collectors) FileNotFoundException(java.io.FileNotFoundException) MFPoint(org.twak.tweed.gen.FeatureCache.MFPoint) List(java.util.List) JSlider(javax.swing.JSlider) Optional(java.util.Optional) Rainbow(org.twak.utils.ui.Rainbow) CollisionResults(com.jme3.collision.CollisionResults) Mesh(com.jme3.scene.Mesh) Geometry(com.jme3.scene.Geometry) IntStream(java.util.stream.IntStream) ActionListener(java.awt.event.ActionListener) DBSCANClusterer(org.apache.commons.math3.ml.clustering.DBSCANClusterer) Vector2f(com.jme3.math.Vector2f) HashMap(java.util.HashMap) MiniFacade(org.twak.viewTrace.facades.MiniFacade) Cach(org.twak.utils.Cach) Plot(org.twak.utils.ui.Plot) SwingConstants(javax.swing.SwingConstants) TreeSet(java.util.TreeSet) Clusterable(org.apache.commons.math3.ml.clustering.Clusterable) Tweed(org.twak.tweed.Tweed) IndexBuffer(com.jme3.scene.mesh.IndexBuffer) ArrayList(java.util.ArrayList) TweedSettings(org.twak.tweed.TweedSettings) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) Mathz(org.twak.utils.Mathz) PaintThing(org.twak.utils.PaintThing) NoSuchElementException(java.util.NoSuchElementException) ProgressMonitor(javax.swing.ProgressMonitor) LinkedHashSet(java.util.LinkedHashSet) MatParam(com.jme3.material.MatParam) JButton(javax.swing.JButton) Texture2D(com.jme3.texture.Texture2D) Iterator(java.util.Iterator) MultiMap(org.twak.utils.collections.MultiMap) BufferUtils(com.jme3.util.BufferUtils) Vector3f(com.jme3.math.Vector3f) MeshBuilder(org.twak.siteplan.jme.MeshBuilder) MegaFacade(org.twak.tweed.gen.ProfileGen.MegaFacade) ModeCollector(org.twak.viewTrace.ModeCollector) JOptionPane(javax.swing.JOptionPane) MegaFeatures(org.twak.tweed.gen.FeatureCache.MegaFeatures) ActionEvent(java.awt.event.ActionEvent) File(java.io.File) Loopz(org.twak.utils.collections.Loopz) Point2d(javax.vecmath.Point2d) Jme3z(org.twak.siteplan.jme.Jme3z) Ray(com.jme3.math.Ray) SuperLine(org.twak.viewTrace.SuperLine) LineHeight(org.twak.viewTrace.facades.LineHeight) Format(com.jme3.scene.VertexBuffer.Format) Cluster(org.apache.commons.math3.ml.clustering.Cluster) ColorRGBA(com.jme3.math.ColorRGBA) FileReader(java.io.FileReader) ImageRaster(com.jme3.texture.image.ImageRaster) Comparator(java.util.Comparator) Collections(java.util.Collections) MutableDouble(org.twak.utils.MutableDouble) MegaFacade(org.twak.tweed.gen.ProfileGen.MegaFacade) HalfEdge(org.twak.utils.geom.HalfMesh2.HalfEdge) HalfFace(org.twak.utils.geom.HalfMesh2.HalfFace) MFPoint(org.twak.tweed.gen.FeatureCache.MFPoint) Line(org.twak.utils.Line) SuperLine(org.twak.viewTrace.SuperLine) TreeSet(java.util.TreeSet) SuperLine(org.twak.viewTrace.SuperLine) Cach(org.twak.utils.Cach) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) MultiMap(org.twak.utils.collections.MultiMap)

Aggregations

HalfEdge (org.twak.utils.geom.HalfMesh2.HalfEdge)31 HalfFace (org.twak.utils.geom.HalfMesh2.HalfFace)25 Point2d (javax.vecmath.Point2d)15 MFPoint (org.twak.tweed.gen.FeatureCache.MFPoint)13 Line (org.twak.utils.Line)13 SuperLine (org.twak.viewTrace.SuperLine)11 ArrayList (java.util.ArrayList)10 HashMap (java.util.HashMap)8 HashSet (java.util.HashSet)8 MegaFeatures (org.twak.tweed.gen.FeatureCache.MegaFeatures)8 HalfMesh2 (org.twak.utils.geom.HalfMesh2)7 Color (java.awt.Color)6 LinkedHashSet (java.util.LinkedHashSet)6 List (java.util.List)6 Map (java.util.Map)6 MultiMap (org.twak.utils.collections.MultiMap)6 File (java.io.File)5 Set (java.util.Set)5 Vector2d (javax.vecmath.Vector2d)5 Cach (org.twak.utils.Cach)5