Beispiel #1
0
        /// <summary>
        /// Returns the incircle of a triangular face.
        /// Assumes face is triangular.
        /// </summary>
        /// <returns></returns>
        public static Circle GetIncircle <V, E, F>(this HeStructure <V, E, F> .Face face, Func <V, Vector3d> getPosition)
            where V : HeStructure <V, E, F> .Vertex
            where E : HeStructure <V, E, F> .Halfedge
            where F : HeStructure <V, E, F> .Face
        {
            // impl ref
            // http://mathworld.wolfram.com/Incenter.html

            var he = face.First;

            var p0 = getPosition(he.Previous.Start);
            var p1 = getPosition(he.Start);
            var p2 = getPosition(he.Next.Start);

            var d01 = p0.DistanceTo(p1);
            var d12 = p1.DistanceTo(p2);
            var d20 = p2.DistanceTo(p0);

            var p      = (d01 + d12 + d20) * 0.5;                                 // semiperimeter
            var pInv   = 1.0 / p;                                                 // inverse semiperimeter
            var radius = Math.Sqrt(p * (p - d01) * (p - d12) * (p - d20)) * pInv; // triangle area (Heron's formula) / semiperimeter

            pInv *= 0.5;                                                          // inverse perimeter
            var center = p0 * (d12 * pInv) + p1 * (d20 * pInv) + p2 * (d01 * pInv);

            return(new Circle(new Plane(p0, p1, (Point3d)p2), center, radius));
        }
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="K"></typeparam>
 /// <param name="start"></param>
 /// <param name="getKey"></param>
 /// <returns></returns>
 public static IEnumerable <E> WalkToMax <V, E, K>(this HeStructure <V, E> .Halfedge start, Func <E, K> getKey)
     where V : HeStructure <V, E> .Vertex
     where E : HeStructure <V, E> .Halfedge
     where K : IComparable <K>
 {
     return(GraphSearch.WalkToMax(start.Self, GetConnected <V, E>, getKey));
 }
Beispiel #3
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <typeparam name="F"></typeparam>
        /// <param name="structure"></param>
        /// <param name="getPosition"></param>
        /// <param name="setResult"></param>
        /// <param name="parallel"></param>
        public static void GetFacePolylines <V, E, F>(this HeStructure <V, E, F> structure, Func <V, Vec3d> getPosition, Action <F, Polyline> setResult, bool parallel = false)
            where V : HeVertex <V, E, F>
            where E : Halfedge <V, E, F>
            where F : HeFace <V, E, F>
        {
            var faces = structure.Faces;

            if (parallel)
            {
                Parallel.ForEach(Partitioner.Create(0, faces.Count), range => Body(range.Item1, range.Item2));
            }
            else
            {
                Body(0, faces.Count);
            }

            void Body(int from, int to)
            {
                for (int i = from; i < to; i++)
                {
                    var f = faces[i];
                    if (f.IsUnused)
                    {
                        continue;
                    }
                    setResult(f, f.ToPolyline(getPosition));
                }
            }
        }
Beispiel #4
0
 /// <summary>
 /// Returns the incircle of a triangular face.
 /// Assumes face is triangular.
 /// http://mathworld.wolfram.com/Incenter.html
 /// </summary>
 /// <returns></returns>
 public static Circle GetIncircle <V, E, F>(this HeStructure <V, E, F> .Face face)
     where V : HeStructure <V, E, F> .Vertex, IPosition3d
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(GetIncircle(face, Position3d <V> .Get));
 }
Beispiel #5
0
        /// <summary>
        /// Returns the entries of the Laplacian matrix.
        /// </summary>
        public static void GetVertexLaplacian <V, E>(this HeStructure <V, E> graph, double[] result)
            where V : HeStructure <V, E> .Vertex
            where E : HeStructure <V, E> .Halfedge
        {
            var verts = graph.Vertices;
            int nv    = verts.Count;

            Array.Clear(result, 0, nv * nv);

            for (int i = 0; i < nv; i++)
            {
                var v = verts[i];
                if (v.IsUnused)
                {
                    continue;
                }

                double wsum   = 0.0;
                int    offset = i * nv;

                foreach (var he in v.OutgoingHalfedges)
                {
                    result[offset + he.End.Index] = 1.0;
                    wsum++;
                }

                result[offset + i] = -wsum;
            }
        }
Beispiel #6
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <param name="structure"></param>
        /// <param name="getPosition"></param>
        /// <param name="setResult"></param>
        /// <param name="parallel"></param>
        public static void GetEdgeLines <V, E>(this HeStructure <V, E> structure, Func <V, Vec3d> getPosition, Action <E, Line> setResult, bool parallel = false)
            where V : HeVertex <V, E>
            where E : Halfedge <V, E>
        {
            var edges = structure.Edges;

            if (parallel)
            {
                Parallel.ForEach(Partitioner.Create(0, edges.Count), range => Body(range.Item1, range.Item2));
            }
            else
            {
                Body(0, edges.Count);
            }

            void Body(int from, int to)
            {
                for (int i = from; i < to; i++)
                {
                    var he = edges[i];
                    if (he.IsUnused)
                    {
                        continue;
                    }
                    setResult(he, he.ToLine(getPosition));
                }
            }
        }
Beispiel #7
0
        /// <summary>
        /// Returns the entries of the adjacency matrix.
        /// </summary>
        /// <returns></returns>
        public static void GetFaceAdjacency <V, E, F>(this HeStructure <V, E, F> mesh, double[] result)
            where V : HeStructure <V, E, F> .Vertex
            where E : HeStructure <V, E, F> .Halfedge
            where F : HeStructure <V, E, F> .Face
        {
            var faces = mesh.Faces;
            int nf    = faces.Count;

            Array.Clear(result, 0, nf * nf);

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

                var offset = i * nf;

                foreach (var f1 in f0.AdjacentFaces)
                {
                    result[offset + f1.Index] = 1.0;
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Returns the entries of the Laplacian matrix.
        /// </summary>
        public static void GetFaceLaplacian <V, E, F>(this HeStructure <V, E, F> mesh, Func <E, double> getWeight, double[] result)
            where V : HeStructure <V, E, F> .Vertex
            where E : HeStructure <V, E, F> .Halfedge
            where F : HeStructure <V, E, F> .Face
        {
            var faces = mesh.Faces;
            int nf    = faces.Count;

            Array.Clear(result, 0, nf * nf);

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

                double wsum   = 0.0;
                var    offset = i * nf;

                foreach (var he in f.Halfedges)
                {
                    double w = getWeight(he);
                    result[offset + he.End.Index] = w;
                    wsum += w;
                }

                result[offset + i] = -wsum;
            }
        }
Beispiel #9
0
        /// <summary>
        /// Returns the entries of the incidence matrix in row-major order.
        /// </summary>
        /// <returns></returns>
        public static void GetFaceIncidence <V, E, F>(this HeStructure <V, E, F> mesh, double[] result)
            where V : HeStructure <V, E, F> .Vertex
            where E : HeStructure <V, E, F> .Halfedge
            where F : HeStructure <V, E, F> .Face
        {
            var faces = mesh.Faces;
            int nf    = faces.Count;
            int ne    = mesh.Edges.Count;

            Array.Clear(result, 0, nf * ne);

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

                int offset = i * ne;
                foreach (var he in f.Halfedges)
                {
                    result[offset + he.EdgeIndex] = 1.0;
                }
            }
        }
Beispiel #10
0
        /// <summary>
        /// Returns the entries of the incidence matrix in row-major order.
        /// </summary>
        /// <returns></returns>
        public static void GetVertexIncidence <V, E>(this HeStructure <V, E> graph, double[] result)
            where V : HeStructure <V, E> .Vertex
            where E : HeStructure <V, E> .Halfedge
        {
            var verts = graph.Vertices;
            int nv    = verts.Count;
            int ne    = graph.Edges.Count;

            Array.Clear(result, 0, nv * ne);

            for (int i = 0; i < nv; i++)
            {
                var v = verts[i];
                if (v.IsUnused)
                {
                    continue;
                }

                int offset = i * ne;
                foreach (var he in v.OutgoingHalfedges)
                {
                    result[offset + he.EdgeIndex] = 1.0;
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Returns the entries of the Laplacian matrix.
        /// </summary>
        private static void GetVertexLaplacianSymmetric <V, E>(this HeStructure <V, E> graph, Func <E, double> getWeight, Func <V, double> getMass, double[] result)
            where V : HeStructure <V, E> .Vertex
            where E : HeStructure <V, E> .Halfedge
        {
            // impl ref
            // http://reuter.mit.edu/papers/reuter-smi09.pdf

            var verts = graph.Vertices;
            int nv    = verts.Count;

            Array.Clear(result, 0, nv * nv);

            for (int i = 0; i < nv; i++)
            {
                var v0 = verts[i];
                if (v0.IsUnused)
                {
                    continue;
                }

                var    a0     = getMass(v0);
                double wsum   = 0.0;
                int    offset = i * nv;

                foreach (var he in v0.OutgoingHalfedges)
                {
                    double w = getWeight(he) / Math.Sqrt(a0 * getMass(he.End));
                    result[offset + he.End.Index] = w;
                    wsum += w;
                }

                result[offset + i] = -wsum;
            }
        }
Beispiel #12
0
        /// <summary>
        /// Returns the entries of the Laplacian matrix in row-major order.
        /// </summary>
        private static void GetVertexLaplacian <V, E>(this HeStructure <V, E> graph, Func <E, double> getWeight, Func <V, double> getMass, double[] result)
            where V : HeStructure <V, E> .Vertex
            where E : HeStructure <V, E> .Halfedge
        {
            var verts = graph.Vertices;
            int nv    = verts.Count;

            Array.Clear(result, 0, nv * nv);

            for (int i = 0; i < nv; i++)
            {
                var v = verts[i];
                if (v.IsUnused)
                {
                    continue;
                }

                var    aInv   = 1.0 / getMass(v);
                double wsum   = 0.0;
                int    offset = i * nv;

                foreach (var he in v.OutgoingHalfedges)
                {
                    double w = getWeight(he) * aInv;
                    result[offset + he.End.Index] = w;
                    wsum += w;
                }

                result[offset + i] = -wsum;
            }
        }
Beispiel #13
0
 /// <summary>
 ///
 /// </summary>
 /// <returns></returns>
 public static double GetArea <V, E, F>(this HeStructure <V, E, F> .Face face)
     where V : HeStructure <V, E, F> .Vertex, IPosition3d
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(GetArea(face, Delegates.Position3d <V> .Get));
 }
 /// <summary>
 /// Calcuated as the signed angle between adjacent face normals where convex is positive.
 /// Assumes the given face normals are unitized.
 /// </summary>>
 public static double GetDihedralAngle <V, E, F>(this HeStructure <V, E, F> .Halfedge hedge, Func <F, Vector3d> getNormal)
     where V : HeStructure <V, E, F> .Vertex, IPosition3d
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(GetDihedralAngle(hedge, Position3d <V> .Get, getNormal));
 }
Beispiel #15
0
 /// <summary>
 /// Returns the circumcenter of the face.
 /// Assumes face is triangular.
 /// http://mathworld.wolfram.com/Incenter.html
 /// </summary>
 /// <returns></returns>
 public static Vector3d GetIncenter <V, E, F>(this HeStructure <V, E, F> .Face face)
     where V : HeStructure <V, E, F> .Vertex, IPosition3d
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(GetIncenter(face, Delegates.Position3d <V> .Get));
 }
 /// <summary>
 /// Returns the area of the given halfedge as per D in https://www.cs.cmu.edu/~kmcrane/Projects/Other/TriangleAreasCheatSheet.pdf
 /// Assumes adjacent faces are triangular.
 /// </summary>
 public static double GetEdgeArea <V, E, F>(this HeStructure <V, E, F> .Halfedge hedge)
     where V : HeStructure <V, E, F> .Vertex, IPosition3d
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(GetEdgeArea(hedge, Position3d <V> .Get));
 }
Beispiel #17
0
 /// <summary>
 /// Returns the average position of vertices in the face.
 /// </summary>
 /// <returns></returns>
 public static Vector3d GetBarycenter <V, E, F>(this HeStructure <V, E, F> .Face face, Func <V, Vector3d> getPosition)
     where V : HeStructure <V, E, F> .Vertex
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(face.Vertices.Mean(getPosition));
 }
 /// <summary>
 /// Calculates the unit length area-weighted edge normal.
 /// </summary>
 public static Vector3d GetEdgeNormal <V, E, F>(this HeStructure <V, E, F> .Halfedge hedge)
     where V : HeStructure <V, E, F> .Vertex, IPosition3d
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(GetEdgeNormal(hedge, Position3d <V> .Get));
 }
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="K"></typeparam>
 /// <param name="start"></param>
 /// <param name="getKey"></param>
 /// <returns></returns>
 public static E NearestMin <V, E, K>(this HeStructure <V, E> .Halfedge start, Func <E, K> getKey)
     where V : HeStructure <V, E> .Vertex
     where E : HeStructure <V, E> .Halfedge
     where K : IComparable <K>
 {
     return(GraphSearch.NearestMin(start.Self, GetConnected <V, E>, getKey));
 }
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="K"></typeparam>
 /// <param name="start"></param>
 /// <param name="getKey"></param>
 /// <returns></returns>
 public static V NearestMax <V, E, K>(this HeStructure <V, E> .Vertex start, Func <V, K> getKey)
     where V : HeStructure <V, E> .Vertex
     where E : HeStructure <V, E> .Halfedge
     where K : IComparable <K>
 {
     return(GraphSearch.NearestMax(start.Self, v => v.ConnectedVertices, getKey));
 }
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="K"></typeparam>
 /// <param name="start"></param>
 /// <param name="getKey"></param>
 /// <returns></returns>
 public static IEnumerable <V> WalkToMin <V, E, K>(this HeStructure <V, E> .Vertex start, Func <V, K> getKey)
     where V : HeStructure <V, E> .Vertex
     where E : HeStructure <V, E> .Halfedge
     where K : IComparable <K>
 {
     return(GraphSearch.WalkToMin(start.Self, v => v.ConnectedVertices, getKey));
 }
 /// <summary>
 /// Calculates the discrete mean curvature over the area of the given vertex.
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <param name="vertex"></param>
 /// <param name="getWeight"></param>
 /// <returns></returns>
 public static double GetMeanCurvature <V, E, F>(this HeStructure <V, E, F> .Vertex vertex, Func <E, double> getWeight)
     where V : HeStructure <V, E, F> .Vertex, IPosition3d
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(GetMeanCurvature(vertex, Position3d <V> .Get, getWeight));
 }
        /// <summary>
        /// Calculates the circle packing radii for the given vertex.
        /// Assumes the mesh is a circle packing (CP) mesh as defined in http://www.geometrie.tuwien.ac.at/hoebinger/mhoebinger_files/circlepackings.pdf
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <typeparam name="F"></typeparam>
        /// <returns></returns>
        public static double GetCirclePackingRadius <V, E, F>(this HeStructure <V, E, F> .Vertex vertex, Func <V, Vector3d> getPosition)
            where V : HeStructure <V, E, F> .Vertex
            where E : HeStructure <V, E, F> .Halfedge
            where F : HeStructure <V, E, F> .Face
        {
            var p0  = getPosition(vertex.Self);
            var sum = 0.0;
            var n   = 0;

            foreach (var he0 in vertex.OutgoingHalfedges)
            {
                if (he0.Face == null)
                {
                    continue;
                }

                var he1 = he0.Next;
                var p1  = getPosition(he1.Start);
                var p2  = getPosition(he1.End);

                sum += p0.DistanceTo(p1) - p1.DistanceTo(p2) * 0.5;
                n++;
            }

            return(sum / n);
        }
 /// <summary>
 /// Calculates the angle defect at the given vertex.
 /// This is also a measure of discrete Gaussian curvature over the area of the given vertex.
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <returns></returns>
 public static double GetAngleDefect <V, E, F>(this HeStructure <V, E, F> .Vertex vertex)
     where V : HeStructure <V, E, F> .Vertex, IPosition3d
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(GetAngleDefect(vertex, Position3d <V> .Get));
 }
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <param name="vertex"></param>
 /// <param name="getPosition"></param>
 /// <param name="getWeight"></param>
 /// <returns></returns>
 public static Vector3d GetNormal <V, E, F>(this HeStructure <V, E, F> .Vertex vertex, Func <V, Vector3d> getPosition, Func <E, double> getWeight)
     where V : HeStructure <V, E, F> .Vertex
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(vertex.OutgoingHalfedges.WeightedSum(he => he.GetNormal(getPosition), getWeight).Unit);
 }
 /// <summary>
 /// Returns the unitized sum of area-weighted halfedge normals around the vertex.
 /// </summary>
 /// <returns></returns>
 public static Vector3d GetNormal <V, E, F>(this HeStructure <V, E, F> .Vertex vertex, Func <V, Vector3d> getPosition)
     where V : HeStructure <V, E, F> .Vertex
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(vertex.OutgoingHalfedges.Where(he => !he.IsHole).Sum(he => he.GetNormal(getPosition)).Unit);
 }
Beispiel #27
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <param name="face"></param>
 /// <returns></returns>
 public static Polyline ToPolyline <V, E, F>(this HeStructure <V, E, F> .Face face)
     where V : HeStructure <V, E, F> .Vertex, IPosition3d
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
 {
     return(ToPolyline(face, Position3d <V> .Get));
 }
Beispiel #28
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <typeparam name="K"></typeparam>
 /// <param name="start"></param>
 /// <param name="getKey"></param>
 /// <returns></returns>
 public static IEnumerable <F> WalkToMax <V, E, F, K>(this HeStructure <V, E, F> .Face start, Func <F, K> getKey)
     where V : HeStructure <V, E, F> .Vertex
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
     where K : IComparable <K>
 {
     return(GraphSearch.WalkToMax(start.Self, f => f.AdjacentFaces, getKey));
 }
Beispiel #29
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="V"></typeparam>
 /// <typeparam name="E"></typeparam>
 /// <typeparam name="F"></typeparam>
 /// <typeparam name="K"></typeparam>
 /// <param name="start"></param>
 /// <param name="getKey"></param>
 /// <returns></returns>
 public static F NearestMin <V, E, F, K>(this HeStructure <V, E, F> .Face start, Func <F, K> getKey)
     where V : HeStructure <V, E, F> .Vertex
     where E : HeStructure <V, E, F> .Halfedge
     where F : HeStructure <V, E, F> .Face
     where K : IComparable <K>
 {
     return(GraphSearch.NearestMin(start.Self, f => f.AdjacentFaces, getKey));
 }
Beispiel #30
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <param name="hedge"></param>
        /// <param name="getPosition"></param>
        /// <returns></returns>
        public static Line ToLine <V, E>(this HeStructure <V, E> .Halfedge hedge, Func <V, Vector3d> getPosition)
            where V : HeStructure <V, E> .Vertex
            where E : HeStructure <V, E> .Halfedge
        {
            var p0 = getPosition(hedge.Start);
            var p1 = getPosition(hedge.End);

            return(new Line(p0.X, p0.Y, p0.Z, p1.X, p1.Y, p1.Z));
        }