/// <summary> /// Allocate each geometry into appropriate tile /// </summary> /// <param name="geometries">Dictionary that contains geometries</param> /// <param name="tiles">Dictionary that contains tiles</param> /// <param name="maxElementPerTile">Maximum number of elements in each tile</param> public static void AllocateGeometryToTile(ref Dictionary <string, GeometryStore> geometries, ref Dictionary <XbimRect3D, List <GeometryStore> > tiles, int maxElementPerTile) { // allocate element to appropriate tile according to intersect volume foreach (GeometryStore gs in geometries.Values) { XbimRect3D candicateTile = XbimRect3D.Empty; double intersectVolume = double.MinValue; foreach (XbimRect3D tile in tiles.Keys) { double volume = GeometryStore.Intersect(gs.BoundBox, tile); if (volume > intersectVolume) { candicateTile = tile; intersectVolume = volume; } } if (!candicateTile.Equals(XbimRect3D.Empty)) { tiles[candicateTile].Add(gs); } } foreach (XbimRect3D bbox in tiles.Keys.ToList()) { // remove empty tile if (tiles[bbox].Count == 0) { tiles.Remove(bbox); } else if (tiles[bbox].Count > maxElementPerTile && bbox.SizeX > 1 && bbox.SizeY > 1 && bbox.SizeZ > 1) // retile a tile(tile size should be large than 1) { Dictionary <XbimRect3D, List <GeometryStore> > subTiles = new Dictionary <XbimRect3D, List <GeometryStore> >(); SplitBoundingBox(bbox, ref subTiles, bbox.SizeX / 2.0, bbox.SizeY / 2.0, bbox.SizeZ / 2.0); Dictionary <string, GeometryStore> elements = new Dictionary <string, GeometryStore>(); foreach (GeometryStore gs in tiles[bbox]) { elements.Add(gs.GlobalId, gs); } AllocateGeometryToTile(ref elements, ref subTiles, maxElementPerTile); tiles.Remove(bbox); foreach (XbimRect3D subBbox in subTiles.Keys) { tiles.Add(subBbox, subTiles[subBbox]); } } } }