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; }
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); }