コード例 #1
0
ファイル: EdgeMesh.cs プロジェクト: Blecki/CCDC
        public EdgeMesh(Mesh m)
        {
            this.Verticies = new List<Vector3>();
            this.Faces = new List<EMFace>();
            this.Edges = new List<EMEdge>();

            foreach (var v in m.verticies) this.Verticies.Add(v.Position);

            for (int i = 0; i < m.indicies.Length; i += 3)
            {
                var face = new EMFace(m.indicies[i + 0], m.indicies[i + 1], m.indicies[i + 2]);

                foreach (var edge in face.edges)
                    face.Centroid += this.Verticies[edge.Verticies[0]];
                face.Centroid /= face.edges.Count;

                this.Faces.Add(face);
                for (int e = 0; e < face.edges.Count; ++e)
                {
                    var foundEdge = FindEdge(face.edges[e].Verticies[0], face.edges[e].Verticies[1]);
                    if (foundEdge != -1)
                    {
                        face.edges[e] = this.Edges[foundEdge];

                        face.edges[e].ParentFace.SetRecipricalNeighbor(face.edges[e], face);
                    }
                    else
                        this.Edges.Add(face.edges[e]);
                }
            }
        }
コード例 #2
0
        private EMFace MergeFaces(EMFace A, EMFace B)
        {
            if (Object.ReferenceEquals(A, B))
            {
                throw new InvalidOperationException("Attempt to merge face with itself");
            }

            EMEdge sharedEdge = null;

            foreach (var e in A.edges)
            {
                if (e.Neighbors.Contains(B))
                {
                    sharedEdge = e;
                }
            }
            if (sharedEdge == null)
            {
                throw new InvalidOperationException("Attempt to merge faces with no shared edge.");
            }

            var newFace = new EMFace();

            newFace.edges = new List <EMEdge>(A.edges);
            newFace.edges.InsertRange(0, B.edges);
            newFace.edges.RemoveAll((e) => Object.ReferenceEquals(e, sharedEdge));

            if (newFace.edges.Count <= 2)
            {
                throw new InvalidOperationException("Degenerate face generated");
            }

            return(newFace);
        }
コード例 #3
0
 private EMFace OtherNeighbor(EMEdge e, EMFace f)
 {
     if (Object.ReferenceEquals(e.Neighbors[0], f))
     {
         return(e.Neighbors[1]);
     }
     else
     {
         return(e.Neighbors[0]);
     }
 }
コード例 #4
0
        private void VisitEdgePairsInSequence(EMFace face, Func <EMEdge, EMEdge, VEPISReturnCode> callback)
        {
            short?endpoint      = null;
            var   currentEdge   = face.edges[0];
            var   terminalCheck = false;

            while (true)
            {
                if (!endpoint.HasValue)
                {
                    endpoint = currentEdge.Verticies[1];
                }

                if (terminalCheck)
                {
                    if (Object.ReferenceEquals(currentEdge, face.edges[0]))
                    {
                        break;                                                     //We've looped through the entire polygon
                    }
                }
                else
                {
                    terminalCheck = true;
                }


                var   nextEdge     = FindNextEdgeInSequence(face, currentEdge, endpoint.Value);
                short nextEndpoint = -1;
                if (nextEdge.Verticies[0] == endpoint)
                {
                    nextEndpoint = nextEdge.Verticies[1];
                }
                else
                {
                    nextEndpoint = nextEdge.Verticies[0];
                }

                var callbackResult = callback(currentEdge, nextEdge);
                if (callbackResult == VEPISReturnCode.Advance)
                {
                    currentEdge = nextEdge;
                }
                else if (callbackResult == VEPISReturnCode.Abort)
                {
                    break;
                }
                else
                {
                    terminalCheck = false;
                }

                endpoint = nextEndpoint;
            }
        }
コード例 #5
0
 public static EMEdge FindSharedEdge(EMFace a, EMFace b)
 {
     foreach (var e in a.edges)
     {
         if (b.edges.Contains(e))
         {
             return(e);
         }
     }
     return(null);
 }
コード例 #6
0
ファイル: EdgeMesh.cs プロジェクト: Blecki/GemgineCore
 internal void SetRecipricalNeighbor(EMEdge edge, EMFace neighbor)
 {
     foreach (var e in edges)
     {
         if (Object.ReferenceEquals(e, edge))
         {
             e.Neighbors[1] = neighbor;
         }
     }
     //for (int i = 0; i < 3; ++i)
     //    if (Object.ReferenceEquals(Edges[i],edge)) Neighbors[i] = neighbor;
 }
コード例 #7
0
ファイル: SimplifyEdgeMesh.cs プロジェクト: Blecki/CCDC
 public List<Vector3> ExtractPerimeter(EMFace face)
 {
     var r = new List<Vector3>();
     VisitEdgePairsInSequence(face, (a, b) =>
         {
             //Record the un-shared end point of a.
             if (b.Verticies.Contains(a.Verticies[0]))
                 r.Add(Verticies[a.Verticies[1]]);
             else
                 r.Add(Verticies[a.Verticies[0]]);
             return VEPISReturnCode.Advance;
         });
     return r;
 }
コード例 #8
0
 private EMEdge FindNextEdgeInSequence(EMFace of, EMEdge after, short endpoint)
 {
     foreach (var e in of.edges)
     {
         if (Object.ReferenceEquals(e, after))
         {
             continue;
         }
         if (e.Verticies.Contains(endpoint))
         {
             return(e);
         }
     }
     throw new InvalidOperationException("Malformed edge mesh");
 }
コード例 #9
0
ファイル: RayIntersection.cs プロジェクト: Blecki/GemgineCore
        public bool IsPointOnFace(Vector3 p, EMFace face)
        {
            var accumulatedAngle = 0.0f;

            foreach (var edge in face.edges)
            {
                var v0 = Verticies[edge.Verticies[0]] - p;
                var v1 = Verticies[edge.Verticies[1]] - p;
                var angle = AngleBetweenVectors(v0, v1);
                if (angle < 0) angle *= -1;
                accumulatedAngle += angle;
            }

            return Gem.Math.Utility.NearlyEqual(accumulatedAngle, Gem.Math.Angle.PI2);
        }
コード例 #10
0
ファイル: RayIntersection.cs プロジェクト: Blecki/GemgineCore
        private Plane ConstructPlane(EMFace face)
        {
            Plane? r = null;

            //Choose the first two edges of the face that are not colinear, and create a plane from them.
            VisitEdgePairsInSequence(face, (A, B) =>
                {
                    if (EdgesAreColinear(A, B)) return VEPISReturnCode.Advance;

                    var points = ExtractPointSequence(A, B);
                    r = new Plane(Verticies[points[0]], Verticies[points[1]], Verticies[points[2]]);
                    return VEPISReturnCode.Abort;
                });

            //If we made it here, there are no non-colinear edge pairs.
            if (!r.HasValue) throw new InvalidOperationException("Attempt to construct plane from degenerate face");
            return r.Value;
        }
コード例 #11
0
ファイル: RayIntersection.cs プロジェクト: Blecki/GemgineCore
        public bool IsPointOnFace(Vector3 p, EMFace face)
        {
            var accumulatedAngle = 0.0f;

            foreach (var edge in face.edges)
            {
                var v0    = Verticies[edge.Verticies[0]] - p;
                var v1    = Verticies[edge.Verticies[1]] - p;
                var angle = AngleBetweenVectors(v0, v1);
                if (angle < 0)
                {
                    angle *= -1;
                }
                accumulatedAngle += angle;
            }

            return(Gem.Math.Utility.NearlyEqual(accumulatedAngle, Gem.Math.Angle.PI2));
        }
コード例 #12
0
        public List <Vector3> ExtractPerimeter(EMFace face)
        {
            var r = new List <Vector3>();

            VisitEdgePairsInSequence(face, (a, b) =>
            {
                //Record the un-shared end point of a.
                if (b.Verticies.Contains(a.Verticies[0]))
                {
                    r.Add(Verticies[a.Verticies[1]]);
                }
                else
                {
                    r.Add(Verticies[a.Verticies[0]]);
                }
                return(VEPISReturnCode.Advance);
            });
            return(r);
        }
コード例 #13
0
ファイル: EdgeMesh.cs プロジェクト: Blecki/GemgineCore
        public EdgeMesh(Mesh m)
        {
            this.Verticies = new List <Vector3>();
            this.Faces     = new List <EMFace>();
            this.Edges     = new List <EMEdge>();

            foreach (var v in m.verticies)
            {
                this.Verticies.Add(v.Position);
            }

            for (int i = 0; i < m.indicies.Length; i += 3)
            {
                var face = new EMFace(m.indicies[i + 0], m.indicies[i + 1], m.indicies[i + 2]);

                foreach (var edge in face.edges)
                {
                    face.Centroid += this.Verticies[edge.Verticies[0]];
                }
                face.Centroid /= face.edges.Count;

                this.Faces.Add(face);
                for (int e = 0; e < face.edges.Count; ++e)
                {
                    var foundEdge = FindEdge(face.edges[e].Verticies[0], face.edges[e].Verticies[1]);
                    if (foundEdge != -1)
                    {
                        face.edges[e] = this.Edges[foundEdge];

                        face.edges[e].ParentFace.SetRecipricalNeighbor(face.edges[e], face);
                    }
                    else
                    {
                        this.Edges.Add(face.edges[e]);
                    }
                }
            }
        }
コード例 #14
0
        private bool IsConvex(EMFace face)
        {
            var accumulatedAngle = 0.0f;

            VisitEdgePairsInSequence(face, (a, b) =>
            {
                var points = ExtractPointSequence(a, b);

                var v0 = Verticies[points[0]] - Verticies[points[1]];
                var v1 = Verticies[points[2]] - Verticies[points[1]];

                var angle         = AngleBetweenVectors(v0, v1);
                accumulatedAngle += angle;

                return(VEPISReturnCode.Advance);
            });

            if (accumulatedAngle < 0)
            {
                accumulatedAngle *= -1;
            }
            return(Gem.Math.Utility.NearlyEqual(accumulatedAngle, (face.edges.Count - 2) * Gem.Math.Angle.PI));
        }
コード例 #15
0
ファイル: RayIntersection.cs プロジェクト: Blecki/GemgineCore
        private Plane ConstructPlane(EMFace face)
        {
            Plane?r = null;

            //Choose the first two edges of the face that are not colinear, and create a plane from them.
            VisitEdgePairsInSequence(face, (A, B) =>
            {
                if (EdgesAreColinear(A, B))
                {
                    return(VEPISReturnCode.Advance);
                }

                var points = ExtractPointSequence(A, B);
                r          = new Plane(Verticies[points[0]], Verticies[points[1]], Verticies[points[2]]);
                return(VEPISReturnCode.Abort);
            });

            //If we made it here, there are no non-colinear edge pairs.
            if (!r.HasValue)
            {
                throw new InvalidOperationException("Attempt to construct plane from degenerate face");
            }
            return(r.Value);
        }
コード例 #16
0
ファイル: SimplifyEdgeMesh.cs プロジェクト: Blecki/CCDC
        private void VisitEdgePairsInSequence(EMFace face, Func<EMEdge, EMEdge, VEPISReturnCode> callback)
        {
            short? endpoint = null;
            var currentEdge = face.edges[0];
            var terminalCheck = false;
            while (true)
            {
                if (!endpoint.HasValue) endpoint = currentEdge.Verticies[1];

                if (terminalCheck)
                {
                    if (Object.ReferenceEquals(currentEdge, face.edges[0])) break; //We've looped through the entire polygon
                }
                else
                    terminalCheck = true;

                var nextEdge = FindNextEdgeInSequence(face, currentEdge, endpoint.Value);
                short nextEndpoint = -1;
                if (nextEdge.Verticies[0] == endpoint) nextEndpoint = nextEdge.Verticies[1];
                else nextEndpoint = nextEdge.Verticies[0];

                var callbackResult = callback(currentEdge, nextEdge);
                if (callbackResult == VEPISReturnCode.Advance)
                    currentEdge = nextEdge;
                else if (callbackResult == VEPISReturnCode.Abort)
                    break;
                else
                    terminalCheck = false;

                endpoint = nextEndpoint;
            }
        }
コード例 #17
0
ファイル: SimplifyEdgeMesh.cs プロジェクト: Blecki/CCDC
 public static EMEdge FindSharedEdge(EMFace a, EMFace b)
 {
     foreach (var e in a.edges)
         if (b.edges.Contains(e)) return e;
     return null;
 }
コード例 #18
0
ファイル: SimplifyEdgeMesh.cs プロジェクト: Blecki/CCDC
 private EMFace OtherNeighbor(EMEdge e, EMFace f)
 {
     if (Object.ReferenceEquals(e.Neighbors[0], f)) return e.Neighbors[1];
     else return e.Neighbors[0];
 }
コード例 #19
0
ファイル: SimplifyEdgeMesh.cs プロジェクト: Blecki/CCDC
        private EMFace MergeFaces(EMFace A, EMFace B)
        {
            if (Object.ReferenceEquals(A, B))
                throw new InvalidOperationException("Attempt to merge face with itself");

            EMEdge sharedEdge = null;
            foreach (var e in A.edges)
                if (e.Neighbors.Contains(B)) sharedEdge = e;
            if (sharedEdge == null)
                throw new InvalidOperationException("Attempt to merge faces with no shared edge.");

            var newFace = new EMFace();
            newFace.edges = new List<EMEdge>(A.edges);
            newFace.edges.InsertRange(0, B.edges);
            newFace.edges.RemoveAll((e) => Object.ReferenceEquals(e, sharedEdge));

            if (newFace.edges.Count <= 2)
                throw new InvalidOperationException("Degenerate face generated");

            return newFace;
        }
コード例 #20
0
ファイル: SimplifyEdgeMesh.cs プロジェクト: Blecki/CCDC
        private bool IsConvex(EMFace face)
        {
            var accumulatedAngle = 0.0f;
            VisitEdgePairsInSequence(face, (a, b) =>
                {
                    var points = ExtractPointSequence(a, b);

                    var v0 = Verticies[points[0]] - Verticies[points[1]];
                    var v1 = Verticies[points[2]] - Verticies[points[1]];

                    var angle = AngleBetweenVectors(v0, v1);
                    accumulatedAngle += angle;

                    return VEPISReturnCode.Advance;
                });

            if (accumulatedAngle < 0) accumulatedAngle *= -1;
            return Gem.Math.Utility.NearlyEqual(accumulatedAngle, (face.edges.Count - 2) * Gem.Math.Angle.PI);
        }
コード例 #21
0
ファイル: SimplifyEdgeMesh.cs プロジェクト: Blecki/CCDC
 private EMEdge FindNextEdgeInSequence(EMFace of, EMEdge after, short endpoint)
 {
     foreach (var e in of.edges)
     {
         if (Object.ReferenceEquals(e, after)) continue;
         if (e.Verticies.Contains(endpoint)) return e;
     }
     throw new InvalidOperationException("Malformed edge mesh");
 }
コード例 #22
0
ファイル: EdgeMesh.cs プロジェクト: Blecki/CCDC
 internal void SetRecipricalNeighbor(EMEdge edge, EMFace neighbor)
 {
     foreach (var e in edges)
         if (Object.ReferenceEquals(e, edge)) e.Neighbors[1] = neighbor;
     //for (int i = 0; i < 3; ++i)
     //    if (Object.ReferenceEquals(Edges[i],edge)) Neighbors[i] = neighbor;
 }
コード例 #23
0
ファイル: SimplifyEdgeMesh.cs プロジェクト: Blecki/CCDC
 public bool FacesAreCoplanar(EMFace A, EMFace B)
 {
     return true; //In current test case, all faces that are connected are coplanar.
 }
コード例 #24
0
        private void CalculateCentroid(EMFace face)
        {
            var perimeterPoints = ExtractPerimeter(face);

            face.Centroid = Sum(perimeterPoints) / perimeterPoints.Count;
        }
コード例 #25
0
ファイル: SimplifyEdgeMesh.cs プロジェクト: Blecki/CCDC
 private void CalculateCentroid(EMFace face)
 {
     var perimeterPoints = ExtractPerimeter(face);
     face.Centroid = Sum(perimeterPoints) / perimeterPoints.Count;
 }
コード例 #26
0
 public bool FacesAreCoplanar(EMFace A, EMFace B)
 {
     return(true); //In current test case, all faces that are connected are coplanar.
 }