public void AddVertex(Vec3 v, ref ContourVertex contourVertex)
 {
     if (_vertices.Contains(v))
     {
         contourVertex = _vertices[v];
     }
     else
     {
         _vertices.Add(v, ref contourVertex);
         _minX = Math.Min(_minX, v.X);
         _minY = Math.Min(_minY, v.Y);
         _minZ = Math.Min(_minZ, v.Z);
         _maxX = Math.Max(_maxX, v.X);
         _maxY = Math.Max(_maxY, v.Y);
         _maxZ = Math.Max(_maxZ, v.Z);
     }
 }
Exemple #2
0
        public static void ComputeNewellsNormal(ContourVertex[] vertices, ref Vec3 normal)
        {
            float         x = 0, y = 0, z = 0;
            ContourVertex current;
            var           previous = new ContourVertex();
            int           count    = 0;
            int           total    = vertices.Length;

            for (var i = 0; i <= total; i++)
            {
                if (i < total)
                {
                    current = vertices[i];
                }
                else
                {
                    current = vertices[0];
                }
                if (count > 0)
                {
                    float xn  = previous.Position.X;
                    float yn  = previous.Position.Y;
                    float zn  = previous.Position.Z;
                    float xn1 = current.Position.X;
                    float yn1 = current.Position.Y;
                    float zn1 = current.Position.Z;
                    x += (yn - yn1) * (zn + zn1);
                    y += (xn + xn1) * (zn - zn1);
                    z += (xn - xn1) * (yn + yn1);
                }
                previous = current;
                count++;
            }
            normal.X = x;
            normal.Y = y;
            normal.Z = z;
            Vec3.Normalize(ref normal);
        }
 public void AddVertex(Vec3 v, ref ContourVertex contourVertex)
 {
     if (_vertices.Contains(v))
         contourVertex = _vertices[v];
     else
     {
         _vertices.Add(v, ref contourVertex);
         _minX = Math.Min(_minX, v.X);
         _minY = Math.Min(_minY, v.Y);
         _minZ = Math.Min(_minZ, v.Z);
         _maxX = Math.Max(_maxX, v.X);
         _maxY = Math.Max(_maxY, v.Y);
         _maxZ = Math.Max(_maxZ, v.Z);
     }
 }
        private XbimTriangulatedMesh TriangulateFaces(IList <IIfcFace> ifcFaces, int entityLabel, float precision)
        {
            var faceId = 0;

            var faceCount        = ifcFaces.Count;
            var triangulatedMesh = new XbimTriangulatedMesh(faceCount, precision);

            foreach (var ifcFace in ifcFaces)
            {
                //improves performance and reduces memory load
                var tess = new Tess();

                var contours = new List <ContourVertex[]>(/*Count?*/);
                foreach (var bound in ifcFace.Bounds) //build all the loops
                {
                    var polyLoop = bound.Bound as IIfcPolyLoop;

                    if (polyLoop == null)
                    {
                        continue;                   //skip empty faces
                    }
                    var polygon = polyLoop.Polygon;

                    if (polygon.Count < 3)
                    {
                        continue;                    //skip non-polygonal faces
                    }
                    var is3D = (polygon[0].Dim == 3);

                    var contour = new ContourVertex[polygon.Count];
                    if (bound.Orientation)
                    {
                        for (var j = 0; j < polygon.Count; j++)
                        {
                            var v = new Vec3(polygon[j].X, polygon[j].Y, is3D ? polygon[j].Z : 0);
                            triangulatedMesh.AddVertex(v, ref contour[j]);
                        }
                    }
                    else
                    {
                        var i = 0;
                        for (var j = polygon.Count - 1; j >= 0; j--)
                        {
                            var v = new Vec3(polygon[j].X, polygon[j].Y, is3D ? polygon[j].Z : 0);
                            triangulatedMesh.AddVertex(v, ref contour[i]);
                            i++;
                        }
                    }
                    contours.Add(contour);
                }

                if (contours.Any())
                {
                    if (contours.Count == 1 && contours[0].Length == 3) //its a triangle just grab it
                    {
                        triangulatedMesh.AddTriangle(contours[0][0].Data, contours[0][1].Data, contours[0][2].Data, faceId);
                        faceId++;
                    }
                    //else
                    //if (contours.Count == 1 && contours[0].Length == 4) //its a quad just grab it
                    //{
                    //    foreach (var v in contours[0])
                    //    {
                    //        Console.WriteLine("{0:F4} ,{1:F4}, {2:F4}", v.Position.X, v.Position.Y, v.Position.Z);

                    //    }
                    //    Console.WriteLine("");
                    //    triangulatedMesh.AddTriangle(contours[0][0].Data, contours[0][1].Data, contours[0][3].Data, faceId);
                    //    triangulatedMesh.AddTriangle(contours[0][3].Data, contours[0][1].Data, contours[0][2].Data, faceId);
                    //    faceId++;
                    //}
                    else    //it is multi-sided and may have holes
                    {
                        tess.AddContours(contours);

                        tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);
                        var faceIndices  = new List <int>(tess.ElementCount * 3);
                        var elements     = tess.Elements;
                        var contourVerts = tess.Vertices;
                        for (var j = 0; j < tess.ElementCount * 3; j++)
                        {
                            var idx = contourVerts[elements[j]].Data;
                            if (idx < 0) //WE HAVE INSERTED A POINT
                            {
                                //add it to the mesh
                                triangulatedMesh.AddVertex(contourVerts[elements[j]].Position, ref contourVerts[elements[j]]);
                            }
                            faceIndices.Add(contourVerts[elements[j]].Data);
                        }

                        if (faceIndices.Count > 0)
                        {
                            for (var j = 0; j < tess.ElementCount; j++)
                            {
                                var p1 = faceIndices[j * 3];
                                var p2 = faceIndices[j * 3 + 1];
                                var p3 = faceIndices[j * 3 + 2];
                                triangulatedMesh.AddTriangle(p1, p2, p3, faceId);
                            }
                            faceId++;
                        }
                    }
                }
            }

            triangulatedMesh.UnifyFaceOrientation(entityLabel);
            return(triangulatedMesh);
        }
        private XbimTriangulatedMesh TriangulateFaces(IEnumerable<IfcFace> ifcFaces, int entityLabel, float precision)
        {
            var faceId = 0;
            var enumerable = ifcFaces as IList<IfcFace> ?? ifcFaces.ToList();

            var faceCount = enumerable.Count;
            var triangulatedMesh = new XbimTriangulatedMesh(faceCount, precision);
            foreach (var ifcFace in enumerable)
            {
                var fc = (IfcFace)_model.InstancesLocal[ifcFace.EntityLabel];
                //improves performance and reduces memory load
                var tess = new Tess();
                var contours = new List<ContourVertex[]>(fc.Bounds.Count);
                foreach (var bound in fc.Bounds) //build all the loops
                {
                    var polyLoop = bound.Bound as IfcPolyLoop;

                    if (polyLoop == null || polyLoop.Polygon.Count < 3) continue; //skip non-polygonal faces

                    var is3D = (polyLoop.Polygon[0].Dim == 3);

                    var contour = new ContourVertex[polyLoop.Polygon.Count];
                    var i = 0;

                    foreach (var p in bound.Orientation ? polyLoop.Polygon : polyLoop.Polygon.Reverse())
                        //add all the points into unique collection
                    {
                        var v = new Vec3(p.X, p.Y, is3D ? p.Z : 0);
                        triangulatedMesh.AddVertex(v, ref contour[i]);
                        i++;
                    }
                    contours.Add(contour);
                }

                if (contours.Any())
                {
                    if (contours.Count == 1 && contours[0].Length == 3) //its a triangle just grab it
                    {
                        triangulatedMesh.AddTriangle(contours[0][0].Data, contours[0][1].Data, contours[0][2].Data, faceId);
                        faceId++;
                    }
                    //else
                    //if (contours.Count == 1 && contours[0].Length == 4) //its a quad just grab it
                    //{
                    //    foreach (var v in contours[0])
                    //    {
                    //        Console.WriteLine("{0:F4} ,{1:F4}, {2:F4}", v.Position.X, v.Position.Y, v.Position.Z);

                    //    }
                    //    Console.WriteLine("");
                    //    triangulatedMesh.AddTriangle(contours[0][0].Data, contours[0][1].Data, contours[0][3].Data, faceId);
                    //    triangulatedMesh.AddTriangle(contours[0][3].Data, contours[0][1].Data, contours[0][2].Data, faceId);
                    //    faceId++;
                    //}
                    else    //it is multi-sided and may have holes
                    {
                        tess.AddContours(contours);

                        tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);
                        var faceIndices = new List<int>(tess.ElementCount * 3);
                        var elements = tess.Elements;
                        var contourVerts = tess.Vertices;
                        for (var j = 0; j < tess.ElementCount * 3; j++)
                        {
                            var idx = contourVerts[elements[j]].Data;
                            if (idx < 0) //WE HAVE INSERTED A POINT
                            {
                                //add it to the mesh
                                triangulatedMesh.AddVertex(contourVerts[elements[j]].Position, ref contourVerts[elements[j]]);
                            }
                            faceIndices.Add(contourVerts[elements[j]].Data);
                        }

                        if (faceIndices.Count > 0)
                        {
                            for (var j = 0; j < tess.ElementCount; j++)
                            {
                                var p1 = faceIndices[j * 3];
                                var p2 = faceIndices[j * 3 + 1];
                                var p3 = faceIndices[j * 3 + 2];
                                triangulatedMesh.AddTriangle(p1, p2, p3, faceId);
                            }
                            faceId++;
                        }
                    }
                }
            }

            triangulatedMesh.UnifyFaceOrientation(entityLabel);
            return triangulatedMesh;
        }
Exemple #6
0
        private float SignedArea(ContourVertex[] vertices)
        {
            float area = 0.0f;

            for (int i = 0; i < vertices.Length; i++)
            {
                var v0 = vertices[i];
                var v1 = vertices[(i + 1) % vertices.Length];

                area += v0.Position.X * v1.Position.Y;
                area -= v0.Position.Y * v1.Position.X;
            }

            return area * 0.5f;
        }
Exemple #7
0
        public void AddContour(ContourVertex[] vertices, ContourOrientation forceOrientation)
        {
            if (_mesh == null)
            {
                _mesh = new Mesh();
            }

            bool reverse = false;
            if (forceOrientation != ContourOrientation.Original)
            {
                float area = SignedArea(vertices);
                reverse = (forceOrientation == ContourOrientation.Clockwise && area < 0.0f) || (forceOrientation == ContourOrientation.CounterClockwise && area > 0.0f);
            }

            MeshUtils.Edge e = null;
            for (int i = 0; i < vertices.Length; ++i)
            {
                if (e == null)
                {
                    e = _mesh.MakeEdge();
                    _mesh.Splice(e, e._Sym);
                }
                else
                {
                    // Create a new vertex and edge which immediately follow e
                    // in the ordering around the left face.
                    _mesh.SplitEdge(e);
                    e = e._Lnext;
                }

                int index = reverse ? vertices.Length - 1 - i : i;
                // The new vertex is now e._Org.
                e._Org._coords = vertices[index].Position;
                e._Org._data = vertices[index].Data;

                // The winding of an edge says how the winding number changes as we
                // cross from the edge's right face to its left face.  We add the
                // vertices in such an order that a CCW contour will add +1 to
                // the winding number of the region inside the contour.
                e._winding = 1;
                e._Sym._winding = -1;
            }
        }
Exemple #8
0
 public void AddContour(ContourVertex[] vertices)
 {
     AddContour(vertices, ContourOrientation.Original);
 }
Exemple #9
0
 public static void ComputeNewellsNormal(ContourVertex[] vertices, ref Vec3 normal)
 {
     float x = 0, y = 0, z = 0;
     ContourVertex current;
     var previous = new ContourVertex();
     int count = 0;
     int total = vertices.Length;
     for (var i = 0; i <= total; i++)
     {
         if (i < total)
             current = vertices[i];
         else
             current = vertices[0];
         if (count > 0)
         {
             float xn = previous.Position.X;
             float yn = previous.Position.Y;
             float zn = previous.Position.Z;
             float xn1 = current.Position.X;
             float yn1 = current.Position.Y;
             float zn1 = current.Position.Z;
             x += (yn - yn1) * (zn + zn1);
             y += (xn + xn1) * (zn - zn1);
             z += (xn - xn1) * (yn + yn1);
         }
         previous = current;
         count++;
     }
     normal.X = x;
     normal.Y = y;
     normal.Z = z;
     Vec3.Normalize(ref normal);
 }