public IXbimGeometryObjectSet CreateSurfaceModel(IIfcTriangulatedFaceSet shell, ILogger logger) { using (new Tracer(LogHelper.CurrentFunctionName(), this._logger, shell)) { return(_engine.CreateSurfaceModel(shell, logger)); } }
public IXbimSolid CreateSolid(IIfcTriangulatedFaceSet shell, ILogger logger) { using (new Tracer(LogHelper.CurrentFunctionName(), this._logger, shell)) { return(_engine.CreateSolid(shell, logger)); } }
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); }
public XbimShapeGeometry Mesh(IIfcTriangulatedFaceSet triangulation) { if (_geometryType == XbimGeometryType.PolyhedronBinary) { return(MeshPolyhedronBinary(triangulation)); } if (_geometryType == XbimGeometryType.Polyhedron) { return(MeshPolyhedronText(triangulation)); } throw new Exception("Illegal Geometry type, " + _geometryType); }
/// <summary> /// returns the manual texture map /// </summary> /// <returns></returns> public IEnumerable <Point> GetTextureMap(IEnumerable <Point3D> vertices, IEnumerable <Vector3D> normals, IEnumerable <int> triangles) { IIfcTriangulatedFaceSet faceSet = _ifcTextMap.MappedTo as IIfcTriangulatedFaceSet; Point[] result = new Point[_numberOfVertices]; Parallel.For(0, _ifcTextMap.TexCoordIndex.Count, (triangleIdx) => { var texCoordTriangle = _ifcTextMap.TexCoordIndex[triangleIdx]; for (int verticeIdx = 0; verticeIdx < texCoordTriangle.Count; verticeIdx++) { int texCoordIdx = (int)texCoordTriangle[verticeIdx] - 1; //ifc indexing is one based int verticeRefIdx = (int)faceSet.CoordIndex[triangleIdx][verticeIdx] - 1; //ifc indexing is one based result[verticeRefIdx] = new Point(_ifcTextMap.TexCoords.TexCoordsList[texCoordIdx][0], _ifcTextMap.TexCoords.TexCoordsList[texCoordIdx][1]); } }); return(result); }
private XbimShapeGeometry MeshPolyhedronBinary(IIfcTriangulatedFaceSet triangulation) { XbimShapeGeometry shapeGeometry = new XbimShapeGeometry(); shapeGeometry.Format = XbimGeometryType.PolyhedronBinary; using (var ms = new MemoryStream(0x4000)) using (var binaryWriter = new BinaryWriter(ms)) { // Prepare the header uint verticesCount = (uint)triangulation.Coordinates.CoordList.Count(); uint triangleCount = (uint)triangulation.CoordIndex.Count(); uint facesCount = 1;//at the moment just write one face for all triangles, may change to support styed faces in future shapeGeometry.BoundingBox = XbimRect3D.Empty; //Write out the header binaryWriter.Write((byte)1); //stream format version // ReSharper disable once RedundantCast //now write out the faces if (triangulation.Normals.Any()) //we have normals so obey them { List <IEnumerable <IfcPositiveInteger> > normalIndex = new List <IEnumerable <IfcPositiveInteger> >(); bool hasPnIndex = triangulation.PnIndex.Any(); if (hasPnIndex) { if (triangulation.PnIndex is List <IItemSet <IfcPositiveInteger> > ) //the list of triplets has not been flattened { foreach (var item in triangulation.PnIndex as List <IItemSet <IfcPositiveInteger> > ) { normalIndex.Add(item); } } else { for (int i = 0; i < triangulation.PnIndex.Count; i += 3) { var item = new List <IfcPositiveInteger>() { triangulation.PnIndex[i], triangulation.PnIndex[i + 1], triangulation.PnIndex[i + 2] }; normalIndex.Add(item); } } } else { foreach (var item in triangulation.CoordIndex) { normalIndex.Add(item); } } binaryWriter.Write(verticesCount); //number of vertices binaryWriter.Write(triangleCount); //number of triangles XbimRect3D bb = XbimRect3D.Empty; // use first point as a local origin for large coordinates. It doesn't matter if // we use min, max or centroid for this. var origin = triangulation.Coordinates?.CoordList.FirstOrDefault()?.AsTriplet() ?? new XbimTriplet <IfcLengthMeasure>(); var isLarge = IsLarge(origin.A) || IsLarge(origin.B) || IsLarge(origin.C); if (isLarge) { shapeGeometry.LocalShapeDisplacement = new XbimVector3D(origin.A, origin.B, origin.C); } var points = isLarge ? triangulation.Coordinates.CoordList.Select(c => c.AsTriplet()).Select(t => new XbimTriplet <IfcLengthMeasure> { A = t.A - origin.A, B = t.B - origin.B, C = t.C - origin.C }) : triangulation.Coordinates.CoordList.Select(c => c.AsTriplet()); foreach (var pt in points) { binaryWriter.Write((float)pt.A); binaryWriter.Write((float)pt.B); binaryWriter.Write((float)pt.C); var rect = new XbimRect3D(pt.A, pt.B, pt.C, 0, 0, 0); bb.Union(rect); } binaryWriter.Write(facesCount); shapeGeometry.BoundingBox = bb; Int32 numTrianglesInFace = triangulation.CoordIndex.Count(); binaryWriter.Write(-numTrianglesInFace); //not a planar face so make negative var packedNormals = new List <XbimPackedNormal>(triangulation.Normals.Count()); foreach (var normal in triangulation.Normals) { var tpl = normal.AsTriplet <IfcParameterValue>(); packedNormals.Add(new XbimPackedNormal(tpl.A, tpl.B, tpl.C)); } int triangleIndex = 0; foreach (var triangle in triangulation.CoordIndex) { var triangleTpl = triangle.AsTriplet(); var normalsIndexTpl = normalIndex[triangleIndex].AsTriplet(); WriteIndex(binaryWriter, (uint)triangleTpl.A - 1, (uint)verticesCount); packedNormals[(int)normalsIndexTpl.A - 1].Write(binaryWriter); WriteIndex(binaryWriter, (uint)triangleTpl.B - 1, (uint)verticesCount); packedNormals[(int)normalsIndexTpl.B - 1].Write(binaryWriter); WriteIndex(binaryWriter, (uint)triangleTpl.C - 1, (uint)verticesCount); packedNormals[(int)normalsIndexTpl.C - 1].Write(binaryWriter); triangleIndex++; } } else //we need to calculate normals to get a better surface fit { var triangulatedMesh = Triangulate(triangulation); shapeGeometry.BoundingBox = triangulatedMesh.BoundingBox; verticesCount = triangulatedMesh.VertexCount; triangleCount = triangulatedMesh.TriangleCount; binaryWriter.Write(verticesCount); //number of vertices binaryWriter.Write(triangleCount); //number of triangles // use minimum bbox as a local origin var origin = triangulatedMesh.BoundingBox.Min; var isLarge = IsLarge(origin.X) || IsLarge(origin.Y) || IsLarge(origin.Z); var vertices = isLarge ? triangulatedMesh.Vertices.Select(v => new Vec3(v.X - origin.X, v.Y - origin.Y, v.Z - origin.Z)) : triangulatedMesh.Vertices; foreach (var vert in vertices) { binaryWriter.Write((float)vert.X); binaryWriter.Write((float)vert.Y); binaryWriter.Write((float)vert.Z); } if (isLarge) { var bb = triangulatedMesh.BoundingBox; shapeGeometry.BoundingBox = new XbimRect3D(bb.X - origin.X, bb.Y = origin.Y, bb.Z - origin.Z, bb.SizeX, bb.SizeY, bb.SizeZ); shapeGeometry.LocalShapeDisplacement = new XbimVector3D(origin.X, origin.Y, origin.Z); } facesCount = (uint)triangulatedMesh.Faces.Count; binaryWriter.Write((UInt32)facesCount); foreach (var faceGroup in triangulatedMesh.Faces) { var numTrianglesInFace = faceGroup.Value.Count; //we need to fix this var planar = (ushort.MaxValue != faceGroup.Key); //we have a mesh of faces that all have the same normals at their vertices if (!planar) { numTrianglesInFace *= -1; //set flag to say multiple normals } // ReSharper disable once RedundantCast binaryWriter.Write((Int32)numTrianglesInFace); bool first = true; foreach (var triangle in faceGroup.Value) { if (planar && first) { triangle[0].PackedNormal.Write(binaryWriter); first = false; } WriteIndex(binaryWriter, (uint)triangle[0].StartVertexIndex, verticesCount); if (!planar) { triangle[0].PackedNormal.Write(binaryWriter); } WriteIndex(binaryWriter, (uint)triangle[0].NextEdge.StartVertexIndex, verticesCount); if (!planar) { triangle[0].NextEdge.PackedNormal.Write(binaryWriter); } WriteIndex(binaryWriter, (uint)triangle[0].NextEdge.NextEdge.StartVertexIndex, verticesCount); if (!planar) { triangle[0].NextEdge.NextEdge.PackedNormal.Write(binaryWriter); } } } } binaryWriter.Flush(); ((IXbimShapeGeometryData)shapeGeometry).ShapeData = ms.ToArray(); } return(shapeGeometry); }
private XbimShapeGeometry MeshPolyhedronText(IIfcTriangulatedFaceSet triangulation) { throw new NotImplementedException(); }
private XbimShapeGeometry MeshPolyhedronBinary(IIfcTriangulatedFaceSet triangulation) { XbimShapeGeometry shapeGeometry = new XbimShapeGeometry(); shapeGeometry.Format = XbimGeometryType.PolyhedronBinary; using (var ms = new MemoryStream(0x4000)) using (var binaryWriter = new BinaryWriter(ms)) { // Prepare the header uint verticesCount = (uint)triangulation.Coordinates.CoordList.Count(); uint triangleCount = (uint)triangulation.CoordIndex.Count(); uint facesCount = 1;//at the moment just write one face for all triangles, may change to support styed faces in future shapeGeometry.BoundingBox = XbimRect3D.Empty; //Write out the header binaryWriter.Write((byte)1); //stream format version // ReSharper disable once RedundantCast //now write out the faces if (triangulation.Normals.Any()) //we have normals so obey them { List <IEnumerable <IfcPositiveInteger> > normalIndex = new List <IEnumerable <IfcPositiveInteger> >(); bool hasPnIndex = triangulation.PnIndex.Any(); if (hasPnIndex) { if (triangulation.PnIndex is List <IItemSet <IfcPositiveInteger> > ) //the list of triplets has not been flattened { foreach (var item in triangulation.PnIndex as List <IItemSet <IfcPositiveInteger> > ) { normalIndex.Add(item); } } else { for (int i = 0; i < triangulation.PnIndex.Count; i += 3) { var item = new List <IfcPositiveInteger>() { triangulation.PnIndex[i], triangulation.PnIndex[i + 1], triangulation.PnIndex[i + 2] }; normalIndex.Add(item); } } } else { foreach (var item in triangulation.CoordIndex) { normalIndex.Add(item); } } binaryWriter.Write(verticesCount); //number of vertices binaryWriter.Write(triangleCount); //number of triangles XbimRect3D bb = XbimRect3D.Empty; foreach (var coordList in triangulation.Coordinates.CoordList) { var pt = coordList.AsTriplet(); binaryWriter.Write((float)pt.A); binaryWriter.Write((float)pt.B); binaryWriter.Write((float)pt.C); var rect = new XbimRect3D(pt.A, pt.B, pt.C, 0, 0, 0); bb.Union(rect); } binaryWriter.Write(facesCount); shapeGeometry.BoundingBox = bb; Int32 numTrianglesInFace = triangulation.CoordIndex.Count(); binaryWriter.Write(-numTrianglesInFace); //not a planar face so make negative var packedNormals = new List <XbimPackedNormal>(triangulation.Normals.Count()); foreach (var normal in triangulation.Normals) { var tpl = normal.AsTriplet <IfcParameterValue>(); packedNormals.Add(new XbimPackedNormal(tpl.A, tpl.B, tpl.C)); } int triangleIndex = 0; foreach (var triangle in triangulation.CoordIndex) { var triangleTpl = triangle.AsTriplet(); var normalsIndexTpl = normalIndex[triangleIndex].AsTriplet(); WriteIndex(binaryWriter, (uint)triangleTpl.A - 1, (uint)verticesCount); packedNormals[(int)normalsIndexTpl.A - 1].Write(binaryWriter); WriteIndex(binaryWriter, (uint)triangleTpl.B - 1, (uint)verticesCount); packedNormals[(int)normalsIndexTpl.B - 1].Write(binaryWriter); WriteIndex(binaryWriter, (uint)triangleTpl.C - 1, (uint)verticesCount); packedNormals[(int)normalsIndexTpl.C - 1].Write(binaryWriter); triangleIndex++; } } else //we need to calculate normals to get a better surface fit { var triangulatedMesh = Triangulate(triangulation); shapeGeometry.BoundingBox = triangulatedMesh.BoundingBox; verticesCount = triangulatedMesh.VertexCount; triangleCount = triangulatedMesh.TriangleCount; binaryWriter.Write(verticesCount); //number of vertices binaryWriter.Write(triangleCount); //number of triangles foreach (var vert in triangulatedMesh.Vertices) { binaryWriter.Write((float)vert.X); binaryWriter.Write((float)vert.Y); binaryWriter.Write((float)vert.Z); } facesCount = (uint)triangulatedMesh.Faces.Count; binaryWriter.Write((UInt32)facesCount); foreach (var faceGroup in triangulatedMesh.Faces) { var numTrianglesInFace = faceGroup.Value.Count; //we need to fix this var planar = (ushort.MaxValue != faceGroup.Key); //we have a mesh of faces that all have the same normals at their vertices if (!planar) { numTrianglesInFace *= -1; //set flag to say multiple normals } // ReSharper disable once RedundantCast binaryWriter.Write((Int32)numTrianglesInFace); bool first = true; foreach (var triangle in faceGroup.Value) { if (planar && first) { triangle[0].PackedNormal.Write(binaryWriter); first = false; } WriteIndex(binaryWriter, (uint)triangle[0].StartVertexIndex, verticesCount); if (!planar) { triangle[0].PackedNormal.Write(binaryWriter); } WriteIndex(binaryWriter, (uint)triangle[0].NextEdge.StartVertexIndex, verticesCount); if (!planar) { triangle[0].NextEdge.PackedNormal.Write(binaryWriter); } WriteIndex(binaryWriter, (uint)triangle[0].NextEdge.NextEdge.StartVertexIndex, verticesCount); if (!planar) { triangle[0].NextEdge.NextEdge.PackedNormal.Write(binaryWriter); } } } } binaryWriter.Flush(); ((IXbimShapeGeometryData)shapeGeometry).ShapeData = ms.ToArray(); } return(shapeGeometry); }
public IXbimGeometryObjectSet CreateSurfaceModel(IIfcTriangulatedFaceSet shell) { return(_engine.CreateSurfaceModel(shell)); }