/// <summary> /// Clears the current graphics and initiates the cascade of events that result in viewing the scene. /// </summary> /// <param name="EntityLabels">If null loads the whole model, otherwise only elements listed in the enumerable</param> public void LoadGeometry(XbimModel model, bool recalcView = true) { // AddLayerToDrawingControl is the function that actually populates the geometry in the viewer. // AddLayerToDrawingControl is triggered by BuildRefModelScene and BuildScene below here when layers get ready. //reset all the visuals ClearGraphics(recalcView); short userDefinedId = 0; if (model == null) { return; //nothing to show } model.UserDefinedId = userDefinedId; Xbim3DModelContext context = new Xbim3DModelContext(model); XbimRegion largest = context.GetLargestRegion(); XbimPoint3D c = new XbimPoint3D(0, 0, 0); XbimRect3D bb = XbimRect3D.Empty; if (largest != null) { bb = new XbimRect3D(largest.Centre, largest.Centre); } foreach (var refModel in model.ReferencedModels) { XbimRegion r; refModel.Model.UserDefinedId = ++userDefinedId; Xbim3DModelContext refContext = new Xbim3DModelContext(refModel.Model); r = refContext.GetLargestRegion(); if (r != null) { if (bb.IsEmpty) { bb = new XbimRect3D(r.Centre, r.Centre); } else { bb.Union(r.Centre); } } } XbimPoint3D p = bb.Centroid(); _modelTranslation = new XbimVector3D(-p.X, -p.Y, -p.Z); model.ReferencedModels.CollectionChanged += RefencedModels_CollectionChanged; //build the geometric scene and render as we go BuildScene(context); foreach (var refModel in model.ReferencedModels) { Xbim3DModelContext refContext = new Xbim3DModelContext(refModel.Model); BuildScene(refContext); } if (recalcView) { RecalculateView(model); } }
/// <summary> /// Bounding box of all hidden elements, aligned to the XYZ axis, containing all points in this mesh /// </summary> /// <param name="forceRecalculation">if true the bounding box is recalculated, if false the previous cached version is returned</param> /// <returns></returns> public XbimRect3D BoundingBoxHidden(bool forceRecalculation = false) { if (!forceRecalculation && !_boundingBoxHidden.IsEmpty) { return(_boundingBoxHidden); } var first = true; foreach (var pos in Hidden.Positions) { if (first) { _boundingBoxHidden = new XbimRect3D(pos); first = false; } else { _boundingBoxHidden.Union(pos); } } foreach (var sublayer in _subLayerMap) { XbimRect3D subBox = sublayer.BoundingBoxHidden(forceRecalculation); if (!subBox.IsEmpty) { _boundingBoxHidden.Union(subBox); } } return(_boundingBoxHidden); }
/// <summary> /// distance point is from the axially aligned bounding boxes (usually in object space) /// </summary> /// <param name="pt">Point to get closet point on bounding box from</param> /// <param name="boundBox">Bounding Box as Rect3D</param> /// <returns>Distance from the box edge</returns> internal static double DistanceFromSpace(XbimPoint3D pt, XbimRect3D boundBox) { XbimPoint3D hitPt = ClosetPointOnBoundingBox(pt, boundBox); XbimVector3D vect = XbimPoint3D.Subtract(pt, hitPt); return(vect.Length); }
public XbimRegion(string name, XbimRect3D bounds, int population) { this.Name = name; this.Size = new XbimVector3D(bounds.SizeX, bounds.SizeY, bounds.SizeZ); this.Centre = bounds.Centroid(); this.Population = population; }
/// <summary> /// Closet point on a axially aligned bounding boxes (usually in object space) /// REF: 3D Math Primer for Graphics and Game Development. page 720. /// </summary> /// <param name="pt">Point to get closet point on bounding box from</param> /// <param name="boundBox">Bounding Box as Rect3D</param> /// <returns>Point3D (note: if return point == pt point then point inside box</returns> internal XbimPoint3D ClosetPointOnBoundingBox(XbimPoint3D pt, XbimRect3D boundBox) { XbimPoint3D retPt = new XbimPoint3D(); XbimPoint3D MinPt = new XbimPoint3D(boundBox.X, boundBox.Y, boundBox.Z); XbimPoint3D MaxPt = new XbimPoint3D(boundBox.X + boundBox.SizeX, boundBox.Y + boundBox.SizeY, boundBox.Z + boundBox.SizeZ); if (pt.X < MinPt.X) { retPt.X = MinPt.X; } else if (pt.X > MaxPt.X) { retPt.X = MaxPt.X; } if (pt.Y < MinPt.Y) { retPt.Y = MinPt.Y; } else if (pt.Y > MaxPt.Y) { retPt.Y = MaxPt.Y; } if (pt.Z < MinPt.Z) { retPt.Z = MinPt.Z; } else if (pt.Z > MaxPt.Z) { retPt.Z = MaxPt.Z; } return(retPt); }
/// <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 TransformedBoundingBox(XbimRect3D boundBox, XbimMatrix3D matrix) : this() { //Object space values MinPt = new XbimPoint3D(boundBox.X, boundBox.Y, boundBox.Z); MaxPt = new XbimPoint3D(boundBox.X + boundBox.SizeX, boundBox.Y + boundBox.SizeY, boundBox.Z + boundBox.SizeZ); //make assumption that the X direction will be the longer length hence the orientation will be along the x axis //transformed values, no longer a valid bounding box in the new space if any Pitch or Yaw MinPt = matrix.Transform(MinPt); MaxPt = matrix.Transform(MaxPt); //--------Calculate rotations from matrix------- //rotation around X,Y,Z axis double rotationZ, rotationY, rotationX; GetMatrixRotations(matrix, out rotationX, out rotationY, out rotationZ); //adjust Z to get clockwise rotation ClockwiseRotation = RadiansToDegrees(rotationZ * -1); //use * -1 to make a clockwise rotation ElevationalRotation = RadiansToDegrees(rotationY); YawRotation = RadiansToDegrees(rotationX); }
public GeometryStore(string globalId, string name) { this.GlobalId = globalId; this.Name = name; this.Meshes = new List <MeshStore>(); this.BoundBox = XbimRect3D.Empty; }
/// <summary> /// Get the space name if any of the points are within the space /// </summary> /// <param name="PtsWCS">list of points</param> /// <param name="hitTotarance">Distance the point is outside the space but considered still usable to reference the space</param> /// <param name="SpaceBoundingBoxInfo"></param> /// <returns>Space name</returns> internal static string GetSpaceFromClosestPoints(IEnumerable <XbimPoint3D> PtsWCS, double hitTotarance, IEnumerable <SpaceInfo> SpaceBoundingBoxInfo) { //holder for space names, could be more then one so a list is used List <string> spaceNames = new List <string>(); foreach (SpaceInfo spGeoData in SpaceBoundingBoxInfo) { //get each space bounding box and To WCS Matrix XbimRect3D spBoundBox = spGeoData.Rectangle; XbimMatrix3D spWorldMatrix = spGeoData.Matrix; String spName = spGeoData.Name; //we need to transform the element max and min points back into the spaces Object Space so we can test on Bounding Box rectangle spWorldMatrix.Invert(); IEnumerable <XbimPoint3D> elBoxPtsOCS = PtsWCS.Select(pt => spWorldMatrix.Transform(pt)); //check if element space object points are contained fully within the space bounding box rectangle IEnumerable <double> hitPts = elBoxPtsOCS.Select(pt => DistanceFromSpace(pt, spBoundBox)).Where(d => d <= hitTotarance); if (hitPts.Any())//one or more point is contained in space and continue in case we have an element over several spaces { if (!spaceNames.Contains(spName)) { spaceNames.Add(spName); } } } if (spaceNames.Count > 0) { return(string.Join(", ", spaceNames)); } else { return(string.Empty); } }
private IEnumerable <XbimDirectionEnum> BBoxBorderDirections(XbimRect3D outer, XbimRect3D inner) { if ((inner.Min.X - outer.Min.X) < _precision) { yield return(XbimDirectionEnum.WEST); } if ((inner.Min.Y - outer.Min.Y) < _precision) { yield return(XbimDirectionEnum.SOUTH); } if ((inner.Min.Z - outer.Min.Z) < _precision) { yield return(XbimDirectionEnum.DOWN); } if ((outer.Max.X - inner.Max.X) < _precision) { yield return(XbimDirectionEnum.EAST); } if ((outer.Max.Y - inner.Max.Y) < _precision) { yield return(XbimDirectionEnum.NORTH); } if ((outer.Max.Z - inner.Max.Z) < _precision) { yield return(XbimDirectionEnum.UP); } }
public static BoundingBox ToBoundingBox(this XbimRect3D rect3D, double scale = 1.0, Func <XbimPoint3D, XbimPoint3D> adapter = null) { return(new BoundingBox { ABox = rect3D.ToABox(scale, adapter) }); }
/// <summary> /// calculates the tansform to convert models to metres and centre on the most populated region, includes reference models /// </summary> /// <returns></returns> private XbimMatrix3D GetGlobalModelTransform() { XbimRegion largest = _context.GetLargestRegion(); XbimRect3D bb = XbimRect3D.Empty; if (largest != null) { bb = new XbimRect3D(largest.Centre, largest.Centre); } foreach (var refModel in _context.Model.ReferencedModels) { XbimRegion r; Xbim3DModelContext refContext = new Xbim3DModelContext(refModel.Model); r = refContext.GetLargestRegion(); if (r != null) { if (bb.IsEmpty) { bb = new XbimRect3D(r.Centre, r.Centre); } else { bb.Union(r.Centre); } } } XbimPoint3D p = bb.Centroid(); var modelTranslation = new XbimVector3D(-p.X, -p.Y, -p.Z); double metreFactor = 1.0 / _context.Model.ModelFactors.OneMetre; return(XbimMatrix3D.CreateTranslation(modelTranslation) * XbimMatrix3D.CreateScale(metreFactor)); }
public XbimTriangulatedModel(byte[] triangles, XbimRect3D bounds, int representationLabel, int surfaceStylelabel) { Triangles = triangles; RepresentationLabel = representationLabel; SurfaceStyleLabel = surfaceStylelabel; Bounds = bounds; }
/// <summary> /// Tiling bounding box into small bounding boxes according to options. /// </summary> /// <param name="bbox">Bounding box to tile</param> /// <param name="tiles">output tiles</param> /// <param name="tileXSize">X size of tile</param> /// <param name="tileYSize">Y size of tile</param> /// <param name="tileZSize">Z size of tile</param> public static void SplitBoundingBox(XbimRect3D bbox, ref Dictionary <XbimRect3D, List <GeometryStore> > tiles, double tileXSize, double tileYSize, double tileZSize) { // calculate tile count along x, y, z axis int xCount = (int)Math.Ceiling(bbox.SizeX / tileXSize); int yCount = (int)Math.Ceiling(bbox.SizeY / tileYSize); int zCount = (int)Math.Ceiling(bbox.SizeZ / tileZSize); // tile boundingbox for (int i = 0; i < xCount; ++i) { for (int j = 0; j < yCount; ++j) { for (int k = 0; k < zCount; ++k) { XbimRect3D range = new XbimRect3D( bbox.Min.X + i * tileXSize, bbox.Min.Y + j * tileYSize, bbox.Min.Z + k * tileZSize, tileXSize, tileYSize, tileZSize ); tiles.Add(range, new List <GeometryStore>()); } } } }
/// <summary> /// 获取一个ifcproduct的boundingbox /// </summary> /// <param name="product">指定的product</param> /// <returns>XbimRect3D精度为2位的盒子</returns> public XbimRect3D GetAABB(IIfcProduct product) { //Xbim3DModelContext context = new Xbim3DModelContext(model); //context.CreateContext(); XbimRect3D prodBox = XbimRect3D.Empty; if (context.ShapeInstancesOf(product).Count() == 0) { return(prodBox); } foreach (var shp in context.ShapeInstancesOf(product)) { var bb = shp.BoundingBox; bb = XbimRect3D.TransformBy(bb, shp.Transformation); if (prodBox.IsEmpty) { prodBox = bb; } else { prodBox.Union(bb); } } //精度为2位小数 prodBox.Round(2); return(prodBox); //Console.WriteLine(prodBox.ToString()); }
/// <summary> /// Constructor of spatial relations analyser of axis aligned bounding boxes of the products. /// If you already have a dictionary of the AABBoxes and products you should use the other constructor /// </summary> /// <param name="model">Building model</param> public XbimAABBoxAnalyser(XbimModel model) { _model = model; Xbim3DModelContext context = new Xbim3DModelContext(model); if (model.GeometriesCount == 0) { context.CreateContext(); } //create cached BBoxes foreach (var prod in model.IfcProducts.Cast <IfcProduct>()) { XbimRect3D prodBox = XbimRect3D.Empty; foreach (var shp in context.ShapeInstancesOf(prod)) { //bounding boxes are lightweight and are produced when geometry is created at first place //get or cast to BBox var bb = shp.BoundingBox; bb = XbimRect3D.TransformBy(bb, shp.Transformation); if (prodBox.IsEmpty) { prodBox = bb; } else { prodBox.Union(bb); } //add every BBox to the world to get the size and position of the world } _prodBBs.Add(prod, prodBox); } }
private static void HaveSameSize(XbimRect3D r1, XbimRect3D r2) { const double delta = 0.00001; Assert.AreEqual(r1.SizeX, r2.SizeX, delta, "Size X out of error margin."); Assert.AreEqual(r1.SizeY, r2.SizeY, delta, "Size Y out of error margin."); Assert.AreEqual(r1.SizeZ, r2.SizeZ, delta, "Size Z out of error margin."); }
public static ABox ToABox(this XbimRect3D rect3D, double scale = 1.0, Func <XbimPoint3D, XbimPoint3D> adapter = null) { return(new ABox { Min = adapter?.Invoke(rect3D.Min).ToXYZ(scale) ?? rect3D.Min.ToXYZ(scale), Max = adapter?.Invoke(rect3D.Max).ToXYZ(scale) ?? rect3D.Max.ToXYZ(scale) }); }
private static void HaveSameLocation(XbimRect3D r1, XbimRect3D r2) { const double delta = 0.00001; Assert.AreEqual(r1.Location.X, r2.Location.X, delta, "Position X out of error margin."); Assert.AreEqual(r1.Location.Y, r2.Location.Y, delta, "Position Y out of error margin."); Assert.AreEqual(r1.Location.Z, r2.Location.Z, delta, "Position Z out of error margin."); }
public void IfcStoreGeometryStoreAddTest() { using (var model = IfcStore.Open("TestFiles\\SampleHouse4.ifc")) { var geomStore = model.GeometryStore; using (var txn = geomStore.BeginInit()) { //ADD A GEOMETRY SHAPE var geomData = new XbimShapeGeometry() { IfcShapeLabel = 1, Format = XbimGeometryType.BoundingBox, GeometryHash = 0, LOD = XbimLOD.LOD100, ReferenceCount = 1, ShapeData = "2123", BoundingBox = XbimRect3D.Empty }; var shapeGeomLabel = txn.AddShapeGeometry(geomData); //ADD A SHAPE INSTANCE var shapeInstance = new XbimShapeInstance() { ShapeGeometryLabel = shapeGeomLabel, StyleLabel = 5, RepresentationContext = 50 }; var instanceId = txn.AddShapeInstance(shapeInstance, shapeGeomLabel); Assert.IsTrue(instanceId == 1); //ADD A REGIONCOLLECTION var regions = new XbimRegionCollection(); regions.ContextLabel = 50; var bb = new XbimRect3D(new XbimPoint3D(1, 1, 1), new XbimVector3D(10, 20, 30)); regions.Add(new XbimRegion("region1", bb, 100, XbimMatrix3D.Identity)); txn.AddRegions(regions); txn.Commit(); } model.SaveAs("SampleHouse4.xbim", StorageType.Xbim); model.Close(); } using (var model = IfcStore.Open(@"SampleHouse4.xbim")) { var geomStore = model.GeometryStore; Assert.IsFalse(geomStore.IsEmpty); using (var reader = geomStore.BeginRead()) { Assert.IsTrue(reader.ContextIds.Any()); Assert.IsTrue(reader.ContextRegions.First().ContextLabel == 50); Assert.IsTrue(reader.ShapeGeometries.Count() == 1); Assert.IsTrue(reader.ShapeInstances.Count() == 1); Assert.IsTrue(reader.StyleIds.Count == 1); } model.Close(); } }
public static bool BBoxEqual(XbimRect3D a, XbimRect3D b, double tolerance = 0.001) { return(Equals(a.X, b.X, tolerance) && Equals(a.Y, b.Y, tolerance) && Equals(a.Z, b.Z, tolerance) && Equals(a.SizeX, b.SizeX, tolerance) && Equals(a.SizeY, b.SizeY, tolerance) && Equals(a.SizeZ, b.SizeZ, tolerance)); }
public XbimOctree(XbimOctree <T> copy) { worldSize = copy.worldSize; length = copy.length; objects = copy.objects; children = copy.children; centre = copy.centre; bounds = copy.bounds; }
public void EsentGeometryStoreReopenAddTest() { var db = Guid.NewGuid().ToString() + ".xbim"; var ifc = "TestFiles\\4walls1floorSite.ifc"; var p = new EsentModelProvider { DatabaseFileName = db }; var s = p.GetXbimSchemaVersion(ifc); using (var m = p.Open(ifc, s)) { p.Close(m); } using (var model = IfcStore.Open(db, accessMode: XbimDBAccess.ReadWrite)) { var geomStore = model.GeometryStore; using (var txn = geomStore.BeginInit()) { //ADD A GEOMETRY SHAPE var geomData = new XbimShapeGeometry() { IfcShapeLabel = 1, Format = XbimGeometryType.BoundingBox, GeometryHash = 0, LOD = XbimLOD.LOD100, ReferenceCount = 1, ShapeData = "2123", BoundingBox = XbimRect3D.Empty }; var shapeGeomLabel = txn.AddShapeGeometry(geomData); //ADD A SHAPE INSTANCE var shapeInstance = new XbimShapeInstance() { ShapeGeometryLabel = shapeGeomLabel, StyleLabel = 5, RepresentationContext = 50 }; var instanceId = txn.AddShapeInstance(shapeInstance, shapeGeomLabel); Assert.IsTrue(instanceId == 1); //ADD A REGIONCOLLECTION var regions = new XbimRegionCollection { ContextLabel = 50 }; var bb = new XbimRect3D(new XbimPoint3D(1, 1, 1), new XbimVector3D(10, 20, 30)); regions.Add(new XbimRegion("region1", bb, 100, XbimMatrix3D.Identity)); txn.AddRegions(regions); txn.Commit(); } model.SaveAs("SampleHouse4.xbim", StorageType.Xbim); model.Close(); } }
/// <summary> /// Looks at the maximum distance (between all axis) between two boxes and compares it with a specified threshold. /// </summary> /// <param name="r1">Bounding box 1</param> /// <param name="r2">Bounding box 2</param> /// <param name="eps">the threshold distance</param> /// <returns>True if the maximum distance is under the threshold.</returns> private static bool ValidDistance(XbimRect3D r1, XbimRect3D r2, double eps) { //if (r2.SizeZ > 2000000) // Console.WriteLine("v big"); var dx = AxisDistance(r1.X, r1.SizeX, r2.X, r2.SizeX); var dy = AxisDistance(r1.Y, r1.SizeY, r2.Y, r2.SizeY); var dz = AxisDistance(r1.Z, r1.SizeZ, r2.Z, r2.SizeZ); var max = Math.Max(Math.Max(dx, dy), dz); return(max < eps); }
/// <summary> /// Adds the given object to the octree. /// </summary> /// <param name="o"></param> /// <param name="bBox"></param> public XbimOctree <T> Add(T o, XbimRect3D bBox) { double radius = bBox.Radius(); XbimPoint3D centre = bBox.Centroid(); if (this.bounds.Contains(bBox)) { return(this.Add(o, bBox, centre, radius)); } return(null); }
private XbimRegion Merge(XbimRegion selectedRegion, XbimRegion reg) { var s1 = MinMaxPoints(selectedRegion); var s2 = MinMaxPoints(reg); var r1 = new XbimRect3D(s1[0], s1[1]); var r2 = new XbimRect3D(s2[0], s2[1]); r1.Union(r2); var merged = new XbimRegion("Merged", r1, selectedRegion.Population + reg.Population); return(merged); }
public static bool Disjoint(XbimRect3D a, XbimRect3D b, double tolerance) { return(( a.Max.X + tolerance < b.Min.X || a.Max.Y + tolerance < b.Min.Y || a.Max.Z + tolerance < b.Min.Z ) || ( a.Min.X - tolerance > b.Max.X || a.Min.Y - tolerance > b.Max.Y || a.Min.Z - tolerance > b.Max.Z )); }
public XbimShapeInstance(int id = -1) { _instanceLabel = id; _ifcTypeId = 0; _ifcProductLabel = 0; _styleLabel = 0; _shapeLabel = -1; _representationContext = 0; _representationType = XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded; _transformation = XbimMatrix3D.Identity; _boundingBox = XbimRect3D.Empty; }
/// <summary> /// Adds the given object to the octree. /// </summary> /// <param name="o">The object to add.</param> /// <param name="centre">The object's centre coordinates.</param> /// <param name="radius">The object's radius.</param> private XbimOctree <T> Add(T o, XbimPoint3D centre, double radius) { XbimPoint3D min = centre - new XbimVector3D(radius); XbimPoint3D max = centre + new XbimVector3D(radius); XbimRect3D bounds = new XbimRect3D(min, max); if (this.bounds.Contains(bounds)) { return(this.Add(o, bounds, centre, radius)); } return(null); }
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())); }