Exemplo n.º 1
0
        /// <summary>
        /// Returns true if the triangle that contains the edge is facing away from the centroid of the mesh
        /// </summary>
        /// <param name="triangleEdge"></param>
        /// <returns></returns>
        public bool IsFacingOutward(XbimTriangleEdge edge)
        {
            //find the centroid of the triangle
            var p1       = _vertices[edge.StartVertexIndex].Position;
            var p2       = _vertices[edge.NextEdge.StartVertexIndex].Position;
            var p3       = _vertices[edge.NextEdge.NextEdge.StartVertexIndex].Position;
            var centroid = new XbimPoint3D((p1.X + p2.X + p3.X) / 3, (p1.Y + p2.Y + p3.Y) / 3, (p1.Z + p2.Z + p3.Z) / 3);
            var normal   = TriangleNormal(edge);
            var vecOut   = PointingOutwardFrom(centroid);
            var dot      = vecOut.DotProduct(normal);

            return(dot > 0);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns the normal of the triangle that contains the specified edge
        /// </summary>
        /// <param name="edge"></param>
        /// <returns></returns>
        public XbimVector3D TriangleNormal(XbimTriangleEdge edge)
        {
            var p1 = _vertices[edge.StartVertexIndex].Position;
            var p2 = _vertices[edge.NextEdge.StartVertexIndex].Position;
            var p3 = _vertices[edge.NextEdge.NextEdge.StartVertexIndex].Position;
            var a  = new XbimPoint3D(p1.X, p1.Y, p1.Z);
            var b  = new XbimPoint3D(p2.X, p2.Y, p2.Z);
            var c  = new XbimPoint3D(p3.X, p3.Y, p3.Z);
            var cv = XbimVector3D.CrossProduct(b - a, c - a);

            cv.Normalize();
            return(cv);
        }
Exemplo n.º 3
0
 public void Reverse()
 {
     if (!_frozen)
     {
         var p1 = StartVertexIndex;
         var p2 = NextEdge.StartVertexIndex;
         var p3 = NextEdge.NextEdge.StartVertexIndex;
         StartVertexIndex                   = p2;
         NextEdge.StartVertexIndex          = p3;
         NextEdge.NextEdge.StartVertexIndex = p1;
         var prevEdge = NextEdge.NextEdge;
         prevEdge.NextEdge = NextEdge;
         NextEdge.NextEdge = this;
         NextEdge          = prevEdge;
     }
 }
Exemplo n.º 4
0
        /// <summary>
        /// Removes an edge from the edge list
        /// </summary>
        /// <param name="edge"></param>
        private void RemoveEdge(XbimTriangleEdge edge)
        {
            var edges = _lookupList[edge.Key];

            if (edges[0] == edge)                 //if it is the first one
            {
                if (edges[1] == null)             //and there is no second one
                {
                    _lookupList.Remove(edge.Key); //remove the entire key
                }
                else
                {
                    edges[0] = edges[1]; //keep the second one
                }
            }
            if (edges[1] == edge) //if it is the second one just remove it and leave the first
            {
                edges[1] = null;
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Adds the triangle using the three ints as inidices into the vertext collection
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <param name="faceId"></param>
        public void AddTriangle(int p1, int p2, int p3, int faceId)
        {
            var e1 = new XbimTriangleEdge(p1);
            var e2 = new XbimTriangleEdge(p2);
            var e3 = new XbimTriangleEdge(p3);

            e1.NextEdge = e2;
            e2.NextEdge = e3;
            e3.NextEdge = e1;


            var  edgeList = new[] { e1, e2, e3 };
            bool faulty   = !AddEdge(e1);

            if (!faulty && !AddEdge(e2))
            {
                RemoveEdge(e1);
                faulty = true;
            }
            if (!faulty && !AddEdge(e3))
            {
                RemoveEdge(e1);
                RemoveEdge(e2);
                faulty = true;
            }
            if (faulty)
            {
                FaultyTriangles.Add(edgeList);
            }
            List <XbimTriangleEdge[]> triangleList;

            if (!_faces.TryGetValue(faceId, out triangleList))
            {
                triangleList = new List <XbimTriangleEdge[]>();
                _faces.Add(faceId, triangleList);
            }
            triangleList.Add(edgeList);
        }
Exemplo n.º 6
0
        private bool AddEdge(XbimTriangleEdge edge)
        {
            var key = edge.Key;

            if (!_lookupList.ContainsKey(key))
            {
                var arr = new XbimTriangleEdge[2];
                arr[0]           = edge;
                _lookupList[key] = arr;
            }
            else
            {
                var edges = _lookupList[key];
                if (edges[1] != null)
                {
                    return(false); //we already have a pair
                }
                edges[1] = edge;
                edges[0].AdjacentEdge = edge;
                edge.AdjacentEdge     = edges[0];
            }

            return(true);
        }
Exemplo n.º 7
0
        private bool AddEdge(XbimTriangleEdge edge)
        {
            var key = edge.Key;
            if (!_lookupList.ContainsKey(key))
            {
                var arr = new XbimTriangleEdge[2];
                arr[0] = edge;
                _lookupList[key] = arr;
            }
            else
            {
                var edges = _lookupList[key];
                if (edges[1] != null)
                    return false; //we already have a pair
                edges[1] = edge;
                edges[0].AdjacentEdge = edge;
                edge.AdjacentEdge = edges[0];
            }

            return true;
        }
Exemplo n.º 8
0
 /// <summary>
 /// Returns the normal of the triangle that contains the specified edge
 /// </summary>
 /// <param name="edge"></param>
 /// <returns></returns>
 public XbimVector3D TriangleNormal(XbimTriangleEdge edge)
 {
     var p1 = _vertices[edge.StartVertexIndex].Position;
     var p2 = _vertices[edge.NextEdge.StartVertexIndex].Position;
     var p3 = _vertices[edge.NextEdge.NextEdge.StartVertexIndex].Position;
     var a = new XbimPoint3D(p1.X,p1.Y,p1.Z);
     var b = new XbimPoint3D(p2.X,p2.Y,p2.Z);
     var c = new XbimPoint3D(p3.X,p3.Y,p3.Z);
     var cv = XbimVector3D.CrossProduct(b - a, c - a );
     cv.Normalize();
     return cv;
 }
Exemplo n.º 9
0
 /// <summary>
 /// Returns true if the triangle that contains the edge is facing away from the centroid of the mesh
 /// </summary>
 /// <param name="triangleEdge"></param>
 /// <returns></returns>
 public bool IsFacingOutward(XbimTriangleEdge edge)
 {
     //find the centroid of the triangle
     var p1 = _vertices[edge.StartVertexIndex].Position;
     var p2 = _vertices[edge.NextEdge.StartVertexIndex].Position;
     var p3 = _vertices[edge.NextEdge.NextEdge.StartVertexIndex].Position;
     var centroid = new XbimPoint3D((p1.X + p2.X + p3.X) / 3, (p1.Y + p2.Y + p3.Y) / 3, (p1.Z + p2.Z + p3.Z) / 3);
     var normal = TriangleNormal(edge);
     var vecOut = PointingOutwardFrom(centroid);
     var dot = vecOut.DotProduct(normal);
     return dot > 0;
 }
Exemplo n.º 10
0
        /// <summary>
        /// Calculates the normal for a connected triangle edge, assumes the edge is part of a complete triangle and there are 3 triangle edges
        /// </summary>
        /// <param name="edge"></param>
        public bool ComputeTriangleNormal(XbimTriangleEdge[] edges)
        {
            var p1 = _vertices[edges[0].StartVertexIndex].Position;
            var p2 = _vertices[edges[0].NextEdge.StartVertexIndex].Position;
            var p3 = _vertices[edges[0].NextEdge.NextEdge.StartVertexIndex].Position;

            var ax = p1.X; var bx = p2.X; var cx = p3.X;
            var ay = p1.Y; var by = p2.Y; var cy = p3.Y;
            var az = p1.Z; var bz = p2.Z; var cz = p3.Z;
            // calculate normal of a triangle
            var v = new Vec3(
                            (by - ay) * (cz - az) - (bz - az) * (cy - ay),
                            (bz - az) * (cx - ax) - (bx - ax) * (cz - az),
                            (bx - ax) * (cy - ay) - (by - ay) * (cx - ax)
                );
            if (Vec3.Normalize(ref v))
            {
                edges[0].Normal = v;
                edges[1].Normal = v;
                edges[2].Normal = v;
                return true;
            }
            return false;
        }
Exemplo n.º 11
0
        /// <summary>
        /// Adds the triangle using the three ints as inidices into the vertext collection
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <param name="faceId"></param>
        public void AddTriangle(int p1, int p2, int p3, int faceId)
        {
            var e1 = new XbimTriangleEdge(p1);
            var e2 = new XbimTriangleEdge(p2);
            var e3 = new XbimTriangleEdge(p3);
            e1.NextEdge = e2;
            e2.NextEdge = e3;
            e3.NextEdge = e1;

            var edgeList = new[] { e1, e2, e3 };
            bool faulty = !AddEdge(e1);
            if (!faulty && !AddEdge(e2))
            {
                RemoveEdge(e1);
                faulty = true;
            }
            if (!faulty && !AddEdge(e3))
            {
                RemoveEdge(e1);
                RemoveEdge(e2);
                faulty = true;
            }
            if (faulty)
                FaultyTriangles.Add(edgeList);
            List<XbimTriangleEdge[]> triangleList;
            if (!_faces.TryGetValue(faceId, out triangleList))
            {
                triangleList = new List<XbimTriangleEdge[]>();
                _faces.Add(faceId, triangleList);
            }
            triangleList.Add(edgeList);
        }
Exemplo n.º 12
0
 internal XbimTriangle(XbimTriangleEdge[] edges, XbimContourVertexCollection vertices)
 {
     _vertices = vertices;
     _edges = edges;
 }
 /// <summary>
 /// Returns true if the triangle that contains the edge is facing away from the centroid of the mesh
 /// </summary>
 /// <param name="triangleEdge"></param>
 /// <returns></returns>
 public bool IsFacingOutward(XbimTriangleEdge triangleEdge)
 {
     var normal = TriangleNormal(triangleEdge);
     var aVec = _vertices[triangleEdge.StartVertexIndex].Position;
     var aPoint = new XbimPoint3D(aVec.X,aVec.Y,aVec.Z);
     var vecOut = PointingOutwardFrom(aPoint);
     var dot = vecOut.DotProduct(normal);
     return dot > 0;
 }
Exemplo n.º 14
0
        public void BalanceNormals()
        {
            const double minAngle = Math.PI / 5;

            //set up the base normals
            foreach (var faceGroup in Faces)
            {
                foreach (var triangle in faceGroup.Value)
                {
                    ComputeTriangleNormal(triangle);
                }
            }


            var edgesAtVertex = _faces.Values.SelectMany(el => el).SelectMany(e => e).Where(e => e != null).GroupBy(k => k.StartVertexIndex);

            foreach (var edges in edgesAtVertex)
            {
                //create a set of faces to divide the point into a set of connected faces
                var faceSet = new List <List <XbimTriangleEdge> >();//the first face set at this point

                //find an unconnected edge if one exists
                var unconnectedEdges = edges.Where(e => e.AdjacentEdge == null);
                var freeEdges        = unconnectedEdges as IList <XbimTriangleEdge> ?? unconnectedEdges.ToList();

                if (!freeEdges.Any())
                //they are all connected to each other so find the first sharp edge or the any one if none sharp, this stops a face being split
                {
                    XbimTriangleEdge nextConnectedEdge = edges.First();
                    freeEdges = new List <XbimTriangleEdge>(1)
                    {
                        edges.First()
                    };                                                           //take the first if we don't find a sharp edge
                    //now look for any connected edges
                    var visited = new HashSet <long>();
                    do
                    {
                        visited.Add(nextConnectedEdge.EdgeId);
                        nextConnectedEdge = nextConnectedEdge.NextEdge.NextEdge.AdjacentEdge;
                        if (nextConnectedEdge != null)
                        {
                            if (visited.Contains(nextConnectedEdge.EdgeId)) //we have been here before
                            {
                                break;                                      //we are looping or at the start
                            }
                            //if the edge is sharp and the triangle is not colinear, start here
                            var nextAngle = nextConnectedEdge.Angle;
                            if (nextAngle > minAngle && nextConnectedEdge.Normal.IsValid)
                            {
                                freeEdges = new List <XbimTriangleEdge>(1)
                                {
                                    nextConnectedEdge
                                };
                                break;
                            }
                        }
                    } while (nextConnectedEdge != null);
                }

                foreach (var edge in freeEdges)
                {
                    var face = new List <XbimTriangleEdge> {
                        edge
                    };
                    faceSet.Add(face);
                    XbimTriangleEdge nextConnectedEdge = edge;
                    //now look for any connected edges
                    var visited = new HashSet <long>();
                    do
                    {
                        visited.Add(nextConnectedEdge.EdgeId);
                        var nextConnectedEdgeCandidate = nextConnectedEdge.NextEdge.NextEdge.AdjacentEdge;
                        while (nextConnectedEdgeCandidate != null && !visited.Contains(nextConnectedEdgeCandidate.EdgeId) && !nextConnectedEdgeCandidate.Normal.IsValid) //skip colinear triangles
                        {
                            //set the colinear triangle to have the same normals as the current edge
                            nextConnectedEdgeCandidate.Normal                   = nextConnectedEdge.Normal;
                            nextConnectedEdgeCandidate.NextEdge.Normal          = nextConnectedEdge.Normal;
                            nextConnectedEdgeCandidate.NextEdge.NextEdge.Normal = nextConnectedEdge.Normal;
                            visited.Add(nextConnectedEdgeCandidate.EdgeId);
                            nextConnectedEdgeCandidate = nextConnectedEdgeCandidate.NextEdge.NextEdge.AdjacentEdge;
                        }

                        nextConnectedEdge = nextConnectedEdgeCandidate;
                        if (nextConnectedEdge != null)
                        {
                            if (visited.Contains(nextConnectedEdge.EdgeId))
                            {
                                break; //we are looping or at the start
                            }
                            //if the edge is sharp start a new face
                            var angle = nextConnectedEdge.Angle;
                            if (angle > minAngle && nextConnectedEdge.Normal.IsValid)
                            {
                                face = new List <XbimTriangleEdge>();
                                faceSet.Add(face);
                            }
                            face.Add(nextConnectedEdge);
                        }
                    } while (nextConnectedEdge != null);
                    //move on to next face
                }

                //we have our smoothing groups
                foreach (var vertexEdges in faceSet.Where(f => f.Count > 1))
                {
                    var vertexNormal = Vec3.Zero;
                    foreach (var edge in vertexEdges)
                    {
                        if (edge.Normal.IsValid)
                        {
                            Vec3.AddTo(ref vertexNormal, ref edge.Normal);
                        }
                    }

                    Vec3.Normalize(ref vertexNormal);
                    foreach (var edge in vertexEdges)
                    {
                        edge.Normal = vertexNormal;
                    }
                }
            }

            var groupedFaces = new Dictionary <int, List <XbimTriangleEdge[]> >(_faces.Count);

            //now regroup faces
            _faces = _faces.Values.SelectMany(v => v).GroupBy(t => ComputeTrianglePackedNormalInt(t)).ToDictionary(k => k.Key, v => v.ToList());
        }
Exemplo n.º 15
0
 /// <summary>
 /// Computes the packed normal for the triangle, if all the normals at each vertex are the same it is returned, if any are different XbimPackedNormal.Invalid is returned. Assumes the normals have been calculated and balanced
 /// </summary>
 /// <param name="edges"></param>
 private int ComputeTrianglePackedNormalInt(XbimTriangleEdge[] edges)
 {
     var pn = edges[0].PackedNormal;
     var pn0 = pn.ToUnit16();
     var pn1 = edges[1].PackedNormal.ToUnit16();
     var pn2 = edges[2].PackedNormal.ToUnit16();
     if (pn0 == pn1 && pn1 == pn2) return pn.ToUnit16();
     return ushort.MaxValue;
 }
Exemplo n.º 16
0
 /// <summary>
 /// Removes an edge from the edge list
 /// </summary>
 /// <param name="edge"></param>
 private void RemoveEdge(XbimTriangleEdge edge)
 {
     var edges = _lookupList[edge.Key];
     if (edges[0] == edge) //if it is the first one
     {
         if (edges[1] == null) //and there is no second one
             _lookupList.Remove(edge.Key); //remove the entire key
         else
             edges[0] = edges[1]; //keep the second one
     }
     if (edges[1] == edge) //if it is the second one just remove it and leave the first
         edges[1] = null;
 }
 private bool AddEdge(XbimTriangleEdge edge)
 {
     if (_extremeEdge == null) _extremeEdge = edge;
     var key = edge.Key;
     if (!_lookupList.ContainsKey(key))
     {
         var arr = new XbimTriangleEdge[2];
         arr[0] = edge;
         _lookupList[key] = arr;
     }
     else
     {
         var edges = _lookupList[key];
         if (edges[1] != null)
             return false; //we already have a pair
         edges[1] = edge;
         edges[0].AdjacentEdge = edge;
         edge.AdjacentEdge = edges[0];
     }
     if (_vertices[edge.StartVertexIndex].Position.Z > _vertices[_extremeEdge.StartVertexIndex].Position.Z && Vec3.Colinear(_vertices[edge.StartVertexIndex].Position, _vertices[edge.NextEdge.StartVertexIndex].Position, _vertices[edge.NextEdge.StartVertexIndex].Position))
         _extremeEdge = edge;
     return true;
 }
Exemplo n.º 18
0
 public void Reverse()
 {
     if (!_frozen)
     {
         var p1 = StartVertexIndex;
         var p2 = NextEdge.StartVertexIndex;
         var p3 = NextEdge.NextEdge.StartVertexIndex;
         StartVertexIndex = p2;
         NextEdge.StartVertexIndex = p3;
         NextEdge.NextEdge.StartVertexIndex = p1;
         var prevEdge = NextEdge.NextEdge;
         prevEdge.NextEdge = NextEdge;
         NextEdge.NextEdge = this;
         NextEdge = prevEdge;
     }
 }
 /// <summary>
 /// Computes the packed normal for the triangle, if all the normals at each vertex are the same it is returned, if any are different XbimPackedNormal.Invalid is returned. Assumes the normals have been calculated and balanced
 /// </summary>
 /// <param name="edges"></param>
 private XbimPackedNormal ComputeTrianglePackedNormal(XbimTriangleEdge[] edges)
 {
     var pn = edges[0].PackedNormal;
     var pn0 = pn.ToUnit16();
     var pn1 = edges[1].PackedNormal.ToUnit16();
     var pn2 = edges[2].PackedNormal.ToUnit16();
     if (pn0 == pn1 && pn1 == pn2) return pn;
     return new XbimPackedNormal(255,255);
 }