/// <summary> /// Generate a Scene /// </summary> /// <param name="model"></param> /// <returns></returns> public XbimScene <XbimMeshGeometry3D, WpfMaterial> GetModelScene(XbimModel model) { //we need a class which implements IXbimRenderMaterial for the material, you might also want to implement a class for Material depending on your needs, //using the WpfMaterial class that then used the Media3D material class as implemented by the XBimXplorer for convenience. XbimScene <XbimMeshGeometry3D, WpfMaterial> scene = new XbimScene <XbimMeshGeometry3D, WpfMaterial>(model); XbimGeometryHandleCollection handles = new XbimGeometryHandleCollection(model.GetGeometryHandles() .Exclude(IfcEntityNameEnum.IFCFEATUREELEMENT)); foreach (var layerContent in handles.GroupByBuildingElementTypes()) { string elementTypeName = layerContent.Key; XbimGeometryHandleCollection layerHandles = layerContent.Value; IEnumerable <XbimGeometryData> geomColl = model.GetGeometryData(layerHandles); XbimColour colour = scene.LayerColourMap[elementTypeName]; XbimMeshLayer <XbimMeshGeometry3D, WpfMaterial> layer = new XbimMeshLayer <XbimMeshGeometry3D, WpfMaterial>(model, colour) { Name = elementTypeName }; //add all content initially into the hidden field foreach (var geomData in geomColl) { layer.AddToHidden(geomData, model); } scene.Add(layer); } return(scene); }
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()); }
public static string GeomInfoMesh(XbimModel model, int iEntLabel) { StringBuilder sb = new StringBuilder(); var geomdata = model.GetGeometryData(iEntLabel, XbimGeometryType.TriangulatedMesh); foreach (var geom in geomdata) { DumpData(sb, geom.ShapeData); // XbimTriangulatedModelStream // sb.AppendLine(BitConverter.ToString(geom.ShapeData)); } return sb.ToString(); }
public static IEnumerable <XbimGeometryData> GeometryData(this IfcProduct product, XbimGeometryType geomType) { XbimModel model = product.ModelOf as XbimModel; if (model != null) { foreach (var item in model.GetGeometryData(product, geomType)) { yield return(item); } } }
public static string GeomInfoMesh(XbimModel model, int iEntLabel) { StringBuilder sb = new StringBuilder(); var geomdata = model.GetGeometryData(iEntLabel, XbimGeometryType.TriangulatedMesh); foreach (var geom in geomdata) { DumpData(sb, geom.ShapeData); // XbimTriangulatedModelStream // sb.AppendLine(BitConverter.ToString(geom.ShapeData)); } return(sb.ToString()); }
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> /// Works only on models version 1. /// </summary> /// <param name="model"></param> /// <returns></returns> private static XbimRegion GetLargestRegion(XbimModel model) { //get the region data should only be one var project = model.IfcProject; var projectId = 0; if (project != null) { projectId = project.EntityLabel; } // in version 1.0 there should be only 1 record in the database for the project (storing multiple regions). var regionData = model.GetGeometryData(projectId, XbimGeometryType.Region).FirstOrDefault(); if (regionData == null) { return(null); } var regions = XbimRegionCollection.FromArray(regionData.ShapeData); return(regions.MostPopulated()); // this then returns }
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"); }
public void CheckSurfaceStyles() { HashSet<int> surfaceSyleHash = new HashSet<int>(); using (XbimModel model1 = new XbimModel()) { Assert.IsTrue(model1.Open(SourceFile, XbimDBAccess.Read)); foreach (var geom in model1.GetGeometryData(XbimGeometryType.TriangulatedMesh)) surfaceSyleHash.Add(geom.StyleLabel); XbimGeometryHandleCollection geomHandles = model1.GetGeometryHandles(XbimGeometryType.TriangulatedMesh, XbimGeometrySort.OrderByIfcSurfaceStyleThenIfcType); IEnumerable<XbimSurfaceStyle> uniqueStyles = geomHandles.GetSurfaceStyles(); Assert.IsTrue(uniqueStyles.Count() == surfaceSyleHash.Count); foreach (var item in uniqueStyles) surfaceSyleHash.Remove(item.IfcSurfaceStyleLabel); Assert.IsTrue(surfaceSyleHash.Count == 0); XbimSurfaceStyleMap map = geomHandles.ToSurfaceStyleMap(); Assert.IsTrue(geomHandles.Count == map.GeometryHandles.Count()); Assert.IsTrue(map.Styles.Count() == uniqueStyles.Count()); } }
public void CheckGeometryHash() { //check how may geometry data objects have the same byte array HashSet<XbimGeometryData> gHash = new HashSet<XbimGeometryData>(new XbimShapeEqualityComparer()); HashSet<int> hashHash = new HashSet<int>(); using (XbimModel model1 = new XbimModel()) { Assert.IsTrue(model1.Open(SourceFile, XbimDBAccess.Read)); foreach (var mesh in model1.GetGeometryData(XbimGeometryType.TriangulatedMesh)) { int sCount = gHash.Count; gHash.Add(mesh); bool dupGeom = sCount == gHash.Count - 1; sCount = hashHash.Count; hashHash.Add(mesh.GeometryHash); bool dupHash = sCount == hashHash.Count - 1; Assert.AreEqual(dupGeom, dupHash); } Assert.IsTrue(gHash.Count == hashHash.Count); } }
/// <summary> /// Works only on models version 1. /// </summary> /// <param name="model"></param> /// <returns></returns> private static XbimRegion GetLargestRegion(XbimModel model) { //get the region data should only be one var project = model.IfcProject; var projectId = 0; if (project != null) projectId = project.EntityLabel; // in version 1.0 there should be only 1 record in the database for the project (storing multiple regions). var regionData = model.GetGeometryData(projectId, XbimGeometryType.Region).FirstOrDefault(); if (regionData == null) return null; var regions = XbimRegionCollection.FromArray(regionData.ShapeData); return regions.MostPopulated(); // this then returns }
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"); }
/// <summary> /// This function builds a scene of all IfcProducts in the model, excluding the geometry of Openings /// It will create a scene database, overwriting any of the same name /// </summary> /// <param name="model">Model containing the model entities</param> /// <param name="sceneDbName">Name of scene DB file</param> /// <param name="Logger">Logging engine for detailed feedback</param> public void BuildGlobalScene(XbimModel model, string sceneDbName, Common.Logging.ILogger Logger = null) { if (File.Exists(sceneDbName)) File.Delete(sceneDbName); //get a connection using (var db = new XbimSqliteDB(sceneDbName)) { try { short spaceId = IfcMetaData.IfcTypeId(typeof(IfcSpace)); XbimGeometryHandleCollection handles = new XbimGeometryHandleCollection(model.GetGeometryHandles() .Exclude(IfcEntityNameEnum.IFCFEATUREELEMENT)); XbimRect3D modelBounds = XbimRect3D.Empty; XbimColourMap cmap = new XbimColourMap(); int layerid = 1; IfcProject project = model.IfcProject; int projectId = 0; if (project != null) projectId = Math.Abs(project.EntityLabel); float mScalingReference = (float)model.ModelFactors.OneMetre; if (Logger != null) Logger.DebugFormat("XbimScene: Scaling reference {0}\r\n", mScalingReference); XbimMatrix3D translate = XbimMatrix3D.Identity; XbimMatrix3D scale = XbimMatrix3D.CreateScale(1 / mScalingReference); XbimMatrix3D composed = translate * scale; XbimGeometryData regionData = model.GetGeometryData(projectId, XbimGeometryType.Region).FirstOrDefault(); //get the region data should only be one if (regionData != null) { // this results in centering the most populated area of the model // XbimRegionCollection regions = XbimRegionCollection.FromArray(regionData.ShapeData); XbimRegion largest = regions.MostPopulated(); if (largest != null) { translate = XbimMatrix3D.CreateTranslation( -largest.Centre.X, -largest.Centre.Y, -largest.Centre.Z ); } composed = translate * scale; // store region information in Scene if ((Options & GenerateSceneOption.IncludeRegions) == GenerateSceneOption.IncludeRegions) { if (Logger != null) Logger.DebugFormat("XbimScene: Exporting regions.\r\n", mScalingReference); foreach (var item in regions) { // the bounding box needs to be moved/scaled by the transform. // XbimRect3D transformed = item.ToXbimRect3D().Transform(composed); db.AddMetaData( "Region", -1, string.Format("Name:{0};Box:{1};", item.Name, transformed.ToString()), // verbose, but only a few items are expected in the model item.Name ); } } } if ((Options & GenerateSceneOption.IncludeTransform) == GenerateSceneOption.IncludeTransform) { if (Logger != null) Logger.DebugFormat("XbimScene: Exporting transform.\r\n", mScalingReference); db.AddMetaData( "Transform", -1, composed.ToArray(false), "World" ); db.Flush(); } if (Logger != null) Logger.DebugFormat("XbimScene: Exporting layers.\r\n", mScalingReference); foreach (var layerContent in handles.GroupByBuildingElementTypes()) { string elementTypeName = layerContent.Key; XbimGeometryHandleCollection layerHandles = layerContent.Value; IEnumerable<XbimGeometryData> geomColl = model.GetGeometryData(layerHandles); XbimColour colour = cmap[elementTypeName]; XbimMeshLayer<XbimMeshGeometry3D, XbimRenderMaterial> layer = new XbimMeshLayer<XbimMeshGeometry3D, XbimRenderMaterial>(model, colour) { Name = elementTypeName }; //add all content initially into the hidden field foreach (var geomData in geomColl) { geomData.TransformBy(composed); if (geomData.IfcTypeId == spaceId) layer.AddToHidden(geomData); else layer.AddToHidden(geomData, model); } if (modelBounds.IsEmpty) modelBounds = layer.BoundingBoxHidden(); else modelBounds.Union(layer.BoundingBoxHidden()); // add top level layers layerid = RecursivelyPersistLayer(db, layer, layerid, -1); layerid++; } // create scene row in Scenes tables // if (Logger != null) Logger.DebugFormat("XbimScene: Exporting scene.\r\n", mScalingReference); byte[] boundingBoxFull = modelBounds.ToFloatArray(); db.AddScene(1, "MainScene", boundingBoxFull); //now add some meta data about spaces if ( (Options & GenerateSceneOption.IncludeSpaces) == GenerateSceneOption.IncludeSpaces || (Options & GenerateSceneOption.IncludeSpacesBBox) == GenerateSceneOption.IncludeSpacesBBox || (Options & GenerateSceneOption.IncludeSpacesStoreyId) == GenerateSceneOption.IncludeSpacesStoreyId ) { if (Logger != null) Logger.DebugFormat("XbimScene: Exporting spaces.\r\n", mScalingReference); // string data loop foreach (var space in model.Instances.OfType<IfcSpace>()) { int iEntLabel = Math.Abs(space.EntityLabel); if ((Options & GenerateSceneOption.IncludeSpaces) == GenerateSceneOption.IncludeSpaces) { db.AddMetaData( space.GetType().Name, iEntLabel, space.Name ?? "Unnamed Space", iEntLabel.ToString() ); } if ((Options & GenerateSceneOption.IncludeSpacesStoreyId) == GenerateSceneOption.IncludeSpacesStoreyId) { var parent = space.GetContainingStructuralElement(); if (parent == null) { // try with different application behaviours foreach (var item in space.Decomposes) { parent = item.RelatingObject as IfcSpatialStructureElement; if (parent != null) { break; } } // parent = space.Decomposes.FirstOrDefault().RelatingObject; // Decomposes RelatingObject } if (parent != null) { db.AddMetaData( "SpaceToStorey", iEntLabel, string.Format("StoreyName={0};StoreyLabel={1};", parent.Name, parent.EntityLabel), iEntLabel.ToString()); } } } // binary data loop foreach (var space in model.Instances.OfType<IfcSpace>()) { int iEntLabel = Math.Abs(space.EntityLabel); if ((Options & GenerateSceneOption.IncludeSpacesBBox) == GenerateSceneOption.IncludeSpacesBBox) { XbimGeometryData geomdata = model.GetGeometryData(iEntLabel, XbimGeometryType.BoundingBox).FirstOrDefault(); if (geomdata != null) { XbimRect3D r3d = XbimRect3D.FromArray(geomdata.ShapeData); XbimRect3D transformed = r3d.Transform(composed); db.AddMetaData( "SpaceBBox", iEntLabel, // string.Format("Box:{1};", transformed.ToString()), // verbose, but only a few items are expected in the model transformed.ToFloatArray(), iEntLabel.ToString() ); } // db.AddMetaData(space.GetType().Name, space.Name ?? "Undefined Space", space.EntityLabel.ToString()); } } } // Add storey information with elevation. // IfcBuilding bld = model.IfcProject.GetBuildings().FirstOrDefault(); if (bld != null && (Options & GenerateSceneOption.IncludeStoreys) == GenerateSceneOption.IncludeStoreys) { if (Logger != null) Logger.DebugFormat("XbimScene: Exporting storeys.\r\n", mScalingReference); double storeyHeight = 0;//all scenes are in metres int defaultStoreyName = 0; foreach (var storey in bld.GetBuildingStoreys(true)) { string cleanName; if(storey.Name.HasValue) cleanName = storey.Name.Value.ToString().Replace(';', ' '); else cleanName = "Floor " + defaultStoreyName++; var spacesCount = storey.SpatialStructuralElementChildren.OfType<IfcSpatialStructureElement>().ToList().Count(); // add for checking spaces // Storey Elevation is optional (and has been found unreliable), therefore // Storey elevation values (in building reference system) are taken from the // objectplacement through the XbimGeometryType.TransformOnly geometry type // XbimGeometryData geomdata = model.GetGeometryData(storey.EntityLabel, XbimGeometryType.TransformOnly).FirstOrDefault(); if (geomdata != null) { storeyHeight = geomdata.Transform.OffsetZ; // apply the transformation previously applied to the building XbimPoint3D InTranslatedReference = composed.Transform( new XbimPoint3D(0, 0, storeyHeight) ); double InTranslatedReferenceZ = InTranslatedReference.Z; // then express it in meters. // Logger.DebugFormat("StoreyName: {0}; Model Elevation: {1}; Scene Elevation: {2}", cleanName, storeyHeight, InTranslatedReferenceZ); db.AddMetaData( "Storey", Math.Abs(storey.EntityLabel), string.Format("Name:{0};Elevation:{1};SpaceCount:{2};", cleanName, InTranslatedReferenceZ, spacesCount), // storeyHeight), cleanName); } } } } finally { db.Flush(); GC.Collect(); } } }
/// <summary> /// Generate a Scene /// </summary> /// <param name="model"></param> /// <returns></returns> public XbimScene<XbimMeshGeometry3D, WpfMaterial> GetModelScene(XbimModel model) { //we need a class which implements IXbimRenderMaterial for the material, you might also want to implement a class for Material depending on your needs, //using the WpfMaterial class that then used the Media3D material class as implemented by the XBimXplorer for convenience. XbimScene<XbimMeshGeometry3D, WpfMaterial> scene = new XbimScene<XbimMeshGeometry3D, WpfMaterial>(model); XbimGeometryHandleCollection handles = new XbimGeometryHandleCollection(model.GetGeometryHandles() .Exclude(IfcEntityNameEnum.IFCFEATUREELEMENT)); foreach (var layerContent in handles.GroupByBuildingElementTypes()) { string elementTypeName = layerContent.Key; XbimGeometryHandleCollection layerHandles = layerContent.Value; IEnumerable<XbimGeometryData> geomColl = model.GetGeometryData(layerHandles); XbimColour colour = scene.LayerColourMap[elementTypeName]; XbimMeshLayer<XbimMeshGeometry3D, WpfMaterial> layer = new XbimMeshLayer<XbimMeshGeometry3D, WpfMaterial>(model, colour) { Name = elementTypeName }; //add all content initially into the hidden field foreach (var geomData in geomColl) { layer.AddToHidden(geomData, model); } scene.Add(layer); } return scene; }
private static XbimRegionCollection PartitionWorld(XbimModel model, XbimRect3D bounds) { float metre = (float)model.ModelFactors.OneMetre; XbimRegionCollection regions = new XbimRegionCollection(); if (bounds.Length() / metre <= MaxWorldSize) { regions.Add(new XbimRegion("All", bounds, -1)); } else //need to partition the model { List<XbimBBoxClusterElement> ElementsToCluster = new List<XbimBBoxClusterElement>(); foreach (var geomData in model.GetGeometryData(XbimGeometryType.BoundingBox)) { XbimRect3D bound = XbimRect3D.FromArray(geomData.ShapeData); XbimMatrix3D m3D = geomData.Transform; bound = XbimRect3D.TransformBy(bound, m3D); ElementsToCluster.Add(new XbimBBoxClusterElement(geomData.GeometryLabel, bound)); } // the XbimDBSCAN method adopted for clustering produces clusters of contiguous elements. // if the maximum size is a problem they could then be split using other algorithms that divide spaces equally // var v = XbimDBSCAN.GetClusters(ElementsToCluster, 5 * metre); // .OrderByDescending(x => x.GeometryIds.Count); int i = 1; foreach (var item in v) { regions.Add(new XbimRegion("Region " + i++, item.Bound, item.GeometryIds.Count)); } } return regions; }
private XbimRegion GetLargestRegion(XbimModel model) { IfcProject project = model.IfcProject; int projectId = 0; if (project != null) projectId = Math.Abs(project.EntityLabel); XbimGeometryData regionData = model.GetGeometryData(projectId, XbimGeometryType.Region).FirstOrDefault(); //get the region data should only be one if (regionData != null) { XbimRegionCollection regions = XbimRegionCollection.FromArray(regionData.ShapeData); return regions.MostPopulated(); } else return null; }