/// <summary> /// Method for mesh decimation /// </summary> /// <param name="meshStore">mesh data</param> /// <param name="targetTriangleCount">target triangle count for decimation</param> public static void Decimate(ref MeshStore meshStore, int targetTriangleCount) { // extract origin mesh data and create mesh instance Vector3d[] vertices = new Vector3d[meshStore.Vertexes.Count / 3]; for (int i = 0, j = 0; i < meshStore.Vertexes.Count; i += 3, ++j) { vertices[j] = new Vector3d(meshStore.Vertexes[i], meshStore.Vertexes[i + 1], meshStore.Vertexes[i + 2]); } Mesh sourceMesh = new Mesh(vertices, meshStore.Indexes.ToArray()); // decimate mesh var algorithm = MeshDecimation.CreateAlgorithm(Algorithm.Default); algorithm.Verbose = true; Mesh destMesh = MeshDecimation.DecimateMesh(algorithm, sourceMesh, targetTriangleCount); // change meshstore meshStore.Indexes = destMesh.Indices.ToList(); List <double> newVertices = new List <double>(); foreach (Vector3d vec in destMesh.Vertices) { newVertices.Add(vec.x); newVertices.Add(vec.y); newVertices.Add(vec.z); } meshStore.Vertexes = newVertices; }
/// <summary> /// Extract Geometries from IFC file. /// </summary> /// <param name="model">IfcStore model.</param> /// <param name="geometries">Geometries data.</param> /// <param name="modelBoundingBox">Bounding box of the ifc model.</param> public static void ExtractGeometries(IfcStore model, ref Dictionary <string, GeometryStore> geometries, ref XbimRect3D modelBoundingBox) { // context is used to extract geometry data var context = new Xbim3DModelContext(model); var meter = context.Model.ModelFactors.OneMeter; context.CreateContext(); // start to extract geometry data var instances = context.ShapeInstances(); XbimColourMap colorMap = new XbimColourMap(); foreach (var instance in instances) // each instance is a mesh { MeshStore meshStore = new MeshStore(); // get the color of this mesh var ss = model.Instances[instance.StyleLabel] as IIfcSurfaceStyle; XbimColour color = XbimColour.DefaultColour; if (ss != null) { var texture = XbimTexture.Create(ss); color = texture.ColourMap.FirstOrDefault(); } else { var styleId = instance.StyleLabel > 0 ? instance.StyleLabel : instance.IfcTypeId; var theType = model.Metadata.GetType((short)styleId); color = colorMap[theType.Name]; } meshStore.Color = string.Format("{0},{1},{2},{3}", (int)(color.Red * 255), (int)(color.Green * 255), (int)(color.Blue * 255), color.Alpha * 255); var geometry = context.ShapeGeometry(instance); var data = (geometry as IXbimShapeGeometryData).ShapeData; // multiple geometry may belong to one product, like frame and glass belong to a ifcwindow var product = model.Instances[instance.IfcProductLabel] as IIfcProduct; if (!geometries.ContainsKey(product.GlobalId)) { geometries.Add(product.GlobalId, new GeometryStore(product.GlobalId, product.Name)); } var geometryStore = geometries[product.GlobalId]; // reading the real geometry data using (var stream = new MemoryStream(data)) { using (var reader = new BinaryReader(stream)) { // triangle the instance and transform it to the correct position var mesh = reader.ReadShapeTriangulation(); mesh = mesh.Transform(instance.Transformation); // geometry data var verticesData = new List <double>(); var normalsData = new List <double>(); var indexesData = new List <int>(); // bouding box for instance. double minX = double.MaxValue, minY = double.MaxValue, minZ = double.MaxValue, maxX = double.MinValue, maxY = double.MinValue, maxZ = double.MinValue; var faces = mesh.Faces as List <XbimFaceTriangulation>; foreach (var face in faces) { foreach (var indice in face.Indices) { indexesData.Add(indice); } foreach (var normal in face.Normals) { normalsData.Add(normal.Normal.X); normalsData.Add(normal.Normal.Y); normalsData.Add(normal.Normal.Z); } } var vertices = mesh.Vertices as List <XbimPoint3D>; foreach (var point in vertices) { double x = point.X / meter, y = point.Y / meter, z = point.Z / meter; verticesData.Add(x); // convert to meter verticesData.Add(y); verticesData.Add(z); // update bounding box minX = Math.Min(minX, x); minY = Math.Min(minY, y); minZ = Math.Min(minZ, z); maxX = Math.Max(maxX, x); maxY = Math.Max(maxY, y); maxZ = Math.Max(maxZ, z); } if (minX == double.MaxValue || minY == double.MaxValue || minZ == double.MaxValue || maxX == double.MinValue || maxY == double.MinValue || maxZ == double.MinValue) { throw new Exception("Invalid Boundingbox"); } // do not trust instance.BoundingBox, it seems to be wrong. XbimRect3D bbox = new XbimRect3D(minX, minY, minZ, maxX - minX, maxY - minY, maxZ - minZ); // update boundingbox of current geometryStore geometryStore.BoundBox = GeometryStore.Union(geometryStore.BoundBox, bbox); // update boundingbox of ifc model modelBoundingBox = GeometryStore.Union(modelBoundingBox, bbox); meshStore.Vertexes = verticesData; meshStore.Normals = normalsData; meshStore.Indexes = indexesData; } } geometryStore.Meshes.Add(meshStore); } }