/// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <param name="mesh"></param>
 /// <param name="quadrangulator"></param>
 /// <param name="getPosition"></param>
 /// <param name="getNormal"></param>
 /// <param name="getTexture"></param>
 /// <param name="getColor"></param>
 /// <returns></returns>
 public static Mesh ToMesh <V, E, F>(this HeMesh <V, E, F> mesh, Func <V, Point3f> getPosition, Func <V, Vector3f> getNormal = null, Func <V, Point2f> getTexture = null, Func <V, Color> getColor = null, IFaceQuadrangulator <V, E, F> quadrangulator = null)
     where V : HeMesh <V, E, F> .Vertex
     where E : HeMesh <V, E, F> .Halfedge
     where F : HeMesh <V, E, F> .Face
 {
     return(RhinoFactory.Mesh.CreateFromHeMesh(mesh, getPosition, getNormal, getTexture, getColor, quadrangulator));
 }
Esempio n. 2
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="TV"></typeparam>
 /// <typeparam name="TE"></typeparam>
 /// <typeparam name="TF"></typeparam>
 /// <param name="mesh"></param>
 /// <param name="path"></param>
 /// <param name="getTexture"></param>
 public static void WriteToObj <TV, TE, TF>(HeMesh <TV, TE, TF> mesh, string path, Func <TV, Vector2d> getTexture = null)
     where TV : HeMesh <TV, TE, TF> .Vertex, IPosition3d, INormal3d
     where TE : HeMesh <TV, TE, TF> .Halfedge
     where TF : HeMesh <TV, TE, TF> .Face
 {
     WriteToObj(mesh, path, Position3d <TV> .Get, Normal3d <TV> .Get, getTexture);
 }
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <param name="mesh"></param>
 /// <param name="quadrangulator"></param>
 /// <returns></returns>
 public static Mesh ToMesh <V, E, F>(this HeMesh <V, E, F> mesh, IFaceQuadrangulator <V, E, F> quadrangulator = null)
     where V : HeMesh <V, E, F> .Vertex, IPosition3d
     where E : HeMesh <V, E, F> .Halfedge
     where F : HeMesh <V, E, F> .Face
 {
     return(RhinoFactory.Mesh.CreateFromHeMesh(mesh, v => (Point3f)v.Position, null, null, null, quadrangulator));
 }
Esempio n. 4
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="UV"></typeparam>
 /// <typeparam name="UE"></typeparam>
 /// <typeparam name="UF"></typeparam>
 /// <param name="mesh"></param>
 /// <param name="setVertex"></param>
 /// <param name="setHedge"></param>
 /// <param name="setFace"></param>
 /// <returns></returns>
 public TM[] CreateConnectedComponents <UV, UE, UF>(HeMesh <UV, UE, UF> mesh, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null, Action <TF, UF> setFace = null)
     where UV : HeMesh <UV, UE, UF> .Vertex
     where UE : HeMesh <UV, UE, UF> .Halfedge
     where UF : HeMesh <UV, UE, UF> .Face
 {
     return(CreateConnectedComponents(mesh, out int[] compIds, out int[] edgeIds, setVertex, setHedge, setFace));
 }
Esempio n. 5
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <param name="mesh"></param>
 /// <param name="getColor"></param>
 /// <param name="quadrangulator"></param>
 /// <returns></returns>
 public static Mesh ToPolySoup <V, E, F>(this HeMesh <V, E, F> mesh, Func <F, Color> getColor = null, IFaceQuadrangulator quadrangulator = null)
     where V : HeMesh <V, E, F> .Vertex, IPosition3d
     where E : HeMesh <V, E, F> .Halfedge
     where F : HeMesh <V, E, F> .Face
 {
     return(RhinoFactory.Mesh.CreatePolySoup(mesh, v => v.Position.As3f, getColor, quadrangulator));
 }
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <param name="mesh"></param>
 /// <param name="getPosition"></param>
 /// <param name="getColor"></param>
 /// <param name="quadrangulator"></param>
 /// <returns></returns>
 public static Mesh ToPolySoup <V, E, F>(this HeMesh <V, E, F> mesh, Func <V, Point3f> getPosition, Func <F, Color> getColor = null, IFaceQuadrangulator <V, E, F> quadrangulator = null)
     where V : HeMesh <V, E, F> .Vertex
     where E : HeMesh <V, E, F> .Halfedge
     where F : HeMesh <V, E, F> .Face
 {
     return(RhinoFactory.Mesh.CreatePolySoup(mesh, getPosition, getColor, quadrangulator));
 }
Esempio n. 7
0
            /// <summary>
            ///
            /// </summary>
            /// <typeparam name="V"></typeparam>
            /// <typeparam name="E"></typeparam>
            /// <typeparam name="F"></typeparam>
            /// <typeparam name="VA"></typeparam>
            /// <typeparam name="EA"></typeparam>
            /// <typeparam name="FA"></typeparam>
            /// <param name="path"></param>
            /// <param name="mesh"></param>
            /// <param name="setVertexAttributes"></param>
            /// <param name="setHedgeAttributes"></param>
            /// <param name="setFaceAttributes"></param>
            public static void ReadFromJson <V, E, F, VA, EA, FA>(string path, HeMesh <V, E, F> mesh, Action <V, VA> setVertexAttributes = null, Action <E, EA> setHedgeAttributes = null, Action <F, FA> setFaceAttributes = null)
                where V : HeMesh <V, E, F> .Vertex
                where E : HeMesh <V, E, F> .Halfedge
                where F : HeMesh <V, E, F> .Face
            {
                var buffer = Interop.DeserializeJson <HeMeshJsonBuffer <VA, EA, FA> >(path);

                buffer.ReadTo(mesh, setVertexAttributes, setHedgeAttributes, setFaceAttributes);
            }
Esempio n. 8
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="UV"></typeparam>
        /// <typeparam name="UE"></typeparam>
        /// <typeparam name="UF"></typeparam>
        /// <param name="mesh"></param>
        /// <param name="setVertex"></param>
        /// <param name="setHedge"></param>
        public void AppendVertexTopology <UV, UE, UF>(HeMesh <UV, UE, UF> mesh, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null)
            where UV : HeMesh <UV, UE, UF> .Vertex
            where UE : HeMesh <UV, UE, UF> .Halfedge
            where UF : HeMesh <UV, UE, UF> .Face
        {
            int nhe = Halfedges.Count;
            int nv  = Vertices.Count;

            var meshHedges = mesh.Halfedges;
            var meshVerts  = mesh.Vertices;

            // append new elements
            for (int i = 0; i < meshVerts.Count; i++)
            {
                AddVertex();
            }

            for (int i = 0; i < meshHedges.Count; i += 2)
            {
                AddEdge();
            }

            // set vertex refs
            for (int i = 0; i < meshVerts.Count; i++)
            {
                var v0 = meshVerts[i];
                var v1 = Vertices[i + nv];

                // transfer attributes
                setVertex?.Invoke(v1, v0);

                if (v0.IsUnused)
                {
                    continue;
                }
                v1.First = Halfedges[v0.First + nhe];
            }

            // set halfedge refs
            for (int i = 0; i < meshHedges.Count; i++)
            {
                var he0 = meshHedges[i];
                var he1 = Halfedges[i + nhe];

                // transfer attributes
                setHedge?.Invoke(he1, he0);

                if (he0.IsUnused)
                {
                    continue;
                }
                he1.Previous = Halfedges[he0.Previous + nhe];
                he1.Next     = Halfedges[he0.Next + nhe];
                he1.Start    = Vertices[he0.Start + nv];
            }
        }
Esempio n. 9
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="UV"></typeparam>
        /// <typeparam name="UE"></typeparam>
        /// <typeparam name="UF"></typeparam>
        /// <param name="mesh"></param>
        /// <param name="setHedge"></param>
        /// <param name="setVertex"></param>
        /// <returns></returns>
        public TG CreateFromFaceTopology <UV, UE, UF>(HeMesh <UV, UE, UF> mesh, Action <TV, UF> setVertex = null, Action <TE, UE> setHedge = null)
            where UV : HeMesh <UV, UE, UF> .Vertex
            where UE : HeMesh <UV, UE, UF> .Halfedge
            where UF : HeMesh <UV, UE, UF> .Face
        {
            var result = Create(mesh.Faces.Count, mesh.Halfedges.Count);

            result.AppendFaceTopology(mesh, setVertex, setHedge);
            return(result);
        }
Esempio n. 10
0
            /// <summary>
            ///
            /// </summary>
            /// <typeparam name="V"></typeparam>
            /// <typeparam name="E"></typeparam>
            /// <typeparam name="F"></typeparam>
            /// <typeparam name="VA"></typeparam>
            /// <typeparam name="EA"></typeparam>
            /// <typeparam name="FA"></typeparam>
            /// <param name="mesh"></param>
            /// <param name="path"></param>
            /// <param name="getVertexAttributes"></param>
            /// <param name="getHedgeAttributes"></param>
            /// <param name="getFaceAttributes"></param>
            public static void WriteToJson <V, E, F, VA, EA, FA>(HeMesh <V, E, F> mesh, string path, Func <V, VA> getVertexAttributes = null, Func <E, EA> getHedgeAttributes = null, Func <F, FA> getFaceAttributes = null)
                where V : HeMesh <V, E, F> .Vertex
                where E : HeMesh <V, E, F> .Halfedge
                where F : HeMesh <V, E, F> .Face
            {
                var buffer = new HeMeshJsonBuffer <VA, EA, FA>();

                buffer.WriteFrom(mesh, getVertexAttributes, getHedgeAttributes, getFaceAttributes);
                Interop.SerializeJson(buffer, path);
            }
Esempio n. 11
0
        /// <summary>
        /// If using external buffers to store vertex attributes, the number of vertices in the resulting mesh equals 8 times the number of edges in the given mesh.
        /// </summary>
        /// <typeparam name="UV"></typeparam>
        /// <typeparam name="UE"></typeparam>
        /// <typeparam name="UF"></typeparam>
        /// <param name="mesh"></param>
        /// <param name="getPosition"></param>
        /// <param name="getScale"></param>
        /// <param name="getNormal"></param>
        /// <param name="getCenter"></param>
        /// <param name="setPosition"></param>
        /// <returns></returns>
        public TM CreateWeave <UV, UE, UF>(HeMesh <UV, UE, UF> mesh, Func <UV, Vector3d> getPosition, Func <UE, double> getScale, Func <UE, Vector3d> getNormal, Func <UF, Vector3d> getCenter, Action <TV, Vector3d> setPosition)
            where UV : HeMesh <UV, UE, UF> .Vertex
            where UE : HeMesh <UV, UE, UF> .Halfedge
            where UF : HeMesh <UV, UE, UF> .Face
        {
            int ne     = mesh.Edges.Count;
            var result = Create(ne << 3, ne << 4, ne << 3);

            CreateWeaveGeometry(mesh, result, getPosition, getScale, getNormal, getCenter, setPosition);
            CreateWeaveTopology(mesh, result);
            return(result);
        }
Esempio n. 12
0
            /// <summary>
            /// Implementation currently ignores texture coordinates and normals.
            /// </summary>
            /// <typeparam name="TV"></typeparam>
            /// <typeparam name="TE"></typeparam>
            /// <typeparam name="TF"></typeparam>
            /// <param name="path"></param>
            /// <param name="mesh"></param>
            /// <param name="setPosition"></param>
            public static void ReadFromObj <TV, TE, TF>(string path, HeMesh <TV, TE, TF> mesh, Action <TV, Vector3d> setPosition)
                where TV : HeMesh <TV, TE, TF> .Vertex
                where TE : HeMesh <TV, TE, TF> .Halfedge
                where TF : HeMesh <TV, TE, TF> .Face
            {
                var verts = mesh.Vertices;
                var faces = mesh.Faces;
                var face  = new List <int>();

                using (var reader = new StreamReader(path))
                {
                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        // skip empty lines and comments
                        if (line.Length == 0 || line[0] == '#')
                        {
                            continue;
                        }

                        // check the first character
                        var segments = line.Split(ObjUtil.Separators, StringSplitOptions.RemoveEmptyEntries);
                        switch (segments[0])
                        {
                        case "v":
                        {
                            // parse vertex
                            double x = double.Parse(segments[1]);
                            double y = double.Parse(segments[2]);
                            double z = double.Parse(segments[3]);

                            var v = mesh.AddVertex();
                            setPosition(v, new Vector3d(x, y, z));
                            break;
                        }

                        case "f":
                        {
                            // parse face
                            for (int i = 1; i < segments.Length; i++)
                            {
                                var ids = segments[i].Split(ObjUtil.FaceSeparators);
                                face.Add(int.Parse(ids[0]) - 1);
                            }

                            mesh.AddFace(face);
                            face.Clear();
                            break;
                        }
                        }
                    }
                }
            }
Esempio n. 13
0
        /// <summary>
        ///
        /// </summary>
        private void CreateWeaveGeometry <UV, UE, UF>(HeMesh <UV, UE, UF> mesh, TM newMesh, Func <UV, Vector3d> getPosition, Func <UE, double> getScale, Func <UE, Vector3d> getNormal, Func <UF, Vector3d> getCenter, Action <TV, Vector3d> setPosition)
            where UV : HeMesh <UV, UE, UF> .Vertex
            where UE : HeMesh <UV, UE, UF> .Halfedge
            where UF : HeMesh <UV, UE, UF> .Face
        {
            var edges = mesh.Edges;
            int ne    = edges.Count;

            // bulk add new vertices
            newMesh.AddVertices(ne << 3);
            var newVerts = newMesh.Vertices;

            // add vertices (8 per halfedge pair in m0)
            for (int i = 0; i < ne; i++)
            {
                var he0 = edges[i];
                var he1 = he0.Twin;

                var f0 = he0.Face;
                var f1 = he1.Face;

                // scale points to mid point of edge
                Vector3d p0 = getPosition(he0.Start);
                Vector3d p1 = getPosition(he1.Start);

                Vector3d p = (p0 + p1) * 0.5;
                var      t = getScale(he0);

                p0 = Vector3d.Lerp(p, p0, t);
                p1 = Vector3d.Lerp(p, p1, t);
                Vector3d p2 = (f0 == null) ? new Vector3d() : Vector3d.Lerp(p, getCenter(f0), t);
                Vector3d p3 = (f1 == null) ? new Vector3d() : Vector3d.Lerp(p, getCenter(f1), t);

                // set vertex positions
                Vector3d d = he0.IsBoundary ? Vector3d.Zero : getNormal(he0);
                int      j = i << 3;

                setPosition(newVerts[j], p0 - d);
                setPosition(newVerts[j + 1], p2 - d);
                setPosition(newVerts[j + 2], p0 + d);
                setPosition(newVerts[j + 3], p2 + d);

                setPosition(newVerts[j + 4], p1 - d);
                setPosition(newVerts[j + 5], p3 - d);
                setPosition(newVerts[j + 6], p1 + d);
                setPosition(newVerts[j + 7], p3 + d);
            }
        }
Esempio n. 14
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="UV"></typeparam>
        /// <typeparam name="UE"></typeparam>
        /// <typeparam name="UF"></typeparam>
        /// <param name="mesh"></param>
        /// <param name="componentIndices"></param>
        /// <param name="edgeIndices"></param>
        /// <param name="setVertex"></param>
        /// <param name="setHedge"></param>
        /// <param name="setFace"></param>
        /// <returns></returns>
        public TM[] CreateConnectedComponents <UV, UE, UF>(HeMesh <UV, UE, UF> mesh, out int[] componentIndices, out int[] edgeIndices, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null, Action <TF, UF> setFace = null)
            where UV : HeMesh <UV, UE, UF> .Vertex
            where UE : HeMesh <UV, UE, UF> .Halfedge
            where UF : HeMesh <UV, UE, UF> .Face
        {
            int ne = mesh.Edges.Count;

            componentIndices = new int[ne];
            edgeIndices      = new int[ne];

            return(CreateConnectedComponents(
                       mesh,
                       HeMesh <UV, UE, UF> .Edge.CreateProperty(componentIndices),
                       HeMesh <UV, UE, UF> .Edge.CreateProperty(edgeIndices),
                       setVertex,
                       setHedge,
                       setFace
                       ));
        }
Esempio n. 15
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="UV"></typeparam>
        /// <typeparam name="UE"></typeparam>
        /// <typeparam name="UF"></typeparam>
        /// <param name="mesh"></param>
        /// <param name="setHedge"></param>
        /// <param name="setVertex"></param>
        public void AppendFaceTopology <UV, UE, UF>(HeMesh <UV, UE, UF> mesh, Action <TV, UF> setVertex = null, Action <TE, UE> setHedge = null)
            where UV : HeMesh <UV, UE, UF> .Vertex
            where UE : HeMesh <UV, UE, UF> .Halfedge
            where UF : HeMesh <UV, UE, UF> .Face
        {
            int nhe = Halfedges.Count;
            int nv  = Vertices.Count;

            var meshHedges = mesh.Halfedges;
            var meshFaces  = mesh.Faces;

            // append new elements
            for (int i = 0; i < meshFaces.Count; i++)
            {
                AddVertex();
            }

            for (int i = 0; i < meshHedges.Count; i += 2)
            {
                AddEdge();
            }

            // set vertex refs
            for (int i = 0; i < meshFaces.Count; i++)
            {
                var fB = meshFaces[i];
                var vA = Vertices[i + nv];

                // transfer attributes
                setVertex?.Invoke(vA, fB);

                if (fB.IsUnused)
                {
                    continue;
                }
                var heB = fB.First;

                // find first interior halfedge in the face
                while (heB.Twin.Face == null)
                {
                    heB = heB.Next;
                    if (heB == fB.First)
                    {
                        goto EndFor;                  // dual vertex has no valid halfedges
                    }
                }

                vA.First = Halfedges[heB + nhe];
                EndFor :;
            }

            // set halfedge refs
            for (int i = 0; i < meshHedges.Count; i++)
            {
                var heB0 = meshHedges[i];
                var heA0 = Halfedges[i + nhe];

                // transfer attributes
                setHedge?.Invoke(heA0, heB0);

                if (heB0.IsUnused || heB0.IsBoundary)
                {
                    continue;
                }
                var heB1 = heB0;

                // find next interior halfedge in the face
                do
                {
                    heB1 = heB1.Next;
                }while (heB1.Twin.Face == null && heB1 != heB0);

                heA0.Start = Vertices[heB0.Face + nv];
                heA0.Twin.MakeConsecutive(Halfedges[heB1 + nhe]);
                //heA0.MakeConsecutive(Halfedges[heB1 + nhe]); // TODO check this
            }
        }
Esempio n. 16
0
                /// <summary>
                /// Reads this buffer to the given mesh.
                /// </summary>
                public void ReadTo <V, E, F>(HeMesh <V, E, F> mesh, Action <V, VA> setVertexAttributes = null, Action <E, EA> setHedgeAttributes = null, Action <F, FA> setFaceAttributes = null)
                    where V : HeMesh <V, E, F> .Vertex
                    where E : HeMesh <V, E, F> .Halfedge
                    where F : HeMesh <V, E, F> .Face
                {
                    var verts = mesh.Vertices;
                    int nv    = verts.Count;

                    var hedges = mesh.Halfedges;
                    int nhe    = hedges.Count;

                    var faces = mesh.Faces;
                    int nf    = faces.Count;

                    // add new vertices
                    for (int i = 0; i < _vertexRefs.Length; i++)
                    {
                        mesh.AddVertex();
                    }

                    // add new halfedges
                    for (int i = 0; i < _hedgeRefs.Length; i += 2)
                    {
                        mesh.AddEdge();
                    }

                    // add new faces
                    for (int i = 0; i < _faceRefs.Length; i++)
                    {
                        mesh.AddFace();
                    }

                    // link up vertices
                    for (int i = 0; i < _vertexRefs.Length; i++)
                    {
                        var v = verts[i + nv];

                        var first = _vertexRefs[i];
                        if (first != -1)
                        {
                            v.First = hedges[first + nhe];
                        }
                    }

                    // link up halfedges
                    for (int i = 0; i < _hedgeRefs.Length; i++)
                    {
                        var he   = hedges[i + nhe];
                        var refs = _hedgeRefs[i];

                        var prev = refs[0];
                        if (prev != -1)
                        {
                            he.Previous = hedges[prev + nhe];
                        }

                        he.Next  = hedges[refs[1] + nhe];
                        he.Start = verts[refs[2] + nv];

                        var face = refs[3];
                        if (face != -1)
                        {
                            he.Face = faces[face + nf];
                        }
                    }

                    // link up faces
                    for (int i = 0; i < _faceRefs.Length; i++)
                    {
                        var f = faces[i + nf];

                        var first = _faceRefs[i];
                        if (first != -1)
                        {
                            f.First = hedges[first + nhe];
                        }
                    }

                    // TODO validate topology?

                    // set vertex attributes
                    if (setVertexAttributes != null)
                    {
                        for (int i = 0; i < _vertexAttributes.Length; i++)
                        {
                            setVertexAttributes(verts[i + nv], _vertexAttributes[i]);
                        }
                    }

                    // set vertex attributes
                    if (setHedgeAttributes != null)
                    {
                        for (int i = 0; i < _hedgeAttributes.Length; i++)
                        {
                            setHedgeAttributes(hedges[i + nhe], _hedgeAttributes[i]);
                        }
                    }

                    // set vertex attributes
                    if (setFaceAttributes != null)
                    {
                        for (int i = 0; i < _faceAttributes.Length; i++)
                        {
                            setFaceAttributes(faces[i + nf], _faceAttributes[i]);
                        }
                    }
                }
Esempio n. 17
0
        /// <summary>
        /// Action delegates specify how attributes of parent elements are mapped to attributes of component elements.
        /// </summary>
        /// <typeparam name="UV"></typeparam>
        /// <typeparam name="UE"></typeparam>
        /// <typeparam name="UF"></typeparam>
        /// <param name="mesh"></param>
        /// <param name="componentIndex"></param>
        /// <param name="edgeIndex"></param>
        /// <param name="setVertex"></param>
        /// <param name="setHedge"></param>
        /// <param name="setFace"></param>
        /// <returns></returns>
        public TM[] CreateConnectedComponents <UV, UE, UF>(HeMesh <UV, UE, UF> mesh, Property <UE, int> componentIndex, Property <UE, int> edgeIndex, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null, Action <TF, UF> setFace = null)
            where UV : HeMesh <UV, UE, UF> .Vertex
            where UE : HeMesh <UV, UE, UF> .Halfedge
            where UF : HeMesh <UV, UE, UF> .Face
        {
            var vertices = mesh.Vertices;
            var hedges   = mesh.Halfedges;
            var faces    = mesh.Faces;

            int ncomp = mesh.GetEdgeComponentIndices(componentIndex.Set);
            var comps = new TM[ncomp];

            // initialize components
            for (int i = 0; i < comps.Length; i++)
            {
                comps[i] = Create();
            }

            // create component halfedges
            for (int i = 0; i < hedges.Count; i += 2)
            {
                var heA = hedges[i];
                if (heA.IsUnused)
                {
                    continue;
                }

                var comp = comps[componentIndex.Get(heA)];
                var heB  = comp.AddEdge();
                edgeIndex.Set(heA, heB.Index >> 1);
            }

            // set component halfedge->halfedge refs
            for (int i = 0; i < hedges.Count; i++)
            {
                var heA0 = hedges[i];
                if (heA0.IsUnused)
                {
                    continue;
                }

                // the component to which heA0 was copied
                var compHedges = comps[componentIndex.Get(heA0)].Halfedges;
                var heA1       = heA0.Next;

                // set refs
                var heB0 = compHedges[(edgeIndex.Get(heA0) << 1) + (i & 1)];
                var heB1 = compHedges[(edgeIndex.Get(heA1) << 1) + (heA1.Index & 1)];
                heB0.MakeConsecutive(heB1);

                // transfer attributes
                setHedge?.Invoke(heB0, heA0);
            }

            // create component vertices
            for (int i = 0; i < vertices.Count; i++)
            {
                var vA = vertices[i];
                if (vA.IsUnused)
                {
                    continue;
                }

                var heA  = vA.First;
                var comp = comps[componentIndex.Get(heA)];
                var heB  = comp.Halfedges[(edgeIndex.Get(heA) << 1) + (heA.Index & 1)];

                // set vertex refs
                var vB = comp.AddVertex();
                vB.First = heB;

                foreach (var he in heB.CirculateStart)
                {
                    he.Start = vB;
                }

                // transfer attributes
                setVertex?.Invoke(vB, vA);
            }

            // create component faces
            for (int i = 0; i < faces.Count; i++)
            {
                var fA = faces[i];
                if (fA.IsUnused)
                {
                    continue;
                }

                var heA  = fA.First;
                var comp = comps[componentIndex.Get(heA)];
                var heB  = comp.Halfedges[(edgeIndex.Get(heA) << 1) + (heA.Index & 1)];

                // set face refs
                var fB = comp.AddFace();
                fB.First = heB;

                foreach (var he in heB.Circulate)
                {
                    he.Face = fB;
                }

                // transfer attributes
                setFace?.Invoke(fB, fA);
            }

            return(comps);
        }
Esempio n. 18
0
            /// <summary>
            ///
            /// </summary>
            /// <typeparam name="TV"></typeparam>
            /// <typeparam name="TE"></typeparam>
            /// <typeparam name="TF"></typeparam>
            /// <param name="mesh"></param>
            /// <param name="path"></param>
            /// <param name="getPosition"></param>
            /// <param name="getNormal"></param>
            /// <param name="getTexture"></param>
            public static void WriteToObj <TV, TE, TF>(HeMesh <TV, TE, TF> mesh, string path, Func <TV, Vector3d> getPosition, Func <TV, Vector3d> getNormal = null, Func <TV, Vector2d> getTexture = null)
                where TV : HeMesh <TV, TE, TF> .Vertex
                where TE : HeMesh <TV, TE, TF> .Halfedge
                where TF : HeMesh <TV, TE, TF> .Face
            {
                var verts       = mesh.Vertices;
                var faces       = mesh.Faces;
                int formatIndex = 0;

                using (var writer = new StreamWriter(path, false))
                {
                    writer.WriteLine(ObjUtil.Header);
                    writer.WriteLine();

                    // write vertex positions
                    for (int i = 0; i < verts.Count; i++)
                    {
                        var v = getPosition(verts[i]);
                        writer.WriteLine("v {0} {1} {2}", v.X, v.Y, v.Z);
                    }

                    // write vertex normals
                    if (getNormal != null)
                    {
                        for (int i = 0; i < verts.Count; i++)
                        {
                            var vn = getNormal(verts[i]);
                            writer.WriteLine("vn {0} {1} {2}", vn.X, vn.Y, vn.Z);
                        }

                        formatIndex |= 2;
                    }

                    // write vertex texCoords
                    if (getTexture != null)
                    {
                        for (int i = 0; i < verts.Count; i++)
                        {
                            var vt = getTexture(verts[i]);
                            writer.WriteLine("vt {0} {1}", vt.X, vt.Y);
                        }

                        formatIndex |= 1;
                    }

                    // write faces
                    string format = ObjUtil.FaceFormats[formatIndex];

                    for (int i = 0; i < faces.Count; i++)
                    {
                        var f = faces[i];
                        if (f.IsUnused)
                        {
                            continue;
                        }

                        writer.Write("f");
                        foreach (var v in f.Vertices)
                        {
                            writer.Write(format, v.Index + 1);
                        }

                        writer.WriteLine();
                    }
                }
            }