private void ProcessTree() { double maxSize = SamplerUtil.Max(_boundingBox.SizeX, _boundingBox.SizeY, _boundingBox.SizeZ); double _looseNess = 1.2; _tree = new XbimOctree <int>(maxSize / _looseNess, ScaleOrder, _looseNess, _boundingBox.Centroid()); foreach (int label in _bboxBuffer.Keys) { _tree.Add(label, _bboxBuffer[label]); } XbimRect3D treeBox = _tree.ContentBounds(); if (SamplerUtil.BBoxEqual(treeBox, _boundingBox)) { log.Info("Tree was successfully populated"); } else { log.Error("Tree bounds do not match the boundingbox of the model !"); } }
/// <summary> /// Octree is created in the constructor. This method of spatial /// indexing should speed up spatial queries by doing simple /// computations on indexed geometries. /// </summary> /// <param name="model">Building model</param> public XbimSpatialAnalyser(XbimModel model) { _model = model; _bboxAnalyser = new XbimAABBoxAnalyser(model, _prodBBs); _semanticAnalyser = new XbimSemanticAnalyser(model); //generate geometry if there is no in the model if (model.GeometriesCount == 0) { //create geometry var m3D = new Xbim3DModelContext(model); m3D.CreateContext(true); } //initialize octree with all the objects var prods = model.Instances.OfType <IfcProduct>(); //Stopwatch sw = new Stopwatch(); //var report = new StringWriter(); //report.WriteLine("{0,-15}, {1,-40}, {2,5}, {3,5}", "Type", "Product name", "Geometry", "BBox"); //we need to preprocess all the products first to get world size. Will keep results to avoid repetition. XbimRect3D worldBB = XbimRect3D.Empty; foreach (var prod in prods) { //bounding boxes are lightweight and are produced when geometry is created at first place //sw.Start(); var geom = prod.Geometry3D(); var trans = prod.ObjectPlacement.ToMatrix3D(); //sw.Stop(); //var geomGeneration = sw.ElapsedMilliseconds; if (geom != null && geom.FirstOrDefault() != null) { //get or cast to BBox //sw.Restart(); var bb = geom.GetAxisAlignedBoundingBox(); bb = new XbimRect3D(trans.Transform(bb.Min), trans.Transform(bb.Max)); //sw.Stop(); //var gettingBbox = sw.ElapsedMilliseconds; //report.WriteLine("{0,-15}, {1,-40}, {2,5}, {3,5}", prod.GetType().Name, prod.Name, geomGeneration, gettingBbox); //add every BBox to the world to get the size and position of the world _prodBBs.Add(prod, bb); if (!double.IsNaN(bb.SizeX)) { worldBB.Union(bb); } //Debug.WriteLine("{0,-45} {1,10:F5} {2,10:F5} {3,10:F5} {4,10:F5} {5,10:F5} {6,10:F5}", // prod.Name, bb.X, bb.Y, bb.Z, bb.SizeX, bb.SizeY, bb.SizeZ); } } //Debug.WriteLine("{0,-45} {1,10:F5} {2,10:F5} {3,10:F5} {4,10:F5} {5,10:F5} {6,10:F5}", // "World", worldBB.X, worldBB.Y, worldBB.Z, worldBB.SizeX, worldBB.SizeY, worldBB.SizeZ); //create octree //target size must depend on the units of the model var meter = (float)model.ModelFactors.OneMetre; var size = Math.Max(Math.Max(worldBB.SizeX, worldBB.SizeY), worldBB.SizeZ) + meter / 2f; var shift = meter / 4f; var position = worldBB.Location + new XbimVector3D() { X = size / 2f - shift, Y = size / 2f - shift, Z = size / 2f - shift }; _tree = new XbimOctree <IfcProduct>(size, meter, 1f, position); //sw.Restart(); //add every product to the world foreach (var item in _prodBBs) { _tree.Add(item.Key, item.Value); } //sw.Stop(); //report.WriteLine("Generation of octree containing {0} products {1}", prods.Count(), sw.ElapsedMilliseconds); }
public GeometryComparerII(XbimModel baselineModel, XbimModel revisedModel) { //Martin needs to be re-engineered for new Geometry if (baselineModel == null || revisedModel == null) { throw new ArgumentNullException(); } _baselineModel = baselineModel; _revisedModel = revisedModel; //check if all the model use the same units _meter = baselineModel.ModelFactors.OneMetre; _precision = baselineModel.ModelFactors.Precision; if (Math.Abs(revisedModel.ModelFactors.OneMetre - _meter) > 1e-9) { throw new ArgumentException("All models have to use the same length units."); } //if (Math.Abs(revisedModel.ModelFactors.Precision - _precision) > 1e-9) // throw new ArgumentException("All models have to use the same precision."); if (revisedModel.ModelFactors.Precision > _precision) { _precision = revisedModel.ModelFactors.Precision; } //create geometry context _baselineContext = new Xbim3DModelContext(_baselineModel); _revisedContext = new Xbim3DModelContext(_revisedModel); //get axis aligned BBoxes and overall world size XbimRect3D worldBB = XbimRect3D.Empty; foreach (var context in new [] { _revisedContext, _baselineContext }) { if (!context.CreateContext()) { throw new Exception("Geometry context not created."); } foreach (var shpInst in context.ShapeInstances()) { var bBox = shpInst.BoundingBox; var product = context.Model.Instances.Where <IfcProduct>(p => p.EntityLabel == shpInst.IfcProductLabel).FirstOrDefault(); if (product == null) { throw new Exception("Product not defined."); } if (context == _baselineContext) { _prodBBsA.Add(product, bBox); } else { _prodBBsB.Add(product, bBox); } //add every BBox to the world to get the size and position of the world //if it contains valid BBox if (!double.IsNaN(bBox.SizeX)) { worldBB.Union(bBox); } } } ////foreach (var model in new[] { baselineModel, revisedModel }) //Parallel.ForEach<XbimModel>(new[] { baselineModel, revisedModel }, model => //{ // //load geometry engine using local path // if (model.GeometriesCount == 0) // { // //load geometry engine if it is not loaded yet // string basePath = Path.GetDirectoryName(GetType().Assembly.Location); // AssemblyResolver.GetModelGeometryAssembly(basePath); // } // //initialize octree with all the objects // Xbim3DModelContext context = new Xbim3DModelContext(model); // context.CreateContext(); // var prodShapes = context.ProductShapes; // if (model == baselineModel) // _baselineContext = context; // else // _revisedContext = context; // //we need to preprocess all the products first to get the world size. Will keep results to avoid repetition. // foreach (var shp in prodShapes) // { // //bounding boxes are lightweight and are produced when geometry is created at first place // var bb = shp.BoundingBox; // if (shp.Product.ModelOf == baselineModel) // _prodBBsA.Add(shp.Product, bb); // else // _prodBBsB.Add(shp.Product, bb); // //add every BBox to the world to get the size and position of the world // //if it contains valid BBox // if (!float.IsNaN(bb.SizeX)) // worldBB.Union(bb); // } //} //); //create octree //target size must depend on the units of the model //size inflated with 0.5 meter so that there are not that many products on the boundary of the world var size = Math.Max(Math.Max(worldBB.SizeX, worldBB.SizeY), worldBB.SizeZ) + _meter / 2.0; var shift = (float)_meter / 4f; var position = worldBB.Location + new XbimVector3D() { X = size / 2f - shift, Y = size / 2f - shift, Z = size / 2f - shift }; _tree = new XbimOctree <IfcProduct>(size, (float)_meter, 1f, position); //add every product and its AABBox to octree foreach (var item in _prodBBsA) { _tree.Add(item.Key, item.Value); } foreach (var item in _prodBBsB) { _tree.Add(item.Key, item.Value); } }