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);
        }
Пример #3
0
        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);
            }
        }