public void Remove(FaceSet faceset)
 {
     for (var face = faceset.First; face != null; face = face.Next)
     {
         Remove(face);
     }
 }
 public void Add(FaceSet faceset)
 {
     for (var face = faceset.First; face != null; face = face.Next)
     {
         Add(face);
     }
 }
        public FaceSet LightFaces(Triangle first_face, int point)
        {
            var lit_faces = new FaceSet(first_face.mesh, first_face);

            light_run++;
            LightFaces(first_face, point, lit_faces);
            return(lit_faces);
        }
Exemplo n.º 4
0
        public void Extend(FaceSet newFaces)
        {
            Triangle face, next;

            for (face = newFaces.First; face != null; face = next)
            {
                next = face.Next;
                Add(face);
            }
        }
 void LightFaces(Triangle face, int point, FaceSet lit_faces)
 {
     if (face.light_run == light_run)
     {
         return;
     }
     face.light_run = light_run;
     if (face.CanSee(point))
     {
         lit_faces.Add(face);
         for (int i = 0; i < 3; i++)
         {
             var conface = this[face.redges[i]];
             if (conface == null)
             {
                 Debug.Log($"[Connectivity] incompletely connected face");
                 continue;
             }
             LightFaces(conface, point, lit_faces);
         }
     }
 }
Exemplo n.º 6
0
        public FaceSet GetHull()
        {
            FindExtremePoints();


            FaceSet faces = FindSimplex();

            var connectivity = new Connectivity(faces);

            var dupPoints = new HashSet <int> ();

            for (int i = 0; i < mesh.verts.Length; i++)
            {
                for (var f = faces.First; f != null; f = f.Next)
                {
                    if (f.IsDup(i))
                    {
                        dupPoints.Add(i);
                        break;
                    }
                }
                if (dupPoints.Contains(i))
                {
                    continue;
                }
                for (var f = faces.First; f != null; f = f.Next)
                {
                    f.AddPoint(i);
                }
            }
            //Debug.Log($"[Quickhull] dupPoints: {dupPoints.Count}");
            //for (var f = faces.First; f != null; f = f.Next) {
            //	Debug.Log ($"[Quickhull] GetHull {f.vispoints.Count} {f.highest} {f.height}");
            //}

            FaceSet finalFaces = new FaceSet(mesh);

            int          iter = 0;
            BinaryWriter bw   = null;

            var donePoints = new HashSet <int> ();

            while (faces.Count > 0)
            {
                //Debug.Log ($"[Quickhull] iteration {iter}");
                if (dump_faces)
                {
                    bw = new BinaryWriter(File.Open($"/tmp/quickhull-{iter:D5}.bin", FileMode.Create));
                    mesh.Write(bw);
                    faces.Write(bw);
                    finalFaces.Write(bw);
                }
                iter++;
                //int nvis = 0;
                //for (var nf = faces.First; nf != null; nf = nf.Next) {
                //	nvis += nf.vispoints.Count;
                //}
                var f = faces.Pop();
                //Debug.Log ($"[Quickhull] total vis {nvis} f.vis {f.vispoints.Count} faces {faces.Count}");
                if (f.vispoints.Count < 1)
                {
                    finalFaces.Add(f);
                    continue;
                }
                int point = f.vispoints[f.highest];
                //Debug.Log ($"[Quickhull] height {f.height}");
                var litFaces = connectivity.LightFaces(f, point);
                if (dump_faces)
                {
                    bw.Write(point);
                    litFaces.Write(bw);
                }
                //Debug.Log ($"[Quickhull] final:{finalFaces.Count} faces:{faces.Count} lit:{litFaces.Count}");
                connectivity.Remove(litFaces);
                var horizonEdges = litFaces.FindOuterEdges();
                var newFaces     = new FaceSet(mesh);
                foreach (Edge e in horizonEdges)
                {
                    if (e.TouchesPoint(point))
                    {
                        var t         = connectivity[e.reverse];
                        int splitEdge = t.TouchedEdge(point);
                        //Debug.Log ($"[Quickhull] point on edge {splitEdge} {faces.Contains (t)} {finalFaces.Contains (t)} {litFaces.Contains (t)}");
                        if (splitEdge >= 0)
                        {
                            SplitTriangle(t, splitEdge, point, connectivity);
                        }
                    }
                    else
                    {
                        var tri = new Triangle(mesh, e.a, e.b, point);
                        newFaces.Add(tri);
                        connectivity.Add(tri);
                    }
                }
                donePoints.Clear();
                for (var lf = litFaces.First; lf != null; lf = lf.Next)
                {
                    for (int j = 0; j < lf.vispoints.Count; j++)
                    {
                        int p = lf.vispoints[j];
                        if (donePoints.Contains(p))
                        {
                            continue;
                        }
                        donePoints.Add(p);
                        for (var nf = newFaces.First; nf != null; nf = nf.Next)
                        {
                            if (nf.IsDup(p))
                            {
                                dupPoints.Add(p);
                                p = -1;
                                break;
                            }
                        }
                        if (p < 0)
                        {
                            continue;
                        }
                        for (var nf = newFaces.First; nf != null; nf = nf.Next)
                        {
                            nf.AddPoint(p);
                        }
                    }
                }
                //Debug.Log($"[Quickhull] dupPoints: {dupPoints.Count}");
                if (dump_faces)
                {
                    newFaces.Write(bw);
                }
                Triangle next;
                for (var nf = newFaces.First; nf != null; nf = next)
                {
                    next = nf.Next;
                    if (nf.vispoints.Count > 0)
                    {
                        faces.Add(nf);
                    }
                    else
                    {
                        finalFaces.Add(nf);
                    }
                }
                if (dump_faces)
                {
                    bw.Close();
                }
                if (connectivity.error)
                {
                    var vis = new HashSet <int> ();
                    for (var lf = litFaces.First; lf != null; lf = lf.Next)
                    {
                        for (int i = 0; i < lf.vispoints.Count; i++)
                        {
                            vis.Add(lf.vispoints[i]);
                        }
                    }
                    Debug.Log($"[Quickhull] {litFaces.Count} {vis.Count}");
                    for (var lf = litFaces.First; lf != null; lf = lf.Next)
                    {
                        float dist1 = float.PositiveInfinity;
                        float dist2 = float.PositiveInfinity;
                        for (int i = 0; i < 3; i++)
                        {
                            float d = lf.edges[i].Distance(point);
                            if (d < dist1)
                            {
                                dist1 = d;
                            }
                            d = (mesh.verts[point] - mesh.verts[lf.edges[i].a]).magnitude;
                            if (d < dist2)
                            {
                                dist2 = d;
                            }
                        }
                        Debug.Log($"    h:{lf.Dist(point)} d1:{dist1} d2:{dist2} {lf.edges[0].TouchesPoint(point)} {lf.edges[1].TouchesPoint(point)} {lf.edges[2].TouchesPoint(point)}");
                    }
                    break;
                }
            }
            if (dump_faces && !connectivity.error)
            {
                bw = new BinaryWriter(File.Open($"/tmp/quickhull-{iter++:D5}.bin", FileMode.Create));
                mesh.Write(bw);
                faces.Write(bw);
                finalFaces.Write(bw);
                bw.Write((int)-1);
                bw.Write((int)0);
                bw.Write((int)0);
                bw.Close();
            }
            error = connectivity.error;
            return(finalFaces);
        }
 public Connectivity(FaceSet faceset)
 {
     Add(faceset);
 }