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); }
/// <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); } }
public void QuaternionVersusMatrixMovingTests() { XbimVector3D t = new XbimVector3D(2, 0, 0); XbimMatrix3D T = new XbimMatrix3D(t); T.RotateAroundZAxis(Math.PI / 2); XbimQuaternion q; XbimQuaternion.RotationMatrix(ref T, out q); // Do the quaternion approach XbimVector3D v = new XbimVector3D(1, 1, 0); XbimVector3D v1; XbimQuaternion.Transform(ref v, ref q, out v1); // Rotate and translate var p1Result = v1 + t; // Do the same with matrix approach XbimPoint3D p = new XbimPoint3D(1, 1, 0); var p2Result = T.Transform(p); Assert.AreEqual(p1Result, XbimPoint3D.Subtract(p2Result, XbimPoint3D.Zero)); // Test quaternion and delta translation (relocating) XbimVector3D mt = new XbimVector3D(2, 2, 0); var dt = t - mt; var pMoved = v1 + dt; var p3Result = pMoved + mt; Assert.AreEqual(p1Result, p3Result); }
/// <summary> /// Creates a transformed copy of the polygon /// </summary> /// <param name="transform"></param> /// <returns></returns> public XPolygon Transformed(XbimMatrix3D transform) { XPolygon transformed = new XPolygon(); ForEach(p => transformed.Add(transform.Transform(p))); return(transformed); }
/// <summary> /// Shofts the points int he polygon relative to the origin. /// </summary> /// <remarks> /// Because XbimPoint3 wont allow us to modify the X,Y,Z values then we have to create new points /// </remarks> /// <param name="origin"></param> public void Normalize(XbimPoint3D origin) { XbimVector3D offset = new XbimVector3D(-origin.X, -origin.Y, -origin.Z); XbimMatrix3D tr = new XbimMatrix3D(offset); List <XbimPoint3D> temp = new List <XbimPoint3D>(this); Clear(); temp.ForEach(pt => Add(tr.Transform(pt))); }
internal void AddMesh(byte[] mesh, XbimMatrix3D?transform = null) { int indexBase = Positions.Count; bool needRotate = false; bool needTransform = false; XbimQuaternion xq = new XbimQuaternion(0.0, 0.0, 0.0, 1.0); XbimMatrix3D transformValue = XbimMatrix3D.Identity; if (transform.HasValue) { transformValue = transform.Value; needTransform = !transformValue.IsIdentity; xq = transformValue.GetRotationQuaternion(); // we have to build a rotation transform from the quaternion (to tranform normals later on) needRotate = !xq.IsIdentity(); } using (var ms = new MemoryStream(mesh)) using (var br = new BinaryReader(ms)) { var t = br.ReadShapeTriangulation(); List <float[]> pts; List <int> idx; t.ToPointsWithNormalsAndIndices(out pts, out idx); // add to lists // // Commented because of https://github.com/xBimTeam/XbimGltf/issues/2 //Positions.Capacity += pts.Count; //Normals.Capacity += pts.Count; //Indices.Capacity += idx.Count; foreach (var floatsArray in pts) { var tmpPosition = new XbimPoint3D(floatsArray[0], floatsArray[1], floatsArray[2]); if (needTransform) { tmpPosition = transformValue.Transform(tmpPosition); } Positions.Add(tmpPosition); var tmpNormal = new XbimVector3D(floatsArray[3], floatsArray[4], floatsArray[5]); if (needRotate) //transform the normal if we have to { XbimQuaternion.Transform(ref tmpNormal, ref xq, out tmpNormal); } Normals.Add(tmpNormal); } foreach (var index in idx) { Indices.Add(index + indexBase); } } }
public double GetArea() { // the normal can be taken from the product of two segments on the polyline if (Count() < 3) { return(double.NaN); } XbimVector3D normal = Normal() * -1; XbimVector3D firstSegment = this.FirstSegment(); XbimVector3D up = XbimVector3D.CrossProduct(normal, firstSegment); XbimVector3D campos = new XbimVector3D( _geomPoints[0].Point.X, _geomPoints[0].Point.Y, _geomPoints[0].Point.Z ); XbimVector3D target = campos + normal; XbimMatrix3D m = XbimMatrix3D.CreateLookAt(campos, target, up); XbimPoint3D[] point = new XbimPoint3D[Count()]; for (int i = 0; i < point.Length; i++) { XbimPoint3D pBefore = new XbimPoint3D( _geomPoints[i].Point.X, _geomPoints[i].Point.Y, _geomPoints[i].Point.Z ); XbimPoint3D pAft = m.Transform(pBefore); point[i] = pAft; } // http://stackoverflow.com/questions/2553149/area-of-a-irregular-shape // it assumes that the last point is NOT the same of the first one, but it tolerates the case. double area = 0.0f; int numVertices = Count(); for (int i = 0; i < numVertices - 1; ++i) { area += point[i].X * point[i + 1].Y - point[i + 1].X * point[i].Y; } area += point[numVertices - 1].X * point[0].Y - point[0].X * point[numVertices - 1].Y; area /= 2.0; return(area); }
/// <summary> /// Get point on arc by given start point, start direction, arc radius, /// is counter-clockwise and distance along. /// </summary> /// <param name="start"></param> /// <param name="dir"></param> /// <param name="radius"></param> /// <param name="isCCW"></param> /// <param name="dist"></param> /// <returns></returns> public static (XbimPoint3D pt, XbimVector3D vec) GetPointOnCurve(XbimPoint3D start, XbimVector3D dir, double radius, bool isCCW, double dist) { // Compute the location of arc center. var zAxis = new XbimVector3D(0, 0, 1); var start2center = isCCW ? zAxis.CrossProduct(dir) : dir.CrossProduct(zAxis); var center = start + radius * start2center; // Compute the location of arc end point var theta = isCCW ? dist / radius : -dist / radius; var center2start = start2center.Negated(); var mat = new XbimMatrix3D(); mat.RotateAroundZAxis(theta); var center2end = mat.Transform(center2start); var lateral = isCCW ? center2end.Negated() : center2end; return(center + radius * center2end, lateral); }
static public XbimMeshGeometry3D MakeBoundingBox(XbimRect3D r3D, XbimMatrix3D transform) { var mesh = new XbimMeshGeometry3D(8); var p0 = transform.Transform(r3D.Location); var p1 = p0; p1.X += r3D.SizeX; var p2 = p1; p2.Z += r3D.SizeZ; var p3 = p2; p3.X -= r3D.SizeX; var p4 = p3; p4.Y += r3D.SizeY; var p5 = p4; p5.Z -= r3D.SizeZ; var p6 = p5; p6.X += r3D.SizeX; var p7 = p6; p7.Z += r3D.SizeZ; mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.Positions.Add(p3); mesh.Positions.Add(p4); mesh.Positions.Add(p5); mesh.Positions.Add(p6); mesh.Positions.Add(p7); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(4); mesh.TriangleIndices.Add(5); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(5); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(6); mesh.TriangleIndices.Add(4); mesh.TriangleIndices.Add(6); mesh.TriangleIndices.Add(5); mesh.TriangleIndices.Add(4); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(6); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(4); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(6); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(5); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(5); return(mesh); }
/// <summary> /// Get the space name holding the element /// </summary> /// <param name="el">IfcElement to get containing space for</param> /// <returns>Space name</returns> internal string GetSpaceHoldingElement(IfcElement el) { //see if we have space information, if not fill information list if (SpaceBoundingBoxInfo.Count == 0) { if (ifcSpaces == null) { ifcSpaces = Model.Instances.OfType <IfcSpace>().ToList(); } //get Geometry for spaces SpaceBoundingBoxInfo = Model.GetGeometryData(XbimGeometryType.BoundingBox) .Where(bb => bb.IfcTypeId == IfcMetaData.IfcTypeId(typeof(IfcSpace))) .Select(bb => new SpaceInfo { Rectangle = XbimRect3D.FromArray(bb.ShapeData), Matrix = XbimMatrix3D.FromArray(bb.DataArray2), Name = ifcSpaces.Where(sp => (sp.EntityLabel == bb.IfcProductLabel)).Select(sp => sp.Name.ToString()).FirstOrDefault() }).ToList(); } string spaceName = string.Empty; //only if we have any space information if (SpaceBoundingBoxInfo.Any()) { //find the IfcElement Bounding Box and To WCS Matrix XbimGeometryData elGeoData = Model.GetGeometryData(el, XbimGeometryType.BoundingBox).FirstOrDefault(); //check to see if we have any geometry within the file if (elGeoData == null) { return(string.Empty); //No geometry } XbimRect3D elBoundBox = XbimRect3D.FromArray(elGeoData.ShapeData); XbimMatrix3D elWorldMatrix = XbimMatrix3D.FromArray(elGeoData.DataArray2); //Get object space top and bottom points of the bounding box List <XbimPoint3D> elBoxPts = new List <XbimPoint3D>(); elBoxPts.Add(new XbimPoint3D(elBoundBox.X, elBoundBox.Y, elBoundBox.Z)); elBoxPts.Add(new XbimPoint3D(elBoundBox.X + elBoundBox.SizeX, elBoundBox.Y + elBoundBox.SizeY, elBoundBox.Z + elBoundBox.SizeZ)); elBoxPts.Add(elBoundBox.Centroid()); //convert points of the bounding box to WCS IEnumerable <XbimPoint3D> elBoxPtsWCS = elBoxPts.Select(pt => elWorldMatrix.Transform(pt)); //see if we hit any spaces spaceName = GetSpaceFromPoints(elBoxPtsWCS); //if we failed to get space on min points then use the remaining corner points if (string.IsNullOrEmpty(spaceName)) { XbimPoint3D elMinPt = elBoxPts[0]; XbimPoint3D elMaxPt = elBoxPts[1]; //elBoxPts.Clear(); //already tested points in list so clear them //Extra testing on remaining corner points on the top and bottom plains elBoxPts.Add(new XbimPoint3D(elMaxPt.X, elMaxPt.Y, elMinPt.Z)); elBoxPts.Add(new XbimPoint3D(elMaxPt.X, elMinPt.Y, elMinPt.Z)); elBoxPts.Add(new XbimPoint3D(elMinPt.X, elMaxPt.Y, elMinPt.Z)); elBoxPts.Add(new XbimPoint3D((elMaxPt.X - elMinPt.X) / 2.0, (elMaxPt.Y - elMinPt.Y) / 2.0, elMinPt.Z)); //centre face point elBoxPts.Add(new XbimPoint3D(elMinPt.X, elMinPt.Y, elMaxPt.Z)); elBoxPts.Add(new XbimPoint3D(elMaxPt.X, elMinPt.Y, elMaxPt.Z)); elBoxPts.Add(new XbimPoint3D(elMinPt.X, elMaxPt.Y, elMaxPt.Z)); elBoxPts.Add(new XbimPoint3D((elMaxPt.X - elMinPt.X) / 2.0, (elMaxPt.Y - elMinPt.Y) / 2.0, elMaxPt.Z)); //centre face point //convert points of the bounding box to WCS elBoxPtsWCS = elBoxPts.Select(pt => elWorldMatrix.Transform(pt)); //see if we hit any spaces spaceName = GetSpaceFromPoints(elBoxPtsWCS); } if (string.IsNullOrEmpty(spaceName)) { //Get tolerance size from element, 1% of smallest side size double tol = elBoundBox.SizeX * 0.001; if ((elBoundBox.SizeY * 0.001) < tol) { tol = elBoundBox.SizeY * 0.001; } if ((elBoundBox.SizeZ * 0.001) < tol) { tol = elBoundBox.SizeZ * 0.001; } if ((tol == 0.0) && //if tol 0.0 ((Context.WorkBookUnits.LengthUnit.Equals("meters", StringComparison.OrdinalIgnoreCase)) || (Context.WorkBookUnits.LengthUnit.Equals("metres", StringComparison.OrdinalIgnoreCase)) ) ) { tol = 0.001; } spaceName = GetSpaceFromClosestPoints(elBoxPtsWCS, tol); } } return(spaceName); }
/// <summary> /// Calculate the ObjectPlacment for an IfcProduct from row data and the parent object /// </summary> /// <param name="row">COBieCoordinateRow holding the data</param> /// <param name="placementRelToIfcProduct">IfcProduct that the ObjectPlacment relates too, i.e. the parent of the ifcProduct ObjectPlacment we are calculating</param> /// <returns></returns> private IfcLocalPlacement CalcObjectPlacement(COBieCoordinateRow row, IfcProduct placementRelToIfcProduct) { XbimPoint3D locationPt; bool havePoint = GetPointFromRow(row, out locationPt); if (havePoint) { if ((placementRelToIfcProduct != null) && (placementRelToIfcProduct.ObjectPlacement is IfcLocalPlacement)) { //TEST, change the building position to see if the same point comes out in Excel sheet, it should be, and in test was. //((IfcAxis2Placement3D)((IfcLocalPlacement)placementRelToIfcProduct.ObjectPlacement).RelativePlacement).SetNewLocation(10.0, 10.0, 0.0); IfcLocalPlacement placementRelTo = (IfcLocalPlacement)placementRelToIfcProduct.ObjectPlacement; XbimMatrix3D matrix3D = ConvertMatrix3D(placementRelTo); //we want to take off the translations and rotations caused by IfcLocalPlacement of the parent objects as we will add these to the new IfcLocalPlacement for this floor matrix3D.Invert(); //so invert matrix to remove the translations to give the origin for the next IfcLocalPlacement locationPt = matrix3D.Transform(locationPt); //get the point with relation to the last IfcLocalPlacement i.e the parent element //Get the WCS matrix values double rotX, rotY, rotZ; if (!(double.TryParse(row.YawRotation, out rotX) && (double.NaN.CompareTo(rotX) != 0))) { rotX = 0.0; } if (!(double.TryParse(row.ElevationalRotation, out rotY) && (double.NaN.CompareTo(rotY) != 0))) { rotY = 0.0; } if (double.TryParse(row.ClockwiseRotation, out rotZ) && (double.NaN.CompareTo(rotZ) != 0)) { rotZ = rotZ * -1; //convert back from clockwise to anti clockwise } else { rotZ = 0.0; } //apply the WCS rotation from COBie Coordinates stored values XbimMatrix3D matrixNewRot3D = new XbimMatrix3D(); if (rotX != 0.0) { matrixNewRot3D.RotateAroundXAxis(TransformedBoundingBox.DegreesToRadians(rotX)); } if (rotY != 0.0) { matrixNewRot3D.RotateAroundYAxis(TransformedBoundingBox.DegreesToRadians(rotY)); } if (rotZ != 0.0) { matrixNewRot3D.RotateAroundZAxis(TransformedBoundingBox.DegreesToRadians(rotZ)); } //remove any displacement from the matrix which moved/rotated us to the object space matrix3D.OffsetX = 0.0F; matrix3D.OffsetY = 0.0F; matrix3D.OffsetZ = 0.0F; //remove the matrix that got use to the object space from the WCS location of this object XbimMatrix3D matrixRot3D = matrixNewRot3D * matrix3D; //get the rotation vectors to place in the new IfcAxis2Placement3D for the new IfcLocalPlacement for this object XbimVector3D ucsAxisX = matrixRot3D.Transform(new XbimVector3D(1, 0, 0)); XbimVector3D ucsAxisZ = matrixRot3D.Transform(new XbimVector3D(0, 0, 1)); ucsAxisX = ucsAxisX.Normalized(); ucsAxisZ = ucsAxisZ.Normalized(); //create the new IfcAxis2Placement3D IfcAxis2Placement3D relativePlacemant = Model.Instances.New <IfcAxis2Placement3D>(); relativePlacemant.SetNewDirectionOf_XZ(ucsAxisX.X, ucsAxisX.Y, ucsAxisX.Z, ucsAxisZ.X, ucsAxisZ.Y, ucsAxisZ.Z); relativePlacemant.SetNewLocation(locationPt.X, locationPt.Y, locationPt.Z); //Set up IfcLocalPlacement IfcLocalPlacement objectPlacement = Model.Instances.New <IfcLocalPlacement>(); objectPlacement.PlacementRelTo = placementRelTo; objectPlacement.RelativePlacement = relativePlacemant; return(objectPlacement); } } return(null); }
/// <summary> /// Add a Bounding Box extrusion onto the ifcProduct /// </summary> /// <param name="row">COBieCoordinateRow holding the data for one corner</param> /// <param name="rowNext">COBieCoordinateRow holding the data for the other corner</param> /// <param name="placementRelToIfcProduct">Product which is parent of ifcProduct passed product to add extrusion onto</param> /// <param name="ifcProduct">IfcProduct to add the extrusion onto</param> private void AddExtrudedRectangle(COBieCoordinateRow row, COBieCoordinateRow rowNext, IfcProduct ifcProduct, IfcProduct placementRelToIfcProduct) { if (ifcProduct != null) { COBieCoordinateRow lowerLeftRow, upperRightRow; if (row.Category.ToLower() == "box-lowerleft") { lowerLeftRow = row; upperRightRow = rowNext; } else { lowerLeftRow = rowNext; upperRightRow = row; } IfcLocalPlacement objectPlacement = CalcObjectPlacement(lowerLeftRow, placementRelToIfcProduct); if (objectPlacement != null) { //set the object placement for the space ifcProduct.ObjectPlacement = objectPlacement; //get matrix to the space placement XbimMatrix3D matrix3D = ConvertMatrix3D(objectPlacement); //invert matrix so we can convert row points back to the object space matrix3D.Invert(); //lets get the points from the two rows XbimPoint3D lowpt, highpt; if ((GetPointFromRow(upperRightRow, out highpt)) && (GetPointFromRow(lowerLeftRow, out lowpt)) ) { //transform the points back to object space lowpt = matrix3D.Transform(lowpt); highpt = matrix3D.Transform(highpt); //in object space so we can use Rect3D as this will be aligned with coordinates systems X and Y XbimRect3D bBox = new XbimRect3D(); bBox.Location = lowpt; bBox.Union(highpt); if ((double.NaN.CompareTo(bBox.SizeX) != 0) && (double.NaN.CompareTo(bBox.SizeY) != 0)) { XbimPoint3D ctrPt = new XbimPoint3D(bBox.X + (bBox.SizeX / 2.0), bBox.Y + (bBox.SizeY / 2.0), bBox.Z + (bBox.SizeZ / 2.0)); //Create IfcRectangleProfileDef IfcCartesianPoint IfcCartesianPointCtr = Model.Instances.New <IfcCartesianPoint>(cp => { cp.X = ctrPt.X; cp.Y = ctrPt.Y; cp.Z = 0.0; }); //centre point of 2D box IfcDirection IfcDirectionXDir = Model.Instances.New <IfcDirection>(d => { d.X = 1.0; d.Y = 0; d.Z = 0.0; }); //default to X direction IfcAxis2Placement2D ifcAxis2Placement2DCtr = Model.Instances.New <IfcAxis2Placement2D>(a2p => { a2p.Location = IfcCartesianPointCtr; a2p.RefDirection = IfcDirectionXDir; }); IfcRectangleProfileDef ifcRectangleProfileDef = Model.Instances.New <IfcRectangleProfileDef>(rpd => { rpd.ProfileType = IfcProfileTypeEnum.AREA; rpd.ProfileName = row.RowName; rpd.Position = ifcAxis2Placement2DCtr; rpd.XDim = bBox.SizeX; rpd.YDim = bBox.SizeY; }); //Create IfcExtrudedAreaSolid IfcDirection IfcDirectionAxis = Model.Instances.New <IfcDirection>(d => { d.X = 0.0; d.Y = 0; d.Z = 1.0; }); //default to Z direction IfcDirection IfcDirectionRefDir = Model.Instances.New <IfcDirection>(d => { d.X = 1.0; d.Y = 0; d.Z = 0.0; }); //default to X direction IfcCartesianPoint IfcCartesianPointPosition = Model.Instances.New <IfcCartesianPoint>(cp => { cp.X = 0.0; cp.Y = 0.0; cp.Z = 0.0; }); //centre point of 2D box IfcAxis2Placement3D ifcAxis2Placement3DPosition = Model.Instances.New <IfcAxis2Placement3D>(a2p3D => { a2p3D.Location = IfcCartesianPointPosition; a2p3D.Axis = IfcDirectionAxis; a2p3D.RefDirection = IfcDirectionRefDir; }); IfcDirection IfcDirectionExtDir = Model.Instances.New <IfcDirection>(d => { d.X = 0.0; d.Y = 0; d.Z = 1.0; }); //default to Z direction IfcExtrudedAreaSolid ifcExtrudedAreaSolid = Model.Instances.New <IfcExtrudedAreaSolid>(eas => { eas.SweptArea = ifcRectangleProfileDef; eas.Position = ifcAxis2Placement3DPosition; eas.ExtrudedDirection = IfcDirectionExtDir; eas.Depth = bBox.SizeZ; }); var project = Model.FederatedInstances.OfType <IfcProject>().FirstOrDefault(); //Create IfcShapeRepresentation IfcShapeRepresentation ifcShapeRepresentation = Model.Instances.New <IfcShapeRepresentation>(sr => { sr.ContextOfItems = project.ModelContext; sr.RepresentationIdentifier = "Body"; sr.RepresentationType = "SweptSolid"; }); ifcShapeRepresentation.Items.Add(ifcExtrudedAreaSolid); //create IfcProductDefinitionShape IfcProductDefinitionShape ifcProductDefinitionShape = Model.Instances.New <IfcProductDefinitionShape>(pds => { pds.Name = row.Name; pds.Description = row.SheetName; }); ifcProductDefinitionShape.Representations.Add(ifcShapeRepresentation); //Link to the IfcProduct ifcProduct.Representation = ifcProductDefinitionShape; } else { #if DEBUG Console.WriteLine("Failed to calculate box size for {0}", row.Name); #endif } } } else { #if DEBUG Console.WriteLine("Failed to add Object placement for {0}", row.Name); #endif } } }
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> /// If adding the data to the mesh causes the mesh to exceed the max size of ushort.MaxSize /// the data is not added and false is returned. /// </summary> /// <typeparam name="TGeomType"></typeparam> /// <param name="builder"></param> /// <param name="br"></param> /// <param name="transform"></param> /// <returns></returns> private bool BuildWithNormals <TGeomType>(TGeomType builder, BinaryReader br, XbimMatrix3D transform) where TGeomType : IXbimTriangulatesToPositionsNormalsIndices { uint numPositions = br.ReadUInt32(); //if we the mesh is smaller that 64K then try and add it to this mesh, if it is bigger than 65K we just have to stake what we can //if (numPositions < ushort.MaxValue && builder.PositionCount > 0 && (builder.PositionCount + numPositions >= ushort.MaxValue)) //we cannot build meshes bigger than this and pass them through to standard graphics buffers // return false; uint numNormals = br.ReadUInt32(); uint numUniques = br.ReadUInt32(); uint numTriangles = br.ReadUInt32(); uint numPolygons = br.ReadUInt32(); IndexReader PositionReader = new IndexReader(numPositions, br); IndexReader NormalsReader = new IndexReader(numNormals, br); IndexReader UniquesReader = new IndexReader(numUniques, br); float[,] pos = new float[numPositions, 3]; float[,] nrm; nrm = new float[numNormals, 3]; // coordinates of positions // for (uint i = 0; i < numPositions; i++) { pos[i, 0] = br.ReadSingle(); pos[i, 1] = br.ReadSingle(); pos[i, 2] = br.ReadSingle(); } // dimensions of normals // for (uint i = 0; i < numNormals; i++) { nrm[i, 0] = br.ReadSingle(); nrm[i, 1] = br.ReadSingle(); nrm[i, 2] = br.ReadSingle(); } // loop twice for how many indices to create the point/normal combinations. builder.BeginPoints(numUniques); if (transform.IsIdentity) { for (uint i = 0; i < numUniques; i++) { uint readpositionI = PositionReader.ReadIndex(); builder.AddPosition( new XbimPoint3D(pos[readpositionI, 0], pos[readpositionI, 1], pos[readpositionI, 2])); } for (uint i = 0; i < numUniques; i++) { uint readnormalI = NormalsReader.ReadIndex(); builder.AddNormal( new XbimVector3D(nrm[readnormalI, 0], nrm[readnormalI, 1], nrm[readnormalI, 2]) ); } } else { for (uint i = 0; i < numUniques; i++) { uint readpositionI = PositionReader.ReadIndex(); var tfdPosition = transform.Transform(new XbimPoint3D(pos[readpositionI, 0], pos[readpositionI, 1], pos[readpositionI, 2])); builder.AddPosition(tfdPosition); } for (uint i = 0; i < numUniques; i++) { // todo: use a quaternion extracted from the matrix instead // uint readnormalI = NormalsReader.ReadIndex(); var origNormal = new XbimVector3D(nrm[readnormalI, 0], nrm[readnormalI, 1], nrm[readnormalI, 2]); XbimVector3D v = transform.Transform(origNormal); v = v.Normalized(); builder.AddNormal(v); } } builder.EndPoints(); //point/normal combinations completed builder.BeginPolygons(numTriangles, numPolygons); for (uint p = 0; p < numPolygons; p++) { // set the state TriangleType meshType = (TriangleType)br.ReadByte(); uint indicesCount = br.ReadUInt32(); builder.BeginPolygon(meshType, indicesCount); //get the triangles for (uint i = 0; i < indicesCount; i++) { builder.AddTriangleIndex(UniquesReader.ReadIndex()); } builder.EndPolygon(); } builder.EndPolygons(); return(true); }
public XLine Transformed(XbimMatrix3D transform) { XLine temp = new XLine(transform.Transform(sp), transform.Transform(ep)); return(temp); }
public IfcElementSignature(IfcElement elem, Xbim3DModelContext geometryContext) { XbimMatrix3D m3D = XbimMatrix3D.Identity; if (elem.ObjectPlacement != null) { m3D = elem.ObjectPlacement.ToMatrix3D(); } var geomManager = elem.ModelOf.GeometryManager; ShapeId = 0; //get the 3D shape var shapes = geometryContext.ShapeInstancesOf(elem); if (shapes.Any()) { XbimRect3D r3D = XbimRect3D.Empty; foreach (var shape in shapes) { if (r3D.IsEmpty) { r3D = shape.BoundingBox; } else { r3D.Union(shape.BoundingBox); } } XbimPoint3D p3D = r3D.Centroid(); p3D = m3D.Transform(p3D); BoundingSphereRadius = r3D.Length() / 2; CentroidX = p3D.X; CentroidY = p3D.Y; CentroidZ = p3D.Z; } //get the defining type IfcTypeObject ot = elem.GetDefiningType(); IfcMaterialSelect material = elem.GetMaterial(); //sort out property definitions List <IfcPropertySet> psets = elem.GetAllPropertySets(); PropertyCount = psets.SelectMany(p => p.HasProperties).Count(); psets.Sort(new PropertySetNameComparer()); foreach (var pset in psets) { PropertySetNamesKey ^= pset.Name.GetHashCode(); } List <IfcPropertySingleValue> props = psets.SelectMany(p => p.HasProperties).OfType <IfcPropertySingleValue>().ToList(); props.Sort(new PropertySingleValueNameComparer()); foreach (var prop in props) { PropertyNamesKey ^= prop.Name.GetHashCode(); } props.Sort(new PropertySingleValueValueComparer()); foreach (var prop in props) { PropertyValuesKey ^= prop.NominalValue.GetHashCode(); } ModelID = elem.EntityLabel; SchemaType = elem.GetType().Name; DefinedTypeId = (ot == null ? "" : ot.GlobalId.ToPart21); GlobalId = elem.GlobalId; OwningUser = elem.OwnerHistory.LastModifyingUser != null?elem.OwnerHistory.LastModifyingUser.ToString() : elem.OwnerHistory.OwningUser.ToString(); Name = elem.Name ?? ""; Description = elem.Description ?? ""; HasAssignmentsKey = elem.HasAssignments.Count(); IsDecomposedByKey = elem.IsDecomposedBy.Count(); DecomposesKey = elem.Decomposes.Count(); HasAssociationsKey = elem.HasAssociations.Count(); ObjectType = elem.ObjectType ?? ""; MaterialName = material == null ? "" : material.Name; ReferencedByKey = elem.ReferencedBy.Count(); Tag = elem.Tag ?? ""; HasStructuralMemberKey = elem.HasStructuralMember.Count(); FillsVoidsKey = elem.FillsVoids.Count(); ConnectedToKey = elem.ConnectedTo.Count(); HasCoveringsKey = elem.HasCoverings.Count(); HasProjectionsKey = elem.HasProjections.Count(); ReferencedInStructuresKey = elem.ReferencedInStructures.Count(); HasPortsKey = elem.HasPorts.Count(); HasOpeningsKey = elem.HasOpenings.Count(); IsConnectionRealizationKey = elem.IsConnectionRealization.Count(); ProvidesBoundariesKey = elem.ProvidesBoundaries.Count(); ConnectedFromKey = elem.ConnectedFrom.Count(); ContainedInStructureKey = elem.ContainedInStructure.Count(); }