Example #1
0
        /// <summary>
        /// Compute the orthonormal bases of the specified face
        /// </summary>
        /// <returns>Array containing the 2 Vector3d.</returns>
        /// <param name="face">Face.</param>
        public static Vector3d[] OrthonormalBases(HE_Face face)
        {
            Vector3d e1     = Vector(face.HalfEdge).Unit();
            Vector3d normal = FaceNormal(face);
            Vector3d e2     = normal.Cross(e1);

            return(new Vector3d[] { e1, e2 });
        }
Example #2
0
    // get clone
    public HE_Mesh get()
    {
        HE_Mesh result = new HE_Mesh();

        reindex();

        for (int i = 0; i < vertices.Count; i++)
        {
            result.vertices.Add((vertices [i]).getClone());
        }

        for (int i = 0; i < faces.Count; i++)
        {
            result.faces.Add(new HE_Face());
        }
        for (int i = 0; i < halfEdges.Count; i++)
        {
            result.halfEdges.Add(new HE_HalfEdge());
        }
        for (int i = 0; i < edges.Count; i++)
        {
            result.edges.Add(new HE_Edge());
        }
        //
        for (int i = 0; i < vertices.Count; i++)
        {
            HE_Vertex sv = vertices [i];
            HE_Vertex tv = result.vertices [i];
            tv.halfEdge = result.halfEdges [sv.halfEdge.id];
        }
        for (int i = 0; i < faces.Count; i++)
        {
            HE_Face sf = faces [i];
            HE_Face tf = result.faces [i];
            tf.id       = i;
            tf.halfEdge = result.halfEdges [sf.halfEdge.id];
        }
        for (int i = 0; i < edges.Count; i++)
        {
            HE_Edge se = edges [i];
            HE_Edge te = result.edges [i];
            te.halfEdge = result.halfEdges [se.halfEdge.id];
            te.id       = i;
        }
        for (int i = 0; i < halfEdges.Count; i++)
        {
            HE_HalfEdge she = halfEdges [i];
            HE_HalfEdge the = result.halfEdges [i];
            the.pair = result.halfEdges [she.pair.id];
            the.next = result.halfEdges [she.next.id];
            the.prev = result.halfEdges [she.prev.id];
            the.vert = result.vertices [she.vert.id];
            the.face = result.faces [she.face.id];
            the.edge = result.edges [she.edge.id];
            the.id   = i;
        }
        return(result);
    }
Example #3
0
        public HE_MeshPoint(Point3d point, HE_Face face)
        {
            List <HE_Vertex> adj = face.adjacentVertices();

            double[] bary = Convert.Point3dToBarycentric(point, adj[0], adj[1], adj[2]);
            U = bary[0];
            V = bary[1];
            W = bary[2];
        }
Example #4
0
    HE_Mesh getDual()
    {
        HE_Mesh result = new HE_Mesh();

        reindex();
        for (int i = 0; i < faces.Count; i++)
        {
            HE_Face     f          = faces [i];
            HE_HalfEdge he         = f.halfEdge;
            PVector     faceCenter = new PVector();
            int         n          = 0;
            do
            {
                faceCenter.add(he.vert);
                he = he.next;
                n++;
            } while(he != f.halfEdge);

            faceCenter.div(n);
            result.vertices.Add(new HE_Vertex(faceCenter.x, faceCenter.y, faceCenter.z, i));
        }
        //for(int i=0;i<vertices.Count;i++){
        //HE_Vertex v=getVertex(i);
        foreach (HE_Vertex v in vertices)
        {
            HE_HalfEdge        he            = v.halfEdge;
            HE_Face            f             = he.face;
            List <HE_HalfEdge> faceHalfEdges = new List <HE_HalfEdge> ();
            HE_Face            nf            = new HE_Face();
            result.faces.Add(nf);
            do
            {
                HE_HalfEdge hen = new HE_HalfEdge();
                faceHalfEdges.Add(hen);
                hen.face = nf;
                hen.vert = result.vertices [f.id];
                if (hen.vert.halfEdge == null)
                {
                    hen.vert.halfEdge = hen;
                }
                if (nf.halfEdge == null)
                {
                    nf.halfEdge = hen;
                }
                he = he.pair.next;
                f  = he.face;
            } while(he != v.halfEdge);

            cycleHalfEdges(faceHalfEdges, false);
            result.halfEdges.AddRange(faceHalfEdges);
        }
        result.pairHalfEdges(result.halfEdges);
        result.createEdges(result.halfEdges, result.edges);
        result.reindex();
        return(result);
    }
Example #5
0
        /// <summary>
        /// Computes the area of the specified face
        /// </summary>
        /// <returns>The face area</returns>
        /// <param name="face">Face.</param>
        public static double Area(HE_Face face)
        {
            if (face.isBoundaryLoop())
            {
                return(0.0);
            }

            Vector3d u = Vector(face.HalfEdge);
            Vector3d v = -Vector(face.HalfEdge.Prev);

            return(0.5 * u.Cross(v).Length);
        }
Example #6
0
        /// <summary>
        /// Compute the normal vector of the specified face
        /// </summary>
        /// <returns>The normal.</returns>
        /// <param name="face">Face.</param>
        public static Vector3d FaceNormal(HE_Face face)
        {
            if (face.isBoundaryLoop())
            {
                return(null);
            }

            Vector3d u = Vector(face.HalfEdge);
            Vector3d v = -Vector(face.HalfEdge.Prev);

            return(u.Cross(v).Unit());
        }
Example #7
0
    public void buildMesh(float[][] simpleVertices, int[][] simpleFaces)
    {
        /*
         * vertices = new List<HE_Vertex>();
         * faces=new List<HE_Face>();
         * halfEdges=new List<HE_HalfEdge>();
         * edges=new List<HE_Edge>();
         */
        vertices.Clear();
        faces.Clear();
        halfEdges.Clear();
        edges.Clear();

        //Add all input vertices to the mesh, the original index of the vertex is stored as an id.
        for (int i = 0; i < simpleVertices.Length; i++)
        {
            vertices.Add(new HE_Vertex(simpleVertices [i] [0], simpleVertices [i] [1], simpleVertices [i] [2], i));
        }

        //Create a loop of halfedges for each face. We assume the vertices are given in a consistent order.
        // To extend this for a non-ordered list, sort the vertices of the input vertices here.
        HE_HalfEdge he;

        for (int i = 0; i < simpleFaces.Length; i++)
        {
            List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> ();
            HE_Face            hef       = new HE_Face();
            faces.Add(hef);
            //TODO: sort face vertices here
            for (int j = 0; j < simpleFaces[i].Length; j++)
            {
                he = new HE_HalfEdge();
                faceEdges.Add(he);
                he.face = hef;
                if (hef.halfEdge == null)
                {
                    hef.halfEdge = he;
                }
                he.vert = vertices [simpleFaces [i] [j]];
                if (he.vert.halfEdge == null)
                {
                    he.vert.halfEdge = he;
                }
            }
            cycleHalfEdges(faceEdges, false);
            halfEdges.AddRange(faceEdges);
        }
        //associate each halfedge with its pair (belonging to adjacent face)
        pairHalfEdges(halfEdges);
        //associate each pair of halfedges to a physical edge
        createEdges(halfEdges, edges);
        reindex();
    }
Example #8
0
        /// <summary>
        /// Compute the centroid of the specified face
        /// </summary>
        /// <returns>The centroid.</returns>
        /// <param name="face">Face.</param>
        public static Point3d Centroid(HE_Face face)
        {
            HE_HalfEdge hE = face.HalfEdge;
            Point3d     a  = hE.Vertex;
            Point3d     b  = hE.Next.Vertex;
            Point3d     c  = hE.Prev.Vertex;

            if (face.isBoundaryLoop())
            {
                return((a + b) / 2);
            }

            return((a + b + c) / 3);
        }
Example #9
0
        /// <summary>
        /// Compute the level on a specified face.
        /// </summary>
        /// <param name="valueKey">Key of the value to be computed per vertex.</param>
        /// <param name="level">Level value to be computed.</param>
        /// <param name="face">Face to computee the level in.</param>
        /// <param name="line">Resulting level line on the face</param>
        /// <returns>True if successful, false if not.</returns>
        public static bool GetFaceLevel(string valueKey, double level, HE_Face face, out Line line)
        {
            List <HE_Vertex> adj          = face.adjacentVertices();
            List <double>    vertexValues = new List <double> {
                adj[0].UserValues[valueKey], adj[1].UserValues[valueKey], adj[2].UserValues[valueKey]
            };

            List <int> above = new List <int>();
            List <int> below = new List <int>();

            for (int i = 0; i < vertexValues.Count; i++)
            {
                if (vertexValues[i] < level)
                {
                    below.Add(i);
                }
                else
                {
                    above.Add(i);
                }
            }

            if (above.Count == 3 || below.Count == 3)
            {
                // Triangle is above or below level
                line = new Line(new Point3d(), new Point3d());
                return(false);
            }
            else
            {
                // Triangle intersects level
                List <Point3d> intersectionPoints = new List <Point3d>();

                foreach (int i in above)
                {
                    foreach (int j in below)
                    {
                        double   diff             = vertexValues[i] - vertexValues[j];
                        double   desiredDiff      = level - vertexValues[j];
                        double   unitizedDistance = desiredDiff / diff;
                        Vector3d edgeV            = adj[i] - adj[j];
                        Point3d  levelPoint       = (Point3d)adj[j] + (edgeV * unitizedDistance);
                        intersectionPoints.Add(levelPoint);
                    }
                }
                line = new Line(intersectionPoints[0], intersectionPoints[1]);
                return(true);
            }
        }
Example #10
0
        /// <summary>
        /// Compute the intersection between a mesh face perimeter and a ray tangent to the face.
        /// </summary>
        /// <param name="ray">The tangent ray.</param>
        /// <param name="Face">The mesh face.</param>
        /// <param name="result">The resulting intersection point.</param>
        /// <param name="halfEdge">The half-edge on where the intersection lies.</param>
        /// <returns></returns>
        public static ISRayFacePerimeter RayFacePerimeter(Ray ray, HE_Face Face, out Point3d result, out HE_HalfEdge halfEdge)
        {
            Vector3d faceNormal = HE_MeshGeometry.FaceNormal(Face);
            Vector3d biNormal   = Vector3d.CrossProduct(ray.Direction, faceNormal);

            Plane perpPlane = new Plane(ray.Origin, ray.Direction, faceNormal, biNormal);

            List <HE_Vertex> vertices = Face.adjacentVertices();

            Point3d temp = new Point3d();

            Line line = new Line(vertices[0], vertices[1]);

            if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point)
            {
                result = null; halfEdge = null; return(ISRayFacePerimeter.Point);
            }                                                                                                                                   // No intersection found
            if (temp != ray.Origin && temp != null)
            {
                result = temp; halfEdge = null; return(ISRayFacePerimeter.Point);
            }                                                                                                            // Intersection found

            line = new Line(vertices[1], vertices[2]);
            if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point)
            {
                result = null; halfEdge = null; return(ISRayFacePerimeter.NoIntersection);
            }                                                                                                                                            // No intersection found
            if (temp != ray.Origin && temp != null)
            {
                result = temp; halfEdge = null; return(ISRayFacePerimeter.Point);
            }                                                                                                            // Intersection found

            line = new Line(vertices[2], vertices[0]);
            if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point)
            {
                result = null; halfEdge = null; return(ISRayFacePerimeter.NoIntersection);
            }
            if (temp != ray.Origin && temp != null)
            {
                result = temp; halfEdge = null; return(ISRayFacePerimeter.Point);
            }
            else
            {
                result = null; halfEdge = null; return(ISRayFacePerimeter.Error);
            }
        }
Example #11
0
        /// <summary>
        /// Computes a geodesic on a mesh given a starting point and an initial direction.
        /// Returns true if successfull and false if something went wrong.
        /// </summary>
        public static bool StartDir(HE_MeshPoint meshPoint, Vector3d vector, HE_Mesh mesh, int maxIter, out List <Point3d> geodesic)
        {
            // Get initial face on the mesh
            HE_Face initialFace = mesh.Faces[meshPoint.FaceIndex];
            // Start iteration

            // Create variables for current iteration step
            HE_Face  thisFace      = initialFace;
            Point3d  thisPoint     = new Point3d();
            Vector3d thisDirection = vector;

            int            iter       = 0;
            List <Point3d> geodPoints = new List <Point3d>();

            do
            {
                Ray ray = new Ray(thisPoint, thisDirection);

                // Find intersection between ray and boundary
                AR_Lib.Intersect3D.RayFacePerimeter(ray, thisFace, out Point3d nextPoint, out HE_HalfEdge halfEdge);

                // Intersection method should check for correct direction using sign of dot product

                // Add point to pointlist
                geodPoints.Add(nextPoint);

                // Walk to next face
                HE_Face nextFace = halfEdge.Twin.Face;

                // Flip vector to next face
                Vector3d perpVector = Vector3d.CrossProduct(thisDirection, HE_MeshGeometry.FaceNormal(thisFace));
                Vector3d nextVector = Vector3d.CrossProduct(HE_MeshGeometry.FaceNormal(nextFace), perpVector);

                // Assign iteration variables to current
                thisPoint     = nextPoint;
                thisFace      = nextFace;
                thisDirection = nextVector;

                // Increase counter
                iter++;
            } while (iter < maxIter);

            // Assign outputs
            geodesic = geodPoints;
            return(true);
        }
Example #12
0
        /// <summary>
        /// Compute the gradient on a given mesh face given some per-vertex values
        /// </summary>
        /// <param name="valueKey">Key of the values in the vertex.UserData dictionary</param>
        /// <param name="face">Face to compute thee gradient.</param>
        /// <returns>A vector representing the gradient on that mesh face</returns>
        public static Vector3d ComputeFaceGradient(string valueKey, HE_Face face)
        {
            List <HE_Vertex> adjacentVertices = face.adjacentVertices();
            Point3d          i = adjacentVertices[0];
            Point3d          j = adjacentVertices[1];
            Point3d          k = adjacentVertices[2];

            double gi = adjacentVertices[0].UserValues[valueKey];
            double gj = adjacentVertices[1].UserValues[valueKey];
            double gk = adjacentVertices[2].UserValues[valueKey];

            Vector3d faceNormal      = face.Normal / (2 * face.Area);
            Vector3d rotatedGradient = (gi * (k - j) + gj * (i - k) + gk * (j - i)) / (2 * face.Area);
            Vector3d gradient        = rotatedGradient.Cross(faceNormal);

            return(gradient);
        }
Example #13
0
        /// <summary>
        /// Compute the circumcenter the specified face.
        /// </summary>
        /// <returns>The circumcenter.</returns>
        /// <param name="face">Face.</param>
        public static Point3d Circumcenter(HE_Face face)
        {
            HE_HalfEdge hE = face.HalfEdge;

            Point3d a = hE.Vertex;
            Point3d b = hE.Next.Vertex;
            Point3d c = hE.Prev.Vertex;

            if (face.isBoundaryLoop())
            {
                return((a + b) / 2);
            }

            Vector3d ac = c - a;
            Vector3d ab = b - a;
            Vector3d w  = ab.Cross(ac);

            Vector3d u = (w.Cross(ab)) * ac.Length2;
            Vector3d v = (ac.Cross(w)) * ab.Length2;

            Point3d x = (u + v) / (2 * w.Length2);

            return(x + a);
        }
Example #14
0
        // Takes a List containing another List per face with the vertex indexes belonging to that face
        private bool createFaces(List <List <int> > faceIndexes)
        {
            Dictionary <string, int>         edgeCount         = new Dictionary <string, int>();
            Dictionary <string, HE_HalfEdge> existingHalfEdges = new Dictionary <string, HE_HalfEdge>();
            Dictionary <HE_HalfEdge, bool>   hasTwinHalfEdge   = new Dictionary <HE_HalfEdge, bool>();

            // Create the faces, edges and half-edges, non-boundary loops and link references when possible;
            foreach (List <int> indexes in faceIndexes)
            {
                HE_Face f = new HE_Face();
                Faces.Add(f);

                List <HE_HalfEdge> tempHEdges = new List <HE_HalfEdge>(indexes.Count);
                //Create empty half-edges
                for (int i = 0; i < indexes.Count; i++)
                {
                    HE_HalfEdge h = new HE_HalfEdge();
                    tempHEdges.Add(h);
                }

                //Fill out each half edge
                for (int i = 0; i < indexes.Count; i++)
                {
                    //Edge goes from v0 to v1
                    int v0 = indexes[i];
                    int v1 = indexes[(i + 1) % indexes.Count];

                    HE_HalfEdge h = tempHEdges[i];
                    // Set previous and next
                    h.Next = tempHEdges[(i + 1) % indexes.Count];
                    h.Prev = tempHEdges[(i + indexes.Count - 1) % indexes.Count];

                    h.onBoundary = false;
                    hasTwinHalfEdge.Add(h, false);

                    // Set half-edge & vertex mutually
                    h.Vertex = Vertices[v0];
                    Vertices[v0].HalfEdge = h;

                    // Set half-edge face & vice versa
                    h.Face     = f;
                    f.HalfEdge = h;

                    // Reverse v0 and v1 if v0 > v1
                    if (v0 > v1)
                    {
                        int temp = v0;
                        v0 = v1;
                        v1 = temp;
                    }
                    string key = v0 + " " + v1;
                    if (existingHalfEdges.ContainsKey(key))
                    {
                        // If this half-edge key already exists, it is the twin of this current half-edge
                        HE_HalfEdge twin = existingHalfEdges[key];
                        h.Twin                = twin;
                        twin.Twin             = h;
                        h.Edge                = twin.Edge;
                        hasTwinHalfEdge[h]    = true;
                        hasTwinHalfEdge[twin] = true;
                        edgeCount[key]       += 1;
                    }
                    else
                    {
                        // Create an edge and set its half-edge
                        HE_Edge e = new HE_Edge();
                        Edges.Add(e);
                        h.Edge     = e;
                        e.HalfEdge = h;

                        // Record the newly created half-edge
                        existingHalfEdges.Add(key, h);
                        edgeCount.Add(key, 1);
                    }
                }

                HalfEdges.AddRange(tempHEdges);
            }

            // Create boundary edges
            for (int i = 0; i < HalfEdges.Count; i++)
            {
                HE_HalfEdge h = HalfEdges[i];
                if (!hasTwinHalfEdge[h])
                {
                    HE_Face f = new HE_Face();
                    Boundaries.Add(f);

                    List <HE_HalfEdge> boundaryCycle = new List <HE_HalfEdge>();
                    HE_HalfEdge        hE            = h;
                    do
                    {
                        HE_HalfEdge bH = new HE_HalfEdge();
                        HalfEdges.Add(bH);
                        boundaryCycle.Add(bH);

                        HE_HalfEdge nextHE = hE.Next;
                        while (hasTwinHalfEdge[nextHE])
                        {
                            nextHE = nextHE.Twin.Next;
                        }

                        bH.Vertex     = nextHE.Vertex;
                        bH.Edge       = hE.Edge;
                        bH.onBoundary = true;

                        bH.Face    = f;
                        f.HalfEdge = bH;

                        bH.Twin = hE;
                        hE.Twin = bH;

                        hE = nextHE;
                    } while (hE != h);

                    int n = boundaryCycle.Count;
                    for (int j = 0; j < n; j++)
                    {
                        boundaryCycle[j].Next                  = boundaryCycle[(j + n - 1) % n];
                        boundaryCycle[j].Prev                  = boundaryCycle[(j + 1) % n];
                        hasTwinHalfEdge[boundaryCycle[j]]      = true;
                        hasTwinHalfEdge[boundaryCycle[j].Twin] = true;
                    }
                }

                if (!h.onBoundary)
                {
                    HE_Corner corner = new HE_Corner();
                    corner.HalfEdge = h;
                    h.Corner        = corner;
                    Corners.Add(corner);
                }
            }

            // Check mesh for common errors
            if (HasIsolatedFaces() || HasIsolatedVertices() || HasNonManifoldEdges())
            {
                return(false);
            }

            // Index elements
            indexElements();

            return(true);
        }
Example #15
0
    // Split the mesh in half, retain the part on the same side as the point "center".
    // Works only on a convex mesh !!!
    public void cutMesh(Plane P, PVector center)
    {
        float centerside = P.side(center);

        if (centerside != 0)          // if center is on the plane, we can't decide which part to keep, ignore.
        {
            List <HE_Vertex>   newVertices  = new List <HE_Vertex> ();
            List <HE_Face>     newFaces     = new List <HE_Face> ();
            List <HE_HalfEdge> newHalfEdges = new List <HE_HalfEdge> ();
            List <HE_Edge>     newEdges     = new List <HE_Edge> ();

            // get all split edges
            List <SplitEdge> splitEdges = retrieveSplitEdges(P);

            //check if the plane cuts the mesh at all, at least one point should be on the other side of the plane.
            //compared to the first point
            float[] sides = new float[vertices.Count];
            //bool cut = false;// add inok
            for (int i = 0; i < vertices.Count; i++)
            {
                HE_Vertex v = vertices [i];
                sides [i] = P.side(v);
                //if(sides[0]*sides[i]<=0f) cut=true;// add inok
            }
            //loop through all faces.
            for (int i = 0; i < faces.Count; i++)
            {
                HE_Face          face             = faces [i];
                HE_HalfEdge      halfEdge         = face.halfEdge;
                List <HE_Vertex> newFaceVertices1 = new List <HE_Vertex> ();              // vertices on the correct side.
                List <HE_Vertex> newFaceVertices2 = new List <HE_Vertex> ();              // vertices on the wrong side, not used right now.

                //for each face, loop through all vertices and retain the vertices on the correct side. If the edge
                //is cut, insert the new point in the appropriate place.
                do
                {
                    if (sides [halfEdge.vert.id] * centerside >= 0f)
                    {
                        newFaceVertices1.Add(halfEdge.vert);
                    }
                    if (sides [halfEdge.vert.id] * centerside <= 0f)
                    {
                        newFaceVertices2.Add(halfEdge.vert);
                    }

                    for (int j = 0; j < splitEdges.Count; j++)                    // loop through all split edges to check for the current edge.
                    {
                        SplitEdge se = splitEdges [j];
                        if (halfEdge.edge == se.edge)
                        {
                            newFaceVertices1.Add(se.splitVertex);
                            newFaceVertices2.Add(se.splitVertex);
                            break;
                        }
                    }
                    halfEdge = halfEdge.next;
                } while(halfEdge != face.halfEdge);

                //Create a new face form the vertices we retained,ignore degenerate faces with less than 3 vertices.
                //Add all face-related information to the data-structure.
                if (newFaceVertices1.Count > 2)
                {
                    HE_Face newFace = new HE_Face();
                    newFaces.Add(newFace);
                    List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> ();
                    for (int j = 0; j < newFaceVertices1.Count; j++)
                    {
                        HE_Vertex v = newFaceVertices1 [j];
                        if (!newVertices.Contains(v))
                        {
                            newVertices.Add(v);
                        }
                        HE_HalfEdge newHalfEdge = new HE_HalfEdge();
                        faceEdges.Add(newHalfEdge);
                        newHalfEdge.vert = v;

                        v.halfEdge       = newHalfEdge;
                        newHalfEdge.face = newFace;
                        if (newFace.halfEdge == null)
                        {
                            newFace.halfEdge = newHalfEdge;
                        }
                    }
                    cycleHalfEdges(faceEdges, false);
                    newHalfEdges.AddRange(faceEdges);
                }
            }

            //Add missing information to the datastructure
            int n = newHalfEdges.Count;
            pairHalfEdges(newHalfEdges);
            createEdges(newHalfEdges, newEdges);

            //Cutting the mesh not only cuts the faces, it also creates one new planar face looping through all new cutpoints(in a convex mesh).
            //This hole in the mesh is identified by unpaired halfedges remaining after the pairibg operation.
            //This part needs to rethought to extend to concave meshes!!!
            List <HE_HalfEdge> unpairedEdges = new List <HE_HalfEdge> ();
            for (int i = 0; i < n; i++)
            {
                HE_HalfEdge he = newHalfEdges [i];
                if (he.pair == null)
                {
                    unpairedEdges.Add(he);
                }
            }
            if (unpairedEdges.Count > 0)
            {
                //Create a closed loop out of the collection of unpaired halfedges and associate a new face with this.
                //Easy to explain with a drawing, beyond my skill with words.
                HE_Face            cutFace   = new HE_Face();
                List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> ();
                HE_HalfEdge        he        = unpairedEdges [0];
                HE_HalfEdge        hen       = he;
                do
                {
                    HE_HalfEdge _hen = he.next;
                    HE_HalfEdge _hep = he.next.pair;
                    if (_hep != null)                    //add inok
                    {
                        hen = he.next.pair.next;
                        while (!unpairedEdges.Contains(hen))
                        {
                            hen = hen.pair.next;
                        }
                    }
                    else
                    {
                        hen = hen.next;
                        Debug.LogWarning("LogWarning: null");
                    }
                    HE_HalfEdge newhe = new HE_HalfEdge();
                    faceEdges.Add(newhe);
                    if (cutFace.halfEdge == null)
                    {
                        cutFace.halfEdge = newhe;
                    }
                    newhe.vert = hen.vert;
                    newhe.pair = he;
                    he.pair    = newhe;
                    HE_Edge e = new HE_Edge();
                    e.halfEdge = newhe;
                    he.edge    = e;
                    newhe.edge = e;
                    newEdges.Add(e);
                    newhe.face = cutFace;
                    he         = hen;
                } while(hen != unpairedEdges[0]);

                cycleHalfEdges(faceEdges, true);
                newHalfEdges.AddRange(faceEdges);
                newFaces.Add(cutFace);
            }

            // update the mesh
            vertices  = newVertices;
            faces     = newFaces;
            halfEdges = newHalfEdges;

            edges = newEdges;
            reindex();
        }
    }
Example #16
0
    void splitSurface(Plane P)
    {
        List <HE_Vertex>   newVertices  = new List <HE_Vertex> ();
        List <HE_Face>     newFaces     = new List <HE_Face> ();
        List <HE_HalfEdge> newHalfEdges = new List <HE_HalfEdge> ();
        List <HE_Edge>     newEdges     = new List <HE_Edge> ();

        // get all split edges
        List <SplitEdge> splitEdges = retrieveSplitEdges(P);

        //check if the plane cuts the mesh at all, at least one point should be on the other side of the plane.
        //compared to the first point
        float[] sides = new float[vertices.Count];
        //bool cut=false;
        for (int i = 0; i < vertices.Count; i++)
        {
            HE_Vertex v = vertices [i];
            sides [i] = P.side(v);
            //if(sides[0]*sides[i]<=0f) cut=true;
        }

        //loop through all faces.
        for (int i = 0; i < faces.Count; i++)
        {
            HE_Face          face             = faces [i];
            HE_HalfEdge      halfEdge         = face.halfEdge;
            List <HE_Vertex> newFaceVertices1 = new List <HE_Vertex> ();
            List <HE_Vertex> newFaceVertices2 = new List <HE_Vertex> ();
            List <HE_Vertex> currentFace      = newFaceVertices1;
            //for each face, loop through all vertices and retain the vertices on the correct side. If the edge
            //is cut, insert the new point in the appropriate place.
            do
            {
                currentFace.Add(halfEdge.vert);
                for (int j = 0; j < splitEdges.Count; j++)              // loop through all split edges to check for the current edge.
                {
                    SplitEdge se = (SplitEdge)splitEdges [j];
                    if (halfEdge.edge == se.edge)
                    {
                        newFaceVertices1.Add(se.splitVertex);
                        newFaceVertices2.Add(se.splitVertex);
                        if (currentFace == newFaceVertices1)
                        {
                            currentFace = newFaceVertices2;
                        }
                        else
                        {
                            currentFace = newFaceVertices1;
                        }
                        break;
                    }
                }
                halfEdge = halfEdge.next;
            } while(halfEdge != face.halfEdge);

            //Create a new face form the vertices we retained,ignore degenerate faces with less than 3 vertices.
            //Add all face-related information to the data-structure.

            HE_Face newFace = new HE_Face();
            newFaces.Add(newFace);
            List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> ();
            for (int j = 0; j < newFaceVertices1.Count; j++)
            {
                HE_Vertex v = newFaceVertices1 [j];
                if (!newVertices.Contains(v))
                {
                    newVertices.Add(v);
                }
                HE_HalfEdge newHalfEdge = new HE_HalfEdge();
                faceEdges.Add(newHalfEdge);
                newHalfEdge.vert = v;

                v.halfEdge       = newHalfEdge;
                newHalfEdge.face = newFace;
                if (newFace.halfEdge == null)
                {
                    newFace.halfEdge = newHalfEdge;
                }
            }
            cycleHalfEdges(faceEdges, false);
            newHalfEdges.AddRange(faceEdges);
            if (newFaceVertices2.Count > 0)
            {
                newFace = new HE_Face();
                newFaces.Add(newFace);
                faceEdges = new List <HE_HalfEdge> ();
                for (int j = 0; j < newFaceVertices2.Count; j++)
                {
                    HE_Vertex v = newFaceVertices2 [j];
                    if (!newVertices.Contains(v))
                    {
                        newVertices.Add(v);
                    }
                    HE_HalfEdge newHalfEdge = new HE_HalfEdge();
                    faceEdges.Add(newHalfEdge);
                    newHalfEdge.vert = v;

                    v.halfEdge       = newHalfEdge;
                    newHalfEdge.face = newFace;
                    if (newFace.halfEdge == null)
                    {
                        newFace.halfEdge = newHalfEdge;
                    }
                }
                cycleHalfEdges(faceEdges, false);
                newHalfEdges.AddRange(faceEdges);

                //}//test
            }

            //Add missing information to the datastructure
            pairHalfEdges(newHalfEdges);
            createEdges(newHalfEdges, newEdges);
        }

        // update the mesh
        vertices  = newVertices;
        faces     = newFaces;
        halfEdges = newHalfEdges;
        edges     = newEdges;
        reindex();
    }
Example #17
0
    // draw as a triangular mesh.
    public Triangle3D draw()
    {
        Triangle3D triangle3d = new Triangle3D();

        for (int i = 0; i < faces.Count; i++)
        {
            HE_Face     face     = faces [i];
            HE_HalfEdge halfEdge = face.halfEdge;
            HE_Vertex   midFace  = new HE_Vertex(0, 0, 0, 0);
            int         c        = 0;
            do
            {
                HE_Vertex v = halfEdge.vert;
                midFace.x += v.x;
                midFace.y += v.y;
                midFace.z += v.z;
                halfEdge   = halfEdge.next;
                c++;
            } while(halfEdge != face.halfEdge);
            midFace.x /= c;
            midFace.y /= c;
            midFace.z /= c;
            halfEdge   = face.halfEdge;

            HE_Vertex vv;
            do
            {
                HE_Vertex v0 = halfEdge.vert;
                HE_Vertex v1 = halfEdge.next.vert;

                triangle3d.vertices.Add(midFace);
                triangle3d.vertices.Add(v1);
                triangle3d.vertices.Add(v0);

                halfEdge = halfEdge.next;
            } while(halfEdge != face.halfEdge);

            //beginShape(TRIANGLE_STRIP);

            /*
             * GL.Begin(GL.TRIANGLE_STRIP);
             * HE_Vertex vv;
             * do{
             *      vv=halfEdge.vert;
             *      GL.Vertex3(vv.x,vv.y,vv.z);
             *      GL.Vertex3(midFace.x,midFace.y,midFace.z);
             *      halfEdge= halfEdge.next;
             * }
             * while(halfEdge!=face.halfEdge);
             * vv=halfEdge.vert;
             * GL.Vertex3(vv.x,vv.y,vv.z);
             * //endShape();
             * GL.End();
             */

            /*
             * HE_Vertex vv;
             * do{
             *      vv=halfEdge.vert;
             *      //GL.Vertex3(vv.x,vv.y,vv.z);
             *      //GL.Vertex3(midFace.x,midFace.y,midFace.z);
             *      triangle3d.vertices.Add(vv);
             *      triangle3d.vertices.Add(midFace);
             *
             *      halfEdge= halfEdge.next;
             * }
             * while(halfEdge!=face.halfEdge);
             * vv=halfEdge.vert;
             *
             * //GL.Vertex3(vv.x,vv.y,vv.z);
             * triangle3d.vertices.Add(vv);
             */
        }

        return(triangle3d);
    }