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);
        }
Example #2
0
        /// <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);
            }
        }
Example #3
0
        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);
        }
Example #4
0
        /// <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);
        }
Example #5
0
        /// <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)));
        }
Example #6
0
        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);
        }
Example #9
0
        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");
        }
Example #14
0
        /// <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);
        }
Example #15
0
        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();
        }