/// <summary> /// Adds the geometry fragment to the hidden mesh, if the model is not null /// the fragment is placed on a sub layer of the correct style /// the sub layer is automaticaly created if it does not exist. /// </summary> /// <param name="geomData"></param> /// <param name="model"></param> public void AddToHidden(XbimGeometryData geomData, IModel model, short modelId) { var addingSuccessfull = Hidden.Add(geomData, modelId); // this is where the geometry is added to the main layer. if (addingSuccessfull) { return; } //if the main layer is too big split it. //try and find a sublayer that is a split of this, i.e. has the same texture foreach (var sublayer in _subLayerMap.Reverse()) { if (!Equals(sublayer.Style, Style)) { continue; } sublayer.AddToHidden(geomData, model, modelId); //try and add the data to this mesh return; //succeeded so return } //didn't find a layer to add it to so create a new one var subLayer = new XbimMeshLayer <TMesh, TMaterial>(model, Style) { Name = Name + "-" + _subLayerMap.Count }; _subLayerMap.Add(subLayer); subLayer.Hidden.Add(geomData, modelId); //this should always pass as it is a new mesh and ifc geom rarely exceeds max mesh size, graphics cards will truncate anyway }
/// <summary> /// Adds the geometry fragment to the hidden mesh, if the model is not null /// the fragment is placed on a sub layer of the correct style /// the sub layer is automaticaly created if it does not exist. /// </summary> /// <param name="geomData"></param> /// <param name="model"></param> public void AddToHidden(XbimGeometryData geomData, IModel model = null) { int modelId = 0; if (model != null) { modelId = model.UserDefinedId; } if (model != null && geomData.StyleLabel > 0) // check if we need to put this item on a sub layer { XbimMeshLayer <TMesh, TMaterial> subLayer; var layerName = geomData.StyleLabel.ToString(); if (!_subLayerMap.Contains(layerName)) { var style = model.Instances[geomData.StyleLabel] as IfcSurfaceStyle; //create a sub layer subLayer = new XbimMeshLayer <TMesh, TMaterial>(model, style) { Name = layerName }; _subLayerMap.Add(subLayer); } else { subLayer = _subLayerMap[layerName]; } subLayer.AddToHidden(geomData, null, (short)modelId); } else { AddToHidden(geomData, model, (short)modelId); } }
/// <summary> /// Appends a geometry data object to the Mesh, returns false if the mesh would become too big and needs splitting /// </summary> /// <param name="geometryMeshData"></param> public bool Add(XbimGeometryData geometryMeshData, short modelId = 0) { var transform = XbimMatrix3D.FromArray(geometryMeshData.DataArray2); if (geometryMeshData.GeometryType == XbimGeometryType.TriangulatedMesh) { var strm = new XbimTriangulatedModelStream(geometryMeshData.ShapeData); var fragment = strm.BuildWithNormals(this, transform, modelId); if (fragment.EntityLabel == -1) //nothing was added due to size being exceeded { return(false); } fragment.EntityLabel = geometryMeshData.IfcProductLabel; fragment.EntityTypeId = geometryMeshData.IfcTypeId; _meshes.Add(fragment); } else if (geometryMeshData.GeometryType == XbimGeometryType.BoundingBox) { var r3D = XbimRect3D.FromArray(geometryMeshData.ShapeData); Add(MakeBoundingBox(r3D, transform), geometryMeshData.IfcProductLabel, IfcMetaData.GetType(geometryMeshData.IfcTypeId), modelId); } else { throw new XbimException("Illegal geometry type found"); } return(true); }
public static string GeomInfoBoundBox(XbimModel model, int iEntLabel) { XbimGeometryData geomdata = model.GetGeometryData(iEntLabel, XbimGeometryType.BoundingBox).FirstOrDefault(); if (geomdata == null) { return("<not found>"); } XbimRect3D r3d = XbimRect3D.FromArray(geomdata.ShapeData); return(string.Format("Bounding box (position, size): {0}", r3d.ToString())); }
/// <summary> /// Do not use this rather create a XbimMeshGeometry3D first and construct this from it, appending WPF collections is slow /// </summary> /// <param name="geometryMeshData"></param> /// <param name="modelId"></param> public bool Add(XbimGeometryData geometryMeshData, short modelId) { throw new NotImplementedException(); }
/// <summary> /// Appends a geometry data object to the Mesh, returns false if the mesh would become too big and needs splitting /// </summary> /// <param name="geometryMeshData"></param> public bool Add(XbimGeometryData geometryMeshData) { XbimMatrix3D transform = geometryMeshData.Transform; if (geometryMeshData.GeometryType == XbimGeometryType.TriangulatedMesh) { XbimTriangulatedModelStream strm = new XbimTriangulatedModelStream(geometryMeshData.ShapeData); XbimMeshFragment fragment = strm.BuildWithNormals(this, transform); if (fragment.EntityLabel==int.MinValue) //nothing was added due to size being exceeded return false; else //added ok { fragment.EntityLabel = geometryMeshData.IfcProductLabel; fragment.EntityType = IfcMetaData.GetType(geometryMeshData.IfcTypeId); meshes.Add(fragment); } } else if (geometryMeshData.GeometryType == XbimGeometryType.BoundingBox) { XbimRect3D r3d = XbimRect3D.FromArray(geometryMeshData.ShapeData); this.Add(XbimMeshGeometry3D.MakeBoundingBox(r3d, transform), geometryMeshData.IfcProductLabel, IfcMetaData.GetType(geometryMeshData.IfcTypeId)); } else throw new XbimException("Illegal geometry type found"); return true; }
/// <summary> /// Do not use this rather create a XbimMeshGeometry3D first and construc this from it, appending WPF collections is slow /// </summary> /// <param name="geometryMeshData"></param> public void Append(XbimGeometryData geometryMeshData) { throw new NotImplementedException(); }
/// <summary> /// Get the space name holding the element /// </summary> /// <param name="el">IfcElement to get containing space for</param> /// <returns>Space name</returns> internal string GetSpaceHoldingElement(IfcElement el) { //see if we have space information, if not fill information list if (SpaceBoundingBoxInfo.Count == 0) { if (ifcSpaces == null) { ifcSpaces = Model.Instances.OfType <IfcSpace>().ToList(); } //get Geometry for spaces SpaceBoundingBoxInfo = Model.GetGeometryData(XbimGeometryType.BoundingBox) .Where(bb => bb.IfcTypeId == IfcMetaData.IfcTypeId(typeof(IfcSpace))) .Select(bb => new SpaceInfo { Rectangle = XbimRect3D.FromArray(bb.ShapeData), Matrix = XbimMatrix3D.FromArray(bb.DataArray2), Name = ifcSpaces.Where(sp => (sp.EntityLabel == bb.IfcProductLabel)).Select(sp => sp.Name.ToString()).FirstOrDefault() }).ToList(); } string spaceName = string.Empty; //only if we have any space information if (SpaceBoundingBoxInfo.Any()) { //find the IfcElement Bounding Box and To WCS Matrix XbimGeometryData elGeoData = Model.GetGeometryData(el, XbimGeometryType.BoundingBox).FirstOrDefault(); //check to see if we have any geometry within the file if (elGeoData == null) { return(string.Empty); //No geometry } XbimRect3D elBoundBox = XbimRect3D.FromArray(elGeoData.ShapeData); XbimMatrix3D elWorldMatrix = XbimMatrix3D.FromArray(elGeoData.DataArray2); //Get object space top and bottom points of the bounding box List <XbimPoint3D> elBoxPts = new List <XbimPoint3D>(); elBoxPts.Add(new XbimPoint3D(elBoundBox.X, elBoundBox.Y, elBoundBox.Z)); elBoxPts.Add(new XbimPoint3D(elBoundBox.X + elBoundBox.SizeX, elBoundBox.Y + elBoundBox.SizeY, elBoundBox.Z + elBoundBox.SizeZ)); elBoxPts.Add(elBoundBox.Centroid()); //convert points of the bounding box to WCS IEnumerable <XbimPoint3D> elBoxPtsWCS = elBoxPts.Select(pt => elWorldMatrix.Transform(pt)); //see if we hit any spaces spaceName = GetSpaceFromPoints(elBoxPtsWCS); //if we failed to get space on min points then use the remaining corner points if (string.IsNullOrEmpty(spaceName)) { XbimPoint3D elMinPt = elBoxPts[0]; XbimPoint3D elMaxPt = elBoxPts[1]; //elBoxPts.Clear(); //already tested points in list so clear them //Extra testing on remaining corner points on the top and bottom plains elBoxPts.Add(new XbimPoint3D(elMaxPt.X, elMaxPt.Y, elMinPt.Z)); elBoxPts.Add(new XbimPoint3D(elMaxPt.X, elMinPt.Y, elMinPt.Z)); elBoxPts.Add(new XbimPoint3D(elMinPt.X, elMaxPt.Y, elMinPt.Z)); elBoxPts.Add(new XbimPoint3D((elMaxPt.X - elMinPt.X) / 2.0, (elMaxPt.Y - elMinPt.Y) / 2.0, elMinPt.Z)); //centre face point elBoxPts.Add(new XbimPoint3D(elMinPt.X, elMinPt.Y, elMaxPt.Z)); elBoxPts.Add(new XbimPoint3D(elMaxPt.X, elMinPt.Y, elMaxPt.Z)); elBoxPts.Add(new XbimPoint3D(elMinPt.X, elMaxPt.Y, elMaxPt.Z)); elBoxPts.Add(new XbimPoint3D((elMaxPt.X - elMinPt.X) / 2.0, (elMaxPt.Y - elMinPt.Y) / 2.0, elMaxPt.Z)); //centre face point //convert points of the bounding box to WCS elBoxPtsWCS = elBoxPts.Select(pt => elWorldMatrix.Transform(pt)); //see if we hit any spaces spaceName = GetSpaceFromPoints(elBoxPtsWCS); } if (string.IsNullOrEmpty(spaceName)) { //Get tolerance size from element, 1% of smallest side size double tol = elBoundBox.SizeX * 0.001; if ((elBoundBox.SizeY * 0.001) < tol) { tol = elBoundBox.SizeY * 0.001; } if ((elBoundBox.SizeZ * 0.001) < tol) { tol = elBoundBox.SizeZ * 0.001; } if ((tol == 0.0) && //if tol 0.0 ((Context.WorkBookUnits.LengthUnit.Equals("meters", StringComparison.OrdinalIgnoreCase)) || (Context.WorkBookUnits.LengthUnit.Equals("metres", StringComparison.OrdinalIgnoreCase)) ) ) { tol = 0.001; } spaceName = GetSpaceFromClosestPoints(elBoxPtsWCS, tol); } } return(spaceName); }
/// <summary> /// Appends a geometry data object to the Mesh, returns false if the mesh would become too big and needs splitting /// </summary> /// <param name="geometryMeshData"></param> public bool Add(XbimGeometryData geometryMeshData, short modelId = 0) { var transform = XbimMatrix3D.FromArray(geometryMeshData.DataArray2); if (geometryMeshData.GeometryType == XbimGeometryType.TriangulatedMesh) { var strm = new XbimTriangulatedModelStream(geometryMeshData.ShapeData); var fragment = strm.BuildWithNormals(this, transform, modelId); if (fragment.EntityLabel == -1) //nothing was added due to size being exceeded return false; fragment.EntityLabel = geometryMeshData.IfcProductLabel; fragment.EntityTypeId = geometryMeshData.IfcTypeId; _meshes.Add(fragment); } else if (geometryMeshData.GeometryType == XbimGeometryType.BoundingBox) { var r3D = XbimRect3D.FromArray(geometryMeshData.ShapeData); Add(MakeBoundingBox(r3D, transform), geometryMeshData.IfcProductLabel, IfcMetaData.GetType(geometryMeshData.IfcTypeId), modelId); } else throw new XbimException("Illegal geometry type found"); return true; }
public void Run() { //to start we need an ifc file, here it is Clinic_Example.ifc string ifcFile = @"IfcFiles/Clinic_Example.ifc"; string xbimFile = Path.ChangeExtension(ifcFile, "xBIM"); //will generate if not existing if (File.Exists(ifcFile)) { using (XbimModel model = new XbimModel()) { if (File.Exists(xbimFile)) { //assume the xbim file has the geometry already generated from ifc file, as below model.Open(xbimFile, XbimDBAccess.Read); } else { //create the xbim file from the ifc file model.CreateFrom(ifcFile, xbimFile, delegate(int percentProgress, object userState) { Console.Write("\rReading File {0}", percentProgress); }); model.Open(xbimFile, XbimDBAccess.ReadWrite); //readwrite as we need to add the geometry //add the the geometry information to the model int total = (int)model.Instances.CountOf <IfcProduct>(); ReportProgressDelegate progDelegate = delegate(int percentProgress, object userState) { Console.Write("\rGeometry {0} / {1}", total, (total * percentProgress / 100)); }; XbimMesher.GenerateGeometry(model, null, progDelegate); } //get all the IfcDoors in the model IEnumerable <IfcDoor> ifcDoors = model.IfcProducts.OfType <IfcDoor>(); //get all the ifcdoors for this model if (ifcDoors.Any()) { IfcDoor ifcDoor = ifcDoors.First(); //we use the first door to get the bounding box from XbimGeometryData geoData = model.GetGeometryData(ifcDoor, XbimGeometryType.BoundingBox).FirstOrDefault(); if (geoData != null) { XbimRect3D boundBox = XbimRect3D.FromArray(geoData.ShapeData); //size information for the IfcDoor, but the information is for the bounding box which encloses the door //if want want in World space XbimMatrix3D worldMatrix = geoData.Transform; //if we want to convert to World space we can use the geoData.Transform property and create the world matrix XbimPoint3D MinPtOCS = new XbimPoint3D(boundBox.X, boundBox.Y, boundBox.Z); XbimPoint3D MaxPtOCS = new XbimPoint3D(boundBox.X + boundBox.SizeX, boundBox.Y + boundBox.SizeY, boundBox.Z + boundBox.SizeZ); //transformed values, may no longer a valid bounding box in the new space if any Pitch or Yaw, i.e. stairs ceiling supports XbimPoint3D MinPtWCS = worldMatrix.Transform(MinPtOCS); XbimPoint3D MaxPtWCS = worldMatrix.Transform(MaxPtOCS); //if you product is at any angle to the World space then the bounding box can be recalculated, //a example of this can be found here https://sbpweb.svn.codeplex.com/svn/SBPweb.Workbench/Workbench%20Framework%202.0.0.x/Presentation/Windows.WPF/Utils/Maths.cs //in the TransformBounds function Console.WriteLine("\n-------------Bounding Box Information-------------"); Console.WriteLine("Entity Type = {0}", IfcMetaData.GetType(geoData.IfcTypeId).Name); Console.WriteLine("Entity Label = {0}", Math.Abs(ifcDoor.EntityLabel).ToString()); Console.WriteLine("Size X = {0:F2}", boundBox.SizeX.ToString()); Console.WriteLine("Size Y = {0:F2}", boundBox.SizeY.ToString()); Console.WriteLine("Size Z = {0:F2}", boundBox.SizeZ.ToString()); Console.WriteLine("Object space minimum point {0}", MinPtOCS); Console.WriteLine("Object space maximum point {0}", MaxPtOCS); Console.WriteLine("World space minimum point {0}", MinPtWCS); Console.WriteLine("World space maximum point {0}", MaxPtWCS); Console.WriteLine("---------------------------------------------"); } } else { Console.WriteLine(string.Format("Failed to find any IfcDoor's in {0}", ifcFile)); return; //exit } } } else { Console.WriteLine(string.Format("Failed to find {0} in executable directory", ifcFile)); } Console.WriteLine("\nFinished"); }