/// <summary>
 /// Assumes the halfedges of the given graph are correctly sorted around each vertex.
 /// </summary>
 /// <typeparam name="UV"></typeparam>
 /// <typeparam name="UE"></typeparam>
 /// <param name="graph"></param>
 /// <param name="setVertex"></param>
 /// <param name="setHedge"></param>
 /// <returns></returns>
 public TM CreateFromGraph <UV, UE>(HeGraph <UV, UE> graph, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null)
     where UV : HeGraph <UV, UE> .Vertex
     where UE : HeGraph <UV, UE> .Halfedge
 {
     // TODO implement
     throw new NotImplementedException();
 }
Exemple #2
0
        /// <summary>
        /// Appends a deep copy of the given graph to this graph.
        /// Allows projection of element data to a different form.
        /// </summary>
        /// <typeparam name="UE"></typeparam>
        /// <typeparam name="UV"></typeparam>
        /// <param name="other"></param>
        /// <param name="setVertex"></param>
        /// <param name="setHedge"></param>
        public void Append <UV, UE>(HeGraph <UV, UE> other, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null)
            where UV : HeGraph <UV, UE> .Vertex
            where UE : HeGraph <UV, UE> .Halfedge
        {
            var vertsB  = other.Vertices;
            var hedgesB = other.Halfedges;

            int nvA = Vertices.Count;
            int nhA = Halfedges.Count;

            // cache in case of appending to self
            int nvB = vertsB.Count;
            int nhB = hedgesB.Count;

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

            for (int i = 0; i < nhB; i += 2)
            {
                AddEdge();
            }

            // set vertex refs
            for (int i = 0; i < nvB; i++)
            {
                var v0 = vertsB[i];
                var v1 = Vertices[i + nvA];

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

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

            // set halfedge refs
            for (int i = 0; i < nhB; i++)
            {
                var he0 = hedgesB[i];
                var he1 = Halfedges[i + nhA];

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

                if (he0.IsUnused)
                {
                    continue;
                }
                he1.Previous = Halfedges[he0.Previous.Index + nhA];
                he1.Next     = Halfedges[he0.Next.Index + nhA];
                he1.Start    = Vertices[he0.Start.Index + nvA];
            }
        }
Exemple #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="graph"></param>
        /// <param name="setVertexAttributes"></param>
        /// <param name="setHedgeAttributes"></param>
        public static void ReadFromJson <V, E, VA, EA>(string path, HeGraph <V, E> graph, Action <V, VA> setVertexAttributes = null, Action <E, EA> setHedgeAttributes = null)
            where V : HeGraph <V, E> .Vertex
            where E : HeGraph <V, E> .Halfedge
        {
            var buffer = CoreIO.DeserializeJson <HeGraphJsonBuffer <VA, EA> >(path);

            buffer.ReadTo(graph, setVertexAttributes, setHedgeAttributes);
        }
Exemple #4
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="E"></typeparam>
        public static void WriteToJson <V, E, VA, EA>(HeGraph <V, E> graph, string path, Func <V, VA> getVertexAttributes = null, Func <E, EA> getHedgeAttributes = null)
            where V : HeGraph <V, E> .Vertex
            where E : HeGraph <V, E> .Halfedge
        {
            var buffer = new HeGraphJsonBuffer <VA, EA>();

            buffer.WriteFrom(graph, getVertexAttributes, getHedgeAttributes);
            CoreIO.SerializeJson(buffer, path);
        }
Exemple #5
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="UV"></typeparam>
        /// <typeparam name="UE"></typeparam>
        /// <param name="graph"></param>
        /// <param name="setVertex"></param>
        /// <param name="setHedge"></param>
        /// <returns></returns>
        public TG CreateCopy <UV, UE>(HeGraph <UV, UE> graph, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null)
            where UV : HeGraph <UV, UE> .Vertex
            where UE : HeGraph <UV, UE> .Halfedge
        {
            var copy = Create(graph.Vertices.Capacity, graph.Halfedges.Capacity);

            copy.Append(graph, setVertex, setHedge);
            return(copy);
        }
Exemple #6
0
            /// <summary>
            /// Writes the given graph to this buffer.
            /// </summary>
            public void WriteFrom <V, E>(HeGraph <V, E> graph, Func <V, VA> getVertexAttributes = null, Func <E, EA> getHedgeAttributes = null)
                where V : HeGraph <V, E> .Vertex
                where E : HeGraph <V, E> .Halfedge
            {
                var verts  = graph.Vertices;
                var hedges = graph.Halfedges;

                _vertexRefs = new int[verts.Count];
                _hedgeRefs  = new int[hedges.Count][];

                // write vertex topology
                for (int i = 0; i < verts.Count; i++)
                {
                    var v = verts[i];
                    _vertexRefs[i] = v.First ?? -1;
                }

                // write halfedge topology
                for (int i = 0; i < hedges.Count; i++)
                {
                    var he = hedges[i];

                    _hedgeRefs[i] = new int[]
                    {
                        he.Previous ?? -1,
                        he.Next,
                        he.Start
                    };
                }

                // write vertex attributes
                if (getVertexAttributes != null)
                {
                    _vertexAttributes = new VA[verts.Count];

                    for (int i = 0; i < verts.Count; i++)
                    {
                        _vertexAttributes[i] = getVertexAttributes(verts[i]);
                    }
                }

                // write halfedge attributes
                if (getHedgeAttributes != null)
                {
                    _hedgeAttributes = new EA[hedges.Count];

                    for (int i = 0; i < hedges.Count; i++)
                    {
                        _hedgeAttributes[i] = getHedgeAttributes(hedges[i]);
                    }
                }
            }
Exemple #7
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="UV"></typeparam>
        /// <typeparam name="UE"></typeparam>
        /// <param name="graph"></param>
        /// <param name="componentIndices"></param>
        /// <param name="edgeIndices"></param>
        /// <param name="setVertex"></param>
        /// <param name="setHedge"></param>
        /// <returns></returns>
        public TG[] CreateConnectedComponents <UV, UE>(HeGraph <UV, UE> graph, out int[] componentIndices, out int[] edgeIndices, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null)
            where UV : HeGraph <UV, UE> .Vertex
            where UE : HeGraph <UV, UE> .Halfedge
        {
            int ne = graph.Edges.Count;

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

            return(CreateConnectedComponents(
                       graph,
                       Halfedge <UE> .CreateEdgeProperty(componentIndices),
                       Halfedge <UE> .CreateEdgeProperty(edgeIndices),
                       setVertex,
                       setHedge
                       ));
        }
Exemple #8
0
        /// <summary>
        /// Throws an exception if the topology of the given mesh is not valid.
        /// </summary>
        /// <typeparam name="TV"></typeparam>
        /// <typeparam name="TE"></typeparam>
        /// <typeparam name="TF"></typeparam>
        /// <param name="mesh"></param>
        internal static void CheckTopology <TV, TE>(HeGraph <TV, TE> graph)
            where TV : HeGraph <TV, TE> .Vertex
            where TE : HeGraph <TV, TE> .Halfedge
        {
            var verts  = graph.Vertices;
            var hedges = graph.Halfedges;

            // ensure halfedges are reciprocally linked
            foreach (var he in hedges)
            {
                if (he.IsUnused)
                {
                    continue;
                }
                if (he.Previous.Next != he && he.Next.Previous != he)
                {
                    Throw();
                }
                if (he.Start.IsUnused)
                {
                    Throw();
                }
            }

            // ensure consistent start vertex during circulation
            foreach (var v in verts)
            {
                foreach (var he in v.OutgoingHalfedges)
                {
                    if (he.Start != v)
                    {
                        Throw();
                    }
                }
            }

            void Throw()
            {
                throw new Exception("The topology of the given mesh is invalid");
            }
        }
Exemple #9
0
            /// <summary>
            /// Reads this buffer to the given graph.
            /// </summary>
            public void ReadTo <V, E>(HeGraph <V, E> graph, Action <V, VA> setVertexAttributes = null, Action <E, EA> setHedgeAttributes = null)
                where V : HeGraph <V, E> .Vertex
                where E : HeGraph <V, E> .Halfedge
            {
                var verts  = graph.Vertices;
                var hedges = graph.Halfedges;

                int nv  = verts.Count;
                int nhe = hedges.Count;

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

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

                // 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];

                    var start = refs[2];
                    if (start > -1)
                    {
                        he.Start = verts[start + 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]);
                    }
                }
            }
Exemple #10
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="other"></param>
 public void Append(HeGraph other)
 {
     Append(other, delegate { }, delegate { });
 }
Exemple #11
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="UV"></typeparam>
 /// <typeparam name="UE"></typeparam>
 /// <param name="graph"></param>
 /// <param name="setVertex"></param>
 /// <param name="setHedge"></param>
 /// <returns></returns>
 public TG[] CreateConnectedComponents <UV, UE>(HeGraph <UV, UE> graph, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null)
     where UV : HeGraph <UV, UE> .Vertex
     where UE : HeGraph <UV, UE> .Halfedge
 {
     return(CreateConnectedComponents(graph, out int[] compIds, out int[] edgeIds, setVertex, setHedge));
 }
Exemple #12
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="UV"></typeparam>
        /// <typeparam name="UE"></typeparam>
        /// <param name="graph"></param>
        /// <param name="componentIndex"></param>
        /// <param name="edgeIndex"></param>
        /// <param name="setVertex"></param>
        /// <param name="setHedge"></param>
        /// <returns></returns>
        public TG[] CreateConnectedComponents <UV, UE>(HeGraph <UV, UE> graph, Property <UE, int> componentIndex, Property <UE, int> edgeIndex, Action <TV, UV> setVertex = null, Action <TE, UE> setHedge = null)
            where UV : HeGraph <UV, UE> .Vertex
            where UE : HeGraph <UV, UE> .Halfedge
        {
            var vertices = graph.Vertices;
            var hedges   = graph.Halfedges;

            int ncomp = graph.GetEdgeComponentIndices(componentIndex.Set);
            var comps = new TG[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.NextAtStart;

                // 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);
            }

            return(comps);
        }