GetFaces() public method

public GetFaces ( ) : HashSet
return HashSet
 static Face FindTriangleWithinPoint(HMesh mesh, Vector3 pos)
 {
     foreach (var face in mesh.GetFaces()){
         var edges = face.Circulate();
         var p1 = edges[0].vert.position;
         var p2 = edges[1].vert.position;
         var p3 = edges[2].vert.position;
         Debug.LogWarning("Points "+p1+", "+p2+", "+p3);
         if (HMeshMath.LeftOf(p1,p2,pos) && HMeshMath.LeftOf(p2,p3,pos) && HMeshMath.LeftOf(p3,p1,pos)){
             return face;
         }
     }
     Debug.LogWarning("Cannot find triangle");
     return null;
 }
 static Face FindTriangleWithinPoint(HMesh mesh, Vector3 pos)
 {
     foreach (var face in mesh.GetFaces())
     {
         var edges = face.Circulate();
         var p1    = edges[0].vert.position;
         var p2    = edges[1].vert.position;
         var p3    = edges[2].vert.position;
         Debug.LogWarning("Points " + p1 + ", " + p2 + ", " + p3);
         if (HMeshMath.LeftOf(p1, p2, pos) && HMeshMath.LeftOf(p2, p3, pos) && HMeshMath.LeftOf(p3, p1, pos))
         {
             return(face);
         }
     }
     Debug.LogWarning("Cannot find triangle");
     return(null);
 }
Example #3
0
    // Update is called once per frame
    public Mesh UpdateMesh()
    {
        Mesh mesh = GetMesh();

        Debug.Log("UpdateMesh");

        List <Vector3> lines   = new List <Vector3>();
        List <Vector3> normals = new List <Vector3>();
        List <int>     indices = new List <int>();
        HMesh          hmesh   = this.hmesh;

        foreach (var face in hmesh.GetFaces())
        {
            foreach (var edge in face.Circulate())
            {
                if (renderType == HMeshRendererType.BoundaryEdges)
                {
                    if (!edge.IsBoundary())
                    {
                        continue;
                    }
                }
                lines.Add(edge.prev.vert.position);
                lines.Add(edge.vert.position);
                normals.Add(Vector3.up);
                normals.Add(Vector3.up);
                indices.Add(indices.Count);
                indices.Add(indices.Count);
            }
        }
        mesh.Clear();
        mesh.vertices = lines.ToArray();
        mesh.normals  = normals.ToArray();
        var meshTopology = renderType == HMeshRendererType.Vertices ? MeshTopology.Points : MeshTopology.Lines;

        mesh.SetIndices(indices.ToArray(), meshTopology, 0);
        mesh.RecalculateBounds();
        mesh.UploadMeshData(false);

        return(mesh);
    }
Example #4
0
    public static void RemoveFacesWithTwoEdges(HMesh hmesh)
    {
        var faces = new List <Face>(hmesh.GetFaces());

        for (int i = 0; i < faces.Count; i++)// (var face in hmesh.GetFaces())
        {
            var edges = faces[i].Circulate();
            if (edges.Count == 2)
            {
                var opp1  = edges[0].opp;
                var opp2  = edges[1].opp;
                var vert1 = edges[0].vert;
                var vert2 = edges[1].vert;
                // reassign vertex halfedges to a he not to be destroyed
                Halfedge.Glue(opp1, opp2);
                hmesh.Destroy(faces[i]);
                hmesh.Destroy(edges[0]);
                hmesh.Destroy(edges[1]);
            }
        }
    }
Example #5
0
    void OnGUI()
    {
        if (GUI.Button(new Rect(0,0,200,50), "FaceSplit")){
            HMesh hMesh = new HMesh();
            var mf = GetComponent<MeshFilter>();
            hMesh.Build(mf.mesh);

            foreach (var f in hMesh.GetFaces()){
                f.Split();
            }

            var mesh = hMesh.Export();
            mesh.RecalculateNormals();
            mf.mesh = mesh;
        }
        if (GUI.Button(new Rect(200,0,200,50), "EdgeFlip")){
            HMesh hMesh = new HMesh();
            var mf = GetComponent<MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet<Halfedge> isFlipped = new HashSet<Halfedge>();
            foreach (var h in hMesh.GetHalfedges()){
                if (!h.IsBoundary() && !isFlipped.Contains(h)){
                    Debug.DrawLine(h.vert.position, h.prev.vert.position,Color.cyan,5);
                    h.Flip();
                    isFlipped.Add(h.opp);
                }
            }
            var mesh = hMesh.Export();
            mesh.RecalculateNormals();
            mf.mesh = mesh;
        }
        if (GUI.Button(new Rect(400,0,200,50), "EdgeSplit")){
            HMesh hMesh = new HMesh();
            var mf = GetComponent<MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet<Halfedge> isSplit = new HashSet<Halfedge>();
            foreach (var h in hMesh.GetHalfedges()){
                if (!h.IsBoundary() && !isSplit.Contains(h)){
                    Debug.DrawLine(h.vert.position, h.prev.vert.position,Color.cyan,5);
                    isSplit.Add(h.opp);
                    h.Split();
                }
            }
            var mesh = hMesh.Export();
            mesh.RecalculateNormals();
            mf.mesh = mesh;
        }
        if (GUI.Button(new Rect(600,0,200,50), "CollapseEdge")){
            HMesh hMesh = new HMesh();
            var mf = GetComponent<MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet<Halfedge> isCollapsed = new HashSet<Halfedge>();
            foreach (var h in hMesh.GetHalfedges()){
                if (!h.IsBoundary()){
                    if (!h.vert.IsBoundary() && !h.prev.vert.IsBoundary() && !isCollapsed.Contains(h)){
                        Debug.DrawLine(h.vert.position, h.prev.vert.position,Color.cyan,5);
                        isCollapsed.Add(h.opp);
                        h.Collapse();
                        break;
                    }
                }
            }
            var mesh = hMesh.Export();
            mesh.RecalculateNormals();
            mf.mesh = mesh;
        }

        if (GUI.Button(new Rect(0,50,200,50), "CirculateRndVertex")){
            HMesh hMesh = new HMesh();
            var mf = GetComponent<MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet<Halfedge> isCollapsed = new HashSet<Halfedge>();

            var vertices = new List<Vertex>(hMesh.GetVertices());
            var vertex = vertices[1];//Random.Range(0,vertices.Count-1)];
            foreach (var h in vertex.Circulate()){
                Debug.DrawLine(h.vert.position, h.prev.vert.position,Color.cyan,5);
            }
            Debug.Log("Circulate vertex: "+vertex.Circulate().Count);
        }
        if (GUI.Button(new Rect(200,50,200,50), "CirculateOppRndVertex")){
            HMesh hMesh = new HMesh();
            var mf = GetComponent<MeshFilter>();
            hMesh.Build(mf.mesh);
            //HashSet<Halfedge> isCollapsed = new HashSet<Halfedge>();

            var vertices = new List<Vertex>(hMesh.GetVertices());
            var vertex = vertices[1];//Random.Range(0,vertices.Count-1)];
            foreach (var h in vertex.CirculateOpp()){
                Debug.DrawLine(h.vert.position, h.prev.vert.position,Color.cyan,5);
            }
            Debug.Log("Circulate vertex: "+vertex.Circulate().Count);
        }
        if (GUI.Button(new Rect(400,50,200,50), "Circulate1RingRndVertex")){
            HMesh hMesh = new HMesh();
            var mf = GetComponent<MeshFilter>();
            hMesh.Build(mf.mesh);
            // HashSet<Halfedge> isCollapsed = new HashSet<Halfedge>();

            var vertices = new List<Vertex>(hMesh.GetVertices());
            var vertex = vertices[Random.Range(0,vertices.Count-1)];
            foreach (var h in vertex.CirculateOneRing()){
                Debug.DrawLine(h.vert.position, h.prev.vert.position,Color.cyan,5);
            }
            Debug.Log("Circulate 1-ring: "+vertex.CirculateOneRing().Count);
        }
        if (GUI.Button(new Rect(600,50,200,50), "CirculateRndFace")){
            HMesh hMesh = new HMesh();
            var mf = GetComponent<MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet<Halfedge> isCollapsed = new HashSet<Halfedge>();

            var faces = new List<Face>(hMesh.GetFaces());
            var face = faces[Random.Range(0,faces.Count-1)];
            foreach (var h in face.Circulate()){
                Debug.DrawLine(h.vert.position, h.prev.vert.position, Color.cyan, 5);
            }
            Debug.Log("Circulate face: "+face.Circulate().Count);
        }
    }
Example #6
0
    void OnGUI()
    {
        if (GUI.Button(new Rect(0, 0, 200, 50), "FaceSplit"))
        {
            HMesh hMesh = new HMesh();
            var   mf    = GetComponent <MeshFilter>();
            hMesh.Build(mf.mesh);

            foreach (var f in hMesh.GetFaces())
            {
                f.Split();
            }

            var mesh = hMesh.Export();
            mesh.RecalculateNormals();
            mf.mesh = mesh;
        }
        if (GUI.Button(new Rect(200, 0, 200, 50), "EdgeFlip"))
        {
            HMesh hMesh = new HMesh();
            var   mf    = GetComponent <MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet <Halfedge> isFlipped = new HashSet <Halfedge>();
            foreach (var h in hMesh.GetHalfedges())
            {
                if (!h.IsBoundary() && !isFlipped.Contains(h))
                {
                    Debug.DrawLine(h.vert.position, h.prev.vert.position, Color.cyan, 5);
                    h.Flip();
                    isFlipped.Add(h.opp);
                }
            }
            var mesh = hMesh.Export();
            mesh.RecalculateNormals();
            mf.mesh = mesh;
        }
        if (GUI.Button(new Rect(400, 0, 200, 50), "EdgeSplit"))
        {
            HMesh hMesh = new HMesh();
            var   mf    = GetComponent <MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet <Halfedge> isSplit = new HashSet <Halfedge>();
            foreach (var h in hMesh.GetHalfedges())
            {
                if (!h.IsBoundary() && !isSplit.Contains(h))
                {
                    Debug.DrawLine(h.vert.position, h.prev.vert.position, Color.cyan, 5);
                    isSplit.Add(h.opp);
                    h.Split();
                }
            }
            var mesh = hMesh.Export();
            mesh.RecalculateNormals();
            mf.mesh = mesh;
        }
        if (GUI.Button(new Rect(600, 0, 200, 50), "CollapseEdge"))
        {
            HMesh hMesh = new HMesh();
            var   mf    = GetComponent <MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet <Halfedge> isCollapsed = new HashSet <Halfedge>();
            foreach (var h in hMesh.GetHalfedges())
            {
                if (!h.IsBoundary())
                {
                    if (!h.vert.IsBoundary() && !h.prev.vert.IsBoundary() && !isCollapsed.Contains(h))
                    {
                        Debug.DrawLine(h.vert.position, h.prev.vert.position, Color.cyan, 5);
                        isCollapsed.Add(h.opp);
                        h.Collapse();
                        break;
                    }
                }
            }
            var mesh = hMesh.Export();
            mesh.RecalculateNormals();
            mf.mesh = mesh;
        }

        if (GUI.Button(new Rect(0, 50, 200, 50), "CirculateRndVertex"))
        {
            HMesh hMesh = new HMesh();
            var   mf    = GetComponent <MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet <Halfedge> isCollapsed = new HashSet <Halfedge>();

            var vertices = new List <Vertex>(hMesh.GetVertices());
            var vertex   = vertices[1];          //Random.Range(0,vertices.Count-1)];
            foreach (var h in vertex.Circulate())
            {
                Debug.DrawLine(h.vert.position, h.prev.vert.position, Color.cyan, 5);
            }
            Debug.Log("Circulate vertex: " + vertex.Circulate().Count);
        }
        if (GUI.Button(new Rect(200, 50, 200, 50), "CirculateOppRndVertex"))
        {
            HMesh hMesh = new HMesh();
            var   mf    = GetComponent <MeshFilter>();
            hMesh.Build(mf.mesh);
            //HashSet<Halfedge> isCollapsed = new HashSet<Halfedge>();

            var vertices = new List <Vertex>(hMesh.GetVertices());
            var vertex   = vertices[1];          //Random.Range(0,vertices.Count-1)];
            foreach (var h in vertex.CirculateOpp())
            {
                Debug.DrawLine(h.vert.position, h.prev.vert.position, Color.cyan, 5);
            }
            Debug.Log("Circulate vertex: " + vertex.Circulate().Count);
        }
        if (GUI.Button(new Rect(400, 50, 200, 50), "Circulate1RingRndVertex"))
        {
            HMesh hMesh = new HMesh();
            var   mf    = GetComponent <MeshFilter>();
            hMesh.Build(mf.mesh);
            // HashSet<Halfedge> isCollapsed = new HashSet<Halfedge>();

            var vertices = new List <Vertex>(hMesh.GetVertices());
            var vertex   = vertices[Random.Range(0, vertices.Count - 1)];
            foreach (var h in vertex.CirculateOneRing())
            {
                Debug.DrawLine(h.vert.position, h.prev.vert.position, Color.cyan, 5);
            }
            Debug.Log("Circulate 1-ring: " + vertex.CirculateOneRing().Count);
        }
        if (GUI.Button(new Rect(600, 50, 200, 50), "CirculateRndFace"))
        {
            HMesh hMesh = new HMesh();
            var   mf    = GetComponent <MeshFilter>();
            hMesh.Build(mf.mesh);
            HashSet <Halfedge> isCollapsed = new HashSet <Halfedge>();

            var faces = new List <Face>(hMesh.GetFaces());
            var face  = faces[Random.Range(0, faces.Count - 1)];
            foreach (var h in face.Circulate())
            {
                Debug.DrawLine(h.vert.position, h.prev.vert.position, Color.cyan, 5);
            }
            Debug.Log("Circulate face: " + face.Circulate().Count);
        }
    }
Example #7
0
    // Dissolves adjacent edges when face normals are equal. Adjecent vertices are dissolved

    /*public static int RemoveAdjecentEdges(HMesh hmesh, double thresholdDistance = 0.001, double thresholdAngle = 0.1)
     * {
     *  bool changed = false;
     *  int count = 0;
     *  do
     *  {
     *      changed = false;
     *      var heCopy = new List<Halfedge>(hmesh.GetHalfedgesRaw());
     *      for (int i = 0; i < heCopy.Count; i++)
     *      {
     *          var he1 = heCopy[i];
     *          if (he1.IsDestroyed())
     *          {
     *              continue;
     *          }
     *          for (int j = i + 1; j < heCopy.Count; j++)
     *          {
     *              var he2 = heCopy[j];
     *              if (he2.IsDestroyed())
     *              {
     *                  continue;
     *              }
     *              if (he1.opp == he2)
     *              {
     *                  continue;
     *              }
     *              var distVert1 = he1.prev.vert.positionD - he2.vert.positionD;
     *              var distVert2 = he1.vert.positionD - he2.prev.vert.positionD;
     *
     *              bool isAdjacentHalfedges = distVert1.magnitude < thresholdDistance &&
     *                                         distVert2.magnitude < thresholdDistance;
     *              if (isAdjacentHalfedges){
     *                  var he1Normal = he1.face.GetNormal();
     *                  var he2Normal = he2.face.GetNormal();
     *                  bool isSameNormal = Vector3D.Angle(he1Normal, he2Normal) < thresholdAngle;
     *                  if (isSameNormal)
     *                  {
     *                      changed = true;
     *
     *                      //Debug.Log("Joining he "+he1.id+" and "+he2.id);
     *                      //Debug.Log("Joining he "+he1.face.ToString() +" and "+he2.face.ToString());
     *
     *                      var he2Vert = he2.vert;
     *                      var he2PrevVert = he2.prev.vert;
     *                      //Debug.Log("Replace "+he2Vert.id+" with "+he1.prev.vert.id);
     *                      //Debug.Log("Replace "+he2PrevVert.id+" with "+he1.vert.id);
     *                      he2Vert.ReplaceVertex(he1.prev.vert);
     *                      he2PrevVert.ReplaceVertex(he1.vert);
     *
     *                      //Debug.Log("Destroy vert "+he2Vert.id);
     *                      //Debug.Log("Destroy vert "+he2PrevVert.id);
     *                      hmesh.Destroy(he2Vert);
     *                      hmesh.Destroy(he2PrevVert);
     *
     *                      he1.Glue(he2);
     *                      //hmesh.IsValid(HMeshValidationRules.All);
     *                      //he1.Dissolve();
     *                      hmesh.IsValid(HMeshValidationRules.All);
     *                      count++;
     *                  }
     *              }
     *          }
     *      }
     *  } while (changed);
     *  return count;
     * }*/

    /// <summary>
    /// Enforces triangular mesh
    /// </summary>
    /// <param name="hmesh"></param>
    /// <returns></returns>
    public static int FixDegenerateFaces(HMesh hmesh)
    {
        int count = 0;
        var faces = new List <Face>(hmesh.GetFaces());

        for (int i = 0; i < faces.Count; i++)// (var face in hmesh.GetFaces())}
        {
            var face = faces[i];
            //var faceWas = face.ToString();
            if (face.IsDestroyed())
            {
                continue;
            }

            // triangulate
            if (face.Circulate().Count > 3)
            {
                count++;
#if HMDebug
                var str                   = face.ToString();
                var debugFaceExp          = face.ExportLocalNeighbourhoodToObj();
                System.IO.StringWriter sw = new System.IO.StringWriter();
                var res                   = face.Triangulate(false, sw);
#else
                var res = face.Triangulate();
#endif
                if (res.Count == 0)
                {
#if HMDebug
                    Debug.LogWarning("Cannot triangulate " + str + " face is now " + face.ToString() + " " + sw.ToString());
                    Debug.LogWarning(debugFaceExp);
#endif
                    // face destroyed
                    continue;
                }
                // add new faces
                for (int j = 0; j < res.Count; j++)
                {
                    if (res[j] != face)
                    {
                        faces.Add(res[j]);
                    }
                }
            }

            // fix degenerate due to zero length edge
            foreach (var he in face.Circulate())
            {
                if (he.IsDestroyed())
                {
                    continue;
                }

                if (he.GetDirection().sqrMagnitude <= hmesh.zeroMagnitudeTresholdSqr)
                {
                    Vector3D[] positions = { he.GetCenter(), he.vert.positionD, he.prev.vert.positionD };
                    bool       collapsed = false;
                    foreach (var p in positions)
                    {
                        var collapsePrecondition = he.CollapsePrecondition(p, Halfedge.CollapsePreconditionReason.EdgeIsBoundary | Halfedge.CollapsePreconditionReason.VertexIsBoundary | Halfedge.CollapsePreconditionReason.NormalFlipped);
                        if (collapsePrecondition == Halfedge.CollapsePreconditionReason.Ok)
                        {
                            count++;
                            he.Collapse();
                            collapsed = true;
                            break;
                        }
                        else
                        {
                            Debug.Log("Cannot collapse - precondition failed " + collapsePrecondition);
                        }
                    }
                    if (!collapsed)
                    {
                        he.Collapse();
                    }
                }
            }
        }

        RemoveFacesWithTwoEdges(hmesh);

        // fix degenerate due to zero area
        faces = new List <Face>(hmesh.GetFaces());
        for (int i = faces.Count - 1; i >= 0; i--)// (var face in hmesh.GetFaces())}
        {
            var face = faces[i];
            if (face.IsDestroyed())
            {
                continue;
            }

            if (face.IsDegenerate())
            {
                // find longest edge
                Halfedge longestEdge = null;
                double   maxLength   = -1;

                var edges = face.Circulate();

                Debug.Assert(edges.Count == 3, "Edges was " + edges.Count);

                foreach (var he in edges)
                {
                    double length = he.GetDirection().sqrMagnitude;
                    if (length > maxLength)
                    {
                        maxLength   = length;
                        longestEdge = he;
                    }
                }
                if (longestEdge == null)
                {
                    Debug.LogError("Face " + face.id + " only has zero length edges");
                    continue;
                }
                var    oppVert      = longestEdge.next.vert;
                Vertex oppHeOppVert = null;
                if (longestEdge.opp != null)
                {
                    oppHeOppVert = longestEdge.opp.next.vert;
                }
                var newVert = longestEdge.Split();
                newVert.positionD = oppVert.positionD;
                var longestEdgeFace = longestEdge.face;
                var res             = longestEdgeFace.Cut(oppVert, newVert);

                if (res == longestEdgeFace)
                {
                    Debug.Log("vertices");
                }

                if (oppHeOppVert != null)
                {
                    var longestEdgeOppFace = longestEdge.opp.face;
                    var newFace            = longestEdgeOppFace.Cut(newVert, oppHeOppVert);
                    faces.Add(newFace);
                    faces.Add(longestEdgeOppFace); // reevaluate face
                }
                var sharedEdge = oppVert.GetSharedEdge(newVert);
                if (sharedEdge == null)
                {
                    Debug.Log("Cannot find shared edge between " + oppVert + " " + newVert);
                    continue;
                }
                var sharedEdgeFace1 = sharedEdge.face;
                var sharedEdgeFace2 = sharedEdge.opp.face; // ensured to exist (just created)
                var precond         = sharedEdge.CollapsePrecondition(true, Halfedge.CollapsePreconditionReason.NormalFlipped);
                if (precond == Halfedge.CollapsePreconditionReason.Ok)
                {
                    sharedEdge.Collapse(true);
                    Debug.Assert(sharedEdgeFace1.IsDestroyed());
                    Debug.Assert(sharedEdgeFace2.IsDestroyed());
                    count++;
                }
                else
                {
                    Debug.Log(precond);
                }
            }
        }
        return(count);
    }