コード例 #1
0
    //associate each pair of halfedges to a physical edge.
    void createEdges(List <HE_HalfEdge> halfEdges, List <HE_Edge> target)
    {
        int n = halfEdges.Count;

        for (int i = 0; i < n; i++)
        {
            HE_HalfEdge he = halfEdges [i];
            for (int j = 0; j < n; j++)
            {
                if (i != j)
                {
                    HE_HalfEdge he2 = halfEdges [j];
                    if (he.pair == he2)
                    {
                        HE_Edge e = new HE_Edge();
                        e.halfEdge = he;
                        target.Add(e);
                        he.edge  = e;
                        he2.edge = e;
                        break;
                    }
                }
            }
        }
    }
コード例 #2
0
        /// <summary>
        /// Calculates the midpoint of the specifiec edge.
        /// </summary>
        /// <returns>The point.</returns>
        /// <param name="edge">Edge.</param>
        public static Point3d MidPoint(HE_Edge edge)
        {
            HE_HalfEdge halfEdge = edge.HalfEdge;
            Point3d     a        = halfEdge.Vertex;
            Point3d     b        = halfEdge.Twin.Vertex;

            return((a + b) / 2);
        }
コード例 #3
0
    void OnPostRender()
    {
        PVector[] sites        = voronoiTest.points;
        HE_Mesh[] voronoiCells = voronoiTest.voronoiCells;

        CreateGLMaterial();
        glMaterial.SetPass(0);

        GL.PushMatrix();

        Matrix4x4 mtx = voronoiTest.transform.localToWorldMatrix;

        //draw sites/////////////////////////////
        float size = 0.1f;

        GL.Begin(GL.QUADS);

        GL.Color(Color.white);
        for (int i = 0; i < sites.Length; i++)
        {
            PVector pt = sites[i];
            //Vector3 pos = pt.pos;
            Vector3 pos = mtx.MultiplyPoint3x4(pt.pos);
            GL.Vertex(pos + new Vector3(-size, -size, 0));
            GL.Vertex(pos + new Vector3(size, -size, 0));
            GL.Vertex(pos + new Vector3(size, size, 0));
            GL.Vertex(pos + new Vector3(-size, size, 0));
        }
        GL.End();

        //draw voronoi mesh//////////////////////////
        GL.Begin(GL.LINES);
        Color color = Color.white;

        for (int i = 0; i < voronoiCells.Length; i++)
        {
            int edgeNum = voronoiCells[i].edges.Count;

            for (int j = 0; j < edgeNum; j++)
            {
                HE_Edge e = voronoiCells[i].edges[j];
                //Color color = Color.Lerp(Color.red, Color.blue, (float)j / (float)edgeNum);
                //Debug.DrawLine(e.halfEdge.vert.pos, e.halfEdge.pair.vert.pos, color);

                GL.Color(color);
                Vector3 pos0 = mtx.MultiplyPoint3x4(e.halfEdge.vert.pos);
                Vector3 pos1 = mtx.MultiplyPoint3x4(e.halfEdge.pair.vert.pos);
                GL.Vertex(pos0);
                GL.Vertex(pos1);
            }
        }
        GL.End();

        //boxMat.SetPass(0);
        //voronoiTest.drawVoronoiBox();

        GL.PopMatrix();
    }
コード例 #4
0
ファイル: DrawGL2.cs プロジェクト: inoook/u_HE_Mesh
    void OnPostRender()
    {
        List <HE_Mesh> meshes  = voronoiTest.meshes;
        List <PVector> centers = voronoiTest.centers;

        CreateGLMaterial();
        glMaterial.SetPass(0);

        GL.PushMatrix();

        Matrix4x4 mtx = voronoiTest.transform.localToWorldMatrix;

        //draw //////////////////////////
        GL.Begin(GL.LINES);
        for (int i = 0; i < meshes.Count; i++)
        {
            PVector center = (PVector)centers [i];
            HE_Mesh mesh   = (HE_Mesh)meshes [i];

            Color color = Color.Lerp(Color.red, Color.blue, (float)i / (float)meshes.Count);

            //mesh.drawEdges();
            int edgeNum = mesh.edges.Count;
            for (int j = 0; j < edgeNum; j++)
            {
                HE_Edge e = mesh.edges [j];

                GL.Color(color);
                Vector3 pos0 = mtx.MultiplyPoint3x4(e.halfEdge.vert.pos + center.pos * 0.2f);
                Vector3 pos1 = mtx.MultiplyPoint3x4(e.halfEdge.pair.vert.pos + center.pos * 0.2f);
                //Debug.DrawLine (p0 + center.pos * 0.2f, p1 + center.pos * 0.2f, Color.red);
                GL.Vertex(pos0);
                GL.Vertex(pos1);
            }
        }

        /*
         * for(int i=0; i < voronoiCells.Length; i++)
         * {
         * int edgeNum = voronoiCells[i].edges.Count;
         *
         * for(int j = 0; j < edgeNum; j++){
         * HE_Edge e = voronoiCells[i].edges[j];
         *              Color color = Color.Lerp(Color.red, Color.blue, (float)j / (float)edgeNum);
         *              //Debug.DrawLine(e.halfEdge.vert.pos, e.halfEdge.pair.vert.pos, color);
         *
         *              GL.Color(color);
         *              Vector3 pos0 = mtx.MultiplyPoint3x4(e.halfEdge.vert.pos);
         *              Vector3 pos1 = mtx.MultiplyPoint3x4(e.halfEdge.pair.vert.pos);
         *              GL.Vertex(pos0);
         *              GL.Vertex(pos1);
         * }
         * }
         */
        GL.End();

        GL.PopMatrix();
    }
コード例 #5
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);
    }
コード例 #6
0
    //Paul Bourke, http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/
    PVector planeEdgeIntersection(HE_Edge e, Plane P)
    {
        PVector p0    = e.halfEdge.vert;
        PVector p1    = e.halfEdge.pair.vert;
        float   denom = P.A * (p0.x - p1.x) + P.B * (p0.y - p1.y) + P.C * (p0.z - p1.z);

        if ((denom < HE_Mesh.DELTA) && (denom > -HE_Mesh.DELTA))
        {
            return(null);
        }
        float u = (P.A * p0.x + P.B * p0.y + P.C * p0.z + P.D) / denom;

        if ((u < 0.0f) || (u > 1.0f))
        {
            return(null);
        }
        return(new PVector(p0.x + u * (p1.x - p0.x), p0.y + u * (p1.y - p0.y), p0.z + u * (p1.z - p0.z)));
    }
コード例 #7
0
    //FLAWED
    public void roundEdges(float d)
    {
        if (d <= 0)
        {
            return;
        }

        List <Plane> cutPlanes = new List <Plane> ();
        PVector      center    = new PVector();

        for (int i = 0; i < vertices.Count; i++)
        {
            HE_Vertex v = vertices [i];
            center.add(v);
        }
        center.div(vertices.Count);

        for (int i = 0; i < edges.Count; i++)
        {
            HE_Edge   e  = edges [i];
            HE_Vertex v1 = e.halfEdge.vert;
            HE_Vertex v2 = e.halfEdge.pair.vert;
            HE_Vertex v  = new HE_Vertex(0.5f * (v1.x + v2.x), 0.5f * (v1.y + v2.y), 0.5f * (v1.z + v2.z), 0);

            PVector n = PVector.sub(v, center);
            //float distanceToVertex=n.mag();
            //if(distanceToVertex>d){
            float distanceToVertex = n.magSq();
            if (distanceToVertex > d * d)
            {
                float   ratio  = (distanceToVertex - d) / distanceToVertex;
                PVector origin = PVector.mult(n, ratio);
                origin.add(center);
                cutPlanes.Add(new Plane(origin, n));
            }
        }
        for (int i = 0; i < cutPlanes.Count; i++)
        {
            Plane P = cutPlanes [i];
            cutMesh(P, center);
        }
    }
コード例 #8
0
    // check all edges for intersection wit a plan
    List <SplitEdge> retrieveSplitEdges(Plane P)
    {
        List <SplitEdge> splitEdges = new List <SplitEdge> ();

        for (int i = 0; i < edges.Count; i++)
        {
            HE_Edge edge = edges [i];

            /*
             * PVector intersection = planeEdgeIntersection(edge,P);
             * if(intersection != null){
             *      splitEdges.Add(new SplitEdge(edge,intersection));
             * }
             */
            PVector intersection;
            bool    b = planeEdgeIntersection(out intersection, edge, P);
            if (b)
            {
                splitEdges.Add(new SplitEdge(edge, intersection));
            }
        }
        return(splitEdges);
    }
コード例 #9
0
ファイル: HE_Mesh.cs プロジェクト: PeterZs/AR_Lib
        // 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);
        }
コード例 #10
0
 /// <summary>
 /// Calculates the length of the specified edge.
 /// </summary>
 /// <returns>The length.</returns>
 /// <param name="edge">Edge.</param>
 public static double Length(HE_Edge edge) => Vector(edge.HalfEdge).Length;
コード例 #11
0
 public SplitEdge(HE_Edge e, PVector p)
 {
     edge        = e;
     splitVertex = new HE_Vertex(p.x, p.y, p.z, 0);
 }
コード例 #12
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();
        }
    }