private XbimTriangulatedMesh Triangulate(IIfcTriangulatedFaceSet triangulation)
        {
            var faceId           = 0;
            var entityLabel      = triangulation.EntityLabel;
            var precision        = (float)triangulation.Model.ModelFactors.Precision;
            var faceCount        = triangulation.CoordIndex.Count();
            var triangulatedMesh = new XbimTriangulatedMesh(faceCount, precision);
            //add all the vertices in to the mesh
            var vertices = new List <int>(triangulation.Coordinates.CoordList.Count());

            foreach (var coord in triangulation.Coordinates.CoordList)
            {
                var tpl = coord.AsTriplet <IfcLengthMeasure>();
                var v   = new Vec3(tpl.A, tpl.B, tpl.C);
                var idx = triangulatedMesh.AddVertex(v);
                vertices.Add(idx);
            }
            foreach (var triangleFace in triangulation.CoordIndex)
            {
                var tpl = triangleFace.AsTriplet <IfcPositiveInteger>();
                triangulatedMesh.AddTriangle(vertices[(int)tpl.A - 1], vertices[(int)tpl.B - 1], vertices[(int)tpl.C - 1], faceId);
            }
            triangulatedMesh.UnifyFaceOrientation(entityLabel);
            return(triangulatedMesh);
        }
        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);
        }