예제 #1
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            IList <IFCAnyHandle> points = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(ifcCurve, "Points");
            int numPoints = points.Count;

            if (numPoints < 2)
            {
                string msg = "IfcPolyLine had " + numPoints + ", expected at least 2, ignoring";
                Importer.TheLog.LogError(Id, msg, false);
                return;
            }

            IList <XYZ> pointXYZs = new List <XYZ>();

            foreach (IFCAnyHandle point in points)
            {
                XYZ pointXYZ = IFCPoint.ProcessScaledLengthIFCCartesianPoint(point);
                pointXYZs.Add(pointXYZ);
            }

            if (pointXYZs.Count != numPoints)
            {
                Importer.TheLog.LogError(Id, "Some of the IFC points cannot be converted to Revit points", true);
            }

            CurveLoop = IFCGeometryUtil.CreatePolyCurveLoop(pointXYZs, points, Id, false);
            Curve     = IFCGeometryUtil.CreateCurveFromPolyCurveLoop(CurveLoop, pointXYZs);
        }
        private void CreateBoxShape(IFCImportShapeEditScope shapeEditScope, Transform scaledLcs)
        {
            using (IFCImportShapeEditScope.IFCContainingRepresentationSetter repSetter = new IFCImportShapeEditScope.IFCContainingRepresentationSetter(shapeEditScope, this))
            {
                // Get the material and graphics style based in the "Box" sub-category of Generic Models.
                // We will create the sub-category if this is our first time trying to use it.
                // Note that all bounding boxes are controlled by a sub-category of Generic Models.  We may revisit that decision later.
                // Note that we hard-wire the identifier to "Box" because older files may have bounding box items in an obsolete representation.
                SolidOptions solidOptions = null;
                Category     bboxCategory = IFCCategoryUtil.GetSubCategoryForRepresentation(shapeEditScope.Document, Id, IFCRepresentationIdentifier.Box);
                if (bboxCategory != null)
                {
                    ElementId     materialId    = (bboxCategory.Material == null) ? ElementId.InvalidElementId : bboxCategory.Material.Id;
                    GraphicsStyle graphicsStyle = bboxCategory.GetGraphicsStyle(GraphicsStyleType.Projection);
                    ElementId     gstyleId      = (graphicsStyle == null) ? ElementId.InvalidElementId : graphicsStyle.Id;
                    solidOptions = new SolidOptions(materialId, gstyleId);
                }

                Solid bboxSolid = IFCGeometryUtil.CreateSolidFromBoundingBox(scaledLcs, BoundingBox, solidOptions);
                if (bboxSolid != null)
                {
                    IFCSolidInfo bboxSolidInfo = IFCSolidInfo.Create(Id, bboxSolid);
                    shapeEditScope.AddGeometry(bboxSolidInfo);
                }
            }
            return;
        }
        private IList <CurveLoop> GetTransformedCurveLoopsFromSimpleProfile(IFCSimpleProfile simpleSweptArea, Transform unscaledLcs, Transform scaledLcs)
        {
            IList <CurveLoop> loops = new List <CurveLoop>();

            // It is legal for simpleSweptArea.Position to be null, for example for IfcArbitraryClosedProfileDef.
            Transform unscaledSweptAreaPosition =
                (simpleSweptArea.Position == null) ? unscaledLcs : unscaledLcs.Multiply(simpleSweptArea.Position);

            Transform scaledSweptAreaPosition =
                (simpleSweptArea.Position == null) ? scaledLcs : scaledLcs.Multiply(simpleSweptArea.Position);

            CurveLoop currLoop = simpleSweptArea.OuterCurve;

            if (currLoop == null || currLoop.Count() == 0)
            {
                Importer.TheLog.LogError(simpleSweptArea.Id, "No outer curve loop for profile, ignoring.", false);
                return(null);
            }
            loops.Add(IFCGeometryUtil.CreateTransformed(currLoop, Id, unscaledSweptAreaPosition, scaledSweptAreaPosition));

            if (simpleSweptArea.InnerCurves != null)
            {
                foreach (CurveLoop innerCurveLoop in simpleSweptArea.InnerCurves)
                {
                    loops.Add(IFCGeometryUtil.CreateTransformed(innerCurveLoop, Id, unscaledSweptAreaPosition, scaledSweptAreaPosition));
                }
            }

            return(loops);
        }
예제 #4
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);
            KnotMultiplicities = IFCAnyHandleUtil.GetAggregateIntAttribute <List <int> >(ifcCurve, "KnotMultiplicities");
            Knots = IFCAnyHandleUtil.GetAggregateDoubleAttribute <List <double> >(ifcCurve, "Knots");

            if (KnotMultiplicities == null || Knots == null)
            {
                Importer.TheLog.LogError(ifcCurve.StepId, "Cannot find the KnotMultiplicities or Knots attribute of this IfcBSplineCurveWithKnots", true);
            }

            if (KnotMultiplicities.Count != Knots.Count)
            {
                Importer.TheLog.LogError(ifcCurve.StepId, "The number of knots and knot multiplicities are not the same", true);
            }

            IList <double> revitKnots = IFCGeometryUtil.ConvertIFCKnotsToRevitKnots(KnotMultiplicities, Knots);

            Curve nurbsSpline = NurbSpline.CreateCurve(Degree, revitKnots, ControlPointsList);

            SetCurve(nurbsSpline);

            if (nurbsSpline == null)
            {
                Importer.TheLog.LogWarning(ifcCurve.StepId, "Cannot get the curve representation of this IfcCurve", false);
            }
        }
예제 #5
0
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation scope.</param>
        /// <param name="unscaledLcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>Zero or more created geometries.</returns>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs, Transform scaledLcs, string guid)
        {
            Transform unscaledSweptDiskPosition = (unscaledLcs == null) ? Transform.Identity : unscaledLcs;
            Transform scaledSweptDiskPosition   = (scaledLcs == null) ? Transform.Identity : scaledLcs;

            CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(Id, Directrix, StartParameter, EndParameter);

            if (trimmedDirectrix == null)
            {
                return(null);
            }

            CurveLoop trimmedDirectrixInWCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, Id, unscaledSweptDiskPosition, scaledSweptDiskPosition);

            // Create the disk.
            Curve firstCurve = null;

            foreach (Curve curve in trimmedDirectrixInWCS)
            {
                firstCurve = curve;
                break;
            }

            double            startParam        = 0.0;
            IList <CurveLoop> profileCurveLoops = CreateProfileCurveLoopsForDirectrix(firstCurve, out startParam);

            if (profileCurveLoops == null)
            {
                return(null);
            }

            SolidOptions           solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            IList <GeometryObject> myObjs       = new List <GeometryObject>();

            try
            {
                Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInWCS, 0, startParam, profileCurveLoops,
                                                                                     solidOptions);
                if (sweptDiskSolid != null)
                {
                    myObjs.Add(sweptDiskSolid);
                }
            }
            catch (Exception ex)
            {
                // If we can't create a solid, we will attempt to split the Solid into valid pieces (that will likely have some overlap).
                if (ex.Message.Contains("self-intersections"))
                {
                    Importer.TheLog.LogWarning(Id, "The IfcSweptDiskSolid definition does not define a valid solid, likely due to self-intersections or other such problems; the profile probably extends too far toward the inner curvature of the sweep path. Creating the minimum number of solids possible to represent the geometry.", false);
                    myObjs = SplitSweptDiskIntoValidPieces(trimmedDirectrixInWCS, profileCurveLoops, solidOptions);
                }
                else
                {
                    throw ex;
                }
            }

            return(myObjs);
        }
예제 #6
0
 private void CreateLineSegments(CurveLoop curveLoop, IList <XYZ> currentSegments)
 {
     if (currentSegments.Count > 0)
     {
         IFCGeometryUtil.AppendPolyCurveToCurveLoop(curveLoop, currentSegments, null, Id, false);
         currentSegments.Clear();
     }
 }
예제 #7
0
 /// <summary>
 /// Set the representation of the curve based on one CurveLoop.
 /// </summary>
 /// <param name="curveLoop">The one CurveLoop.</param>
 /// <param name="pointXYZs">The point list that created this CurveLoop.</param>
 /// <remarks>The point list is used to potentially collapse a series of
 /// line segments into one.</remarks>
 public void SetCurveLoop(CurveLoop curveLoop, IList <XYZ> pointXYZs)
 {
     SetCurveLoop(curveLoop);
     if (Curve == null)
     {
         Curve = IFCGeometryUtil.CreateCurveFromPolyCurveLoop(GetTheCurveLoop(), pointXYZs);
     }
 }
예제 #8
0
        protected List <GeometryObject> CreateConformalGeometryIfPossible(
            IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs)
        {
            Transform unscaledSweptDiskPosition = (unscaledLcs == null) ? Transform.Identity : unscaledLcs;

            IList <CurveLoop> trimmedDirectrices = IFCGeometryUtil.TrimCurveLoops(Id, Directrix, StartParameter, EndParameter);

            if (trimmedDirectrices == null)
            {
                return(null);
            }

            List <GeometryObject> myObjs = null;
            bool isIdentity = unscaledSweptDiskPosition.IsIdentity;

            foreach (CurveLoop trimmedDirectrix in trimmedDirectrices)
            {
                // Create the disk.
                Curve firstCurve = null;
                foreach (Curve curve in trimmedDirectrix)
                {
                    firstCurve = curve;
                    break;
                }

                double            startParam        = 0.0;
                IList <CurveLoop> profileCurveLoops = CreateProfileCurveLoopsForDirectrix(firstCurve, out startParam);
                if (profileCurveLoops == null)
                {
                    return(null);
                }

                SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
                myObjs = new List <GeometryObject>();

                try
                {
                    Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrix, 0, startParam, profileCurveLoops,
                                                                                         solidOptions);
                    if (!isIdentity)
                    {
                        sweptDiskSolid = SolidUtils.CreateTransformed(sweptDiskSolid, unscaledSweptDiskPosition);
                    }

                    if (sweptDiskSolid != null)
                    {
                        myObjs.Add(sweptDiskSolid);
                    }
                }
                catch
                {
                    return(null);
                }
            }

            return(myObjs);
        }
예제 #9
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            IList <IFCAnyHandle> points = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(ifcCurve, "Points");
            int numPoints = points.Count;

            if (numPoints < 2)
            {
                string msg = "IfcPolyLine had " + numPoints + ", expected at least 2, ignoring";
                Importer.TheLog.LogError(Id, msg, false);
                return;
            }

            IList <XYZ> pointXYZs = new List <XYZ>();

            foreach (IFCAnyHandle point in points)
            {
                XYZ pointXYZ = IFCPoint.ProcessScaledLengthIFCCartesianPoint(point);
                pointXYZs.Add(pointXYZ);
            }
            if (pointXYZs.Count != numPoints)
            {
                Importer.TheLog.LogError(Id, "Some of the IFC points cannot be converted to Revit points", true);
            }

            CurveLoop = IFCGeometryUtil.CreatePolyCurveLoop(pointXYZs, points, Id, false);
            if (pointXYZs.Count == 2)
            {
                Curve = Line.CreateBound(pointXYZs[0], pointXYZs[1]);
            }
            else
            {
                // if we go here we are sure that the number of point must be at least 3
                XYZ firstPoint   = pointXYZs[0];
                XYZ secondPoint  = pointXYZs[1];
                XYZ vectorToTest = (secondPoint - firstPoint).Normalize();

                bool allAreCollinear = true;
                for (int ii = 2; ii < numPoints; ii++)
                {
                    XYZ vectorTmp = (pointXYZs[ii] - firstPoint).Normalize();
                    if (!vectorTmp.IsAlmostEqualTo(vectorToTest))
                    {
                        allAreCollinear = false;
                        break;
                    }
                }
                if (allAreCollinear)
                {
                    Curve = Line.CreateBound(firstPoint, pointXYZs[numPoints - 1]);
                }
            }
        }
예제 #10
0
        private BRepBuilderSurfaceGeometry StartCollectingNURBSFace(IFCBSplineSurfaceWithKnots bSplineSurfaceWithKnots, Transform localTransform)
        {
            if (bSplineSurfaceWithKnots == null)
            {
                return(null);
            }

            IFCRationalBSplineSurfaceWithKnots rationalBSplineSurfaceWithKnots = (bSplineSurfaceWithKnots as IFCRationalBSplineSurfaceWithKnots);

            IList <double> knotsU = IFCGeometryUtil.ConvertIFCKnotsToRevitKnots(bSplineSurfaceWithKnots.UMultiplicities, bSplineSurfaceWithKnots.UKnots);

            if (knotsU == null || knotsU.Count == 0)
            {
                throw new InvalidOperationException("No knots in u-direction");
            }

            IList <double> knotsV = IFCGeometryUtil.ConvertIFCKnotsToRevitKnots(bSplineSurfaceWithKnots.VMultiplicities, bSplineSurfaceWithKnots.VKnots);

            if (knotsV == null || knotsV.Count == 0)
            {
                throw new InvalidOperationException("No knots in v-direction");
            }

            IList <double> weights = (rationalBSplineSurfaceWithKnots != null) ? rationalBSplineSurfaceWithKnots.WeightsList : null;

            IList <XYZ> controlPoints = new List <XYZ>();

            foreach (XYZ point in bSplineSurfaceWithKnots.ControlPointsList)
            {
                controlPoints.Add(localTransform.OfPoint(point));
            }

            int uDegree = bSplineSurfaceWithKnots.UDegree;
            int vDegree = bSplineSurfaceWithKnots.VDegree;

            BRepBuilderSurfaceGeometry surfaceGeometry = null;

            if (weights == null)
            {
                surfaceGeometry = BRepBuilderSurfaceGeometry.CreateNURBSSurface(uDegree, vDegree, knotsU, knotsV, controlPoints, false, null);
            }
            else
            {
                surfaceGeometry = BRepBuilderSurfaceGeometry.CreateNURBSSurface(uDegree, vDegree, knotsU, knotsV, controlPoints, weights, false, null);
            }

            return(surfaceGeometry);
        }
예제 #11
0
        override protected CurveLoop GenerateLoop()
        {
            IList <XYZ> polygon = Polygon;

            if (polygon == null)
            {
                throw new InvalidOperationException("#" + Id + ": missing polygon, ignoring.");
            }

            int numVertices = Polygon.Count;

            if (numVertices < 3)
            {
                throw new InvalidOperationException("#" + Id + ": Polygon attribute has only " + numVertices + " vertices, 3 expected.");
            }

            return(IFCGeometryUtil.CreatePolyCurveLoop(polygon, null, Id, true));
        }
예제 #12
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            IFCAnyHandle points = IFCAnyHandleUtil.GetInstanceAttribute(ifcCurve, "Points");

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(points))
            {
                Importer.TheLog.LogMissingRequiredAttributeError(ifcCurve, "Points", true);
                return;
            }

            IFCCartesianPointList pointList = IFCCartesianPointList.ProcessIFCCartesianPointList(points);
            IList <XYZ>           pointXYZs = pointList.CoordList;

            int numPoints = pointXYZs.Count;

            SetCurveLoop(IFCGeometryUtil.CreatePolyCurveLoop(pointXYZs, null, Id, false), pointXYZs);
        }
예제 #13
0
        /// <summary>
        /// Cut a IFCSolidInfo by the voids in this IFCProduct, if any.
        /// </summary>
        /// <param name="solidInfo">The solid information.</param>
        /// <returns>False if the return solid is empty; true otherwise.</returns>
        protected override bool CutSolidByVoids(IFCSolidInfo solidInfo)
        {
            int numVoids = Voids.Count;

            if (numVoids == 0)
            {
                return(true);
            }

            // We only cut body representation items.
            if (solidInfo.RepresentationType != IFCRepresentationIdentifier.Body)
            {
                return(true);
            }

            if (!(solidInfo.GeometryObject is Solid))
            {
                string typeName = (solidInfo.GeometryObject is Mesh) ? "mesh" : "instance";
                Importer.TheLog.LogError(Id, "Can't cut " + typeName + " geometry, ignoring " + numVoids + " void(s).", false);
                return(true);
            }

            for (int voidIdx = 0; voidIdx < numVoids; voidIdx++)
            {
                Solid voidObject = Voids[voidIdx].GeometryObject as Solid;
                if (voidObject == null)
                {
                    Importer.TheLog.LogError(Id, "Can't cut Solid geometry with a Mesh (# " + Voids[voidIdx].Id + "), ignoring.", false);
                    return(true);
                }

                solidInfo.GeometryObject = IFCGeometryUtil.ExecuteSafeBooleanOperation(solidInfo.Id, Voids[voidIdx].Id,
                                                                                       (solidInfo.GeometryObject as Solid), voidObject, BooleanOperationsType.Difference, null);
                if (solidInfo.GeometryObject == null || (solidInfo.GeometryObject as Solid).Faces.IsEmpty)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #14
0
        override protected CurveLoop GenerateLoop()
        {
            IList <XYZ> polygon = Polygon;

            if (polygon == null)
            {
                // This used to throw an error.  However, we found files that threw this error
                // thousands of times, causing incredibly slow links.  Instead, null out the
                // data and log an error.
                Importer.TheLog.LogError(Id, "missing polygon, ignoring.", false);
            }

            int numVertices = Polygon.Count;

            if (numVertices < 3)
            {
                throw new InvalidOperationException("#" + Id + ": Polygon attribute has only " + numVertices + " vertices, 3 expected.");
            }

            return(IFCGeometryUtil.CreatePolyCurveLoop(polygon, null, Id, true));
        }
예제 #15
0
        private void ProcessIFCPolyline(IFCAnyHandle ifcCurve)
        {
            IList <IFCAnyHandle> points = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(ifcCurve, "Points");
            int numPoints = points.Count;

            if (numPoints < 2)
            {
                string msg = "IfcPolyLine had " + numPoints + ", expected at least 2, ignoring";
                IFCImportFile.TheLog.LogError(Id, msg, false);
                return;
            }

            IList <XYZ> pointXYZs = new List <XYZ>();

            foreach (IFCAnyHandle point in points)
            {
                XYZ pointXYZ = IFCPoint.ProcessScaledLengthIFCCartesianPoint(point);
                pointXYZs.Add(pointXYZ);
            }

            CurveLoop = IFCGeometryUtil.CreatePolyCurveLoop(pointXYZs, points, Id, false);
        }
예제 #16
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            bool   found  = false;
            double radius = IFCImportHandleUtil.GetRequiredScaledLengthAttribute(ifcCurve, "Radius", out found);

            if (!found)
            {
                Importer.TheLog.LogError(ifcCurve.StepId, "Cannot find the radius of this circle", false);
                return;
            }

            if (!IFCGeometryUtil.IsValidRadius(radius))
            {
                Importer.TheLog.LogError(ifcCurve.StepId, "Invalid radius for this circle: " + radius, false);
                return;
            }

            try
            {
                SetCurve(Arc.Create(Position.Origin, radius, 0, 2.0 * Math.PI, Position.BasisX, Position.BasisY));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("too small"))
                {
                    string lengthAsString = IFCUnitUtil.FormatLengthAsString(radius);
                    Importer.TheLog.LogError(Id, "Found a circle with radius of " + lengthAsString + ", ignoring.", false);
                }
                else
                {
                    Importer.TheLog.LogError(Id, ex.Message, false);
                }
                SetCurve(null);
            }
        }
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation scope.</param>
        /// <param name="unscaledLcs">The unscaled local coordinate system for the geometry, if the scaled version isn't supported downstream.</param>
        /// <param name="scaledLcs">The scaled (true) local coordinate system for the geometry.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs, Transform scaledLcs, string guid)
        {
            Transform unscaledObjectPosition = (unscaledLcs == null) ? Position : unscaledLcs.Multiply(Position);
            Transform scaledObjectPosition   = (scaledLcs == null) ? Position : scaledLcs.Multiply(Position);

            CurveLoop baseProfileCurve = Directrix.GetCurveLoop();

            if (baseProfileCurve == null)
            {
                return(null);
            }

            CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(Id, baseProfileCurve, StartParameter, EndParameter);

            if (trimmedDirectrix == null)
            {
                return(null);
            }

            double    startParam  = 0.0; // If the directrix isn't bound, this arbitrary parameter will do.
            Transform originTrf0  = null;
            Curve     firstCurve0 = trimmedDirectrix.First();

            if (firstCurve0.IsBound)
            {
                startParam = firstCurve0.GetEndParameter(0);
            }
            originTrf0 = firstCurve0.ComputeDerivatives(startParam, false);
            if (originTrf0 == null)
            {
                return(null);
            }

            // Note: the computation of the reference Surface Local Transform must be done before the directrix is transform to LCS (because the ref surface isn't)
            //     and therefore the origin is at the start of the curve should be the start of the directrix that lies on the surface.
            //     This is needed to transform the swept area that must be perpendicular to the start of the directrix curve

            Transform referenceSurfaceLocalTransform = ReferenceSurface.GetTransformAtPoint(originTrf0.Origin);

            CurveLoop trimmedDirectrixInLCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, Id, unscaledObjectPosition, scaledObjectPosition);

            // Create the sweep.
            Transform originTrf  = null;
            Curve     firstCurve = trimmedDirectrixInLCS.First();

            //if (firstCurve.IsBound)
            //    startParam = firstCurve.GetEndParameter(0);
            originTrf = firstCurve.ComputeDerivatives(startParam, false);

            Transform unscaledReferenceSurfaceTransform = unscaledObjectPosition.Multiply(referenceSurfaceLocalTransform);
            Transform scaledReferenceSurfaceTransform   = scaledObjectPosition.Multiply(referenceSurfaceLocalTransform);

            Transform profileCurveLoopsTransform = Transform.CreateTranslation(originTrf.Origin);

            profileCurveLoopsTransform.BasisX = scaledReferenceSurfaceTransform.BasisZ;
            profileCurveLoopsTransform.BasisZ = originTrf.BasisX.Normalize();
            profileCurveLoopsTransform.BasisY = profileCurveLoopsTransform.BasisZ.CrossProduct(profileCurveLoopsTransform.BasisX);

            ISet <IList <CurveLoop> > profileCurveLoops = GetTransformedCurveLoops(profileCurveLoopsTransform, profileCurveLoopsTransform);

            if (profileCurveLoops == null || profileCurveLoops.Count == 0)
            {
                return(null);
            }

            SolidOptions           solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            IList <GeometryObject> myObjs       = new List <GeometryObject>();

            foreach (IList <CurveLoop> loops in profileCurveLoops)
            {
                GeometryObject myObj = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInLCS, 0, startParam, loops, solidOptions);
                if (myObj != null)
                {
                    myObjs.Add(myObj);
                }
            }

            return(myObjs);
        }
예제 #18
0
        /// <summary>
        /// Add curves to represent the plan view of the created object.
        /// </summary>
        /// <param name="curves">The list of curves, to be validated.</param>
        /// <param name="id">The id of the object being created, for error logging.</param>
        /// <returns>True if any curves were added to the plan view representation.</returns>
        public bool AddPlanViewCurves(IList <Curve> curves, int id)
        {
            ViewShapeBuilder = null;
            int numCurves = curves.Count;

            if (numCurves > 0)
            {
                ViewShapeBuilder = new ViewShapeBuilder(DirectShapeTargetViewType.Plan);

                IFCGeometryUtil.SplitUnboundCyclicCurves(curves);

                // Ideally we'd form these curves into a CurveLoop and get the Plane of the CurveLoop.  However, there is no requirement
                // that the plan view curves form one contiguous loop.
                foreach (Curve curve in curves)
                {
                    if (ViewShapeBuilder.ValidateCurve(curve))
                    {
                        ViewShapeBuilder.AddCurve(curve);
                    }
                    else
                    {
                        // We will move the origin to Z=0 if necessary, since the VSB requires all curves to be in the Z=0 plane.
                        // This only works if the curves are in a plane parallel to the Z=0 plane.
                        // NOTE: We could instead project the curves to the Z=0 plane, which could have the effect of changing their geometry.
                        // Until we see such cases, we will take the easier route here.
                        try
                        {
                            // If the end points aren't equal in Z, then the curve isn't parallel to Z.
                            bool isBound    = curve.IsBound;
                            XYZ  startPoint = isBound ? curve.GetEndPoint(0) : curve.Evaluate(0, false);
                            XYZ  endPoint   = isBound ? curve.GetEndPoint(1) : startPoint;
                            if (!MathUtil.IsAlmostEqual(startPoint.Z, endPoint.Z))
                            {
                                throw new InvalidOperationException("Non-planar curve in footprint representation.");
                            }

                            // Lines won't have a non-zero BasisZ value, so don't bother computing.
                            if (!(curve is Line))
                            {
                                Transform coordinatePlane = curve.ComputeDerivatives(0, true);
                                if (coordinatePlane != null && coordinatePlane.BasisZ != null && !coordinatePlane.BasisZ.IsZeroLength())
                                {
                                    XYZ normalizedZ = coordinatePlane.BasisZ.Normalize();
                                    if (!MathUtil.IsAlmostEqual(Math.Abs(normalizedZ.Z), 1.0))
                                    {
                                        throw new InvalidOperationException("Non-planar curve in footprint representation.");
                                    }
                                }
                            }

                            // We expect startPoint.Z to be non-zero, otherwise ValidateCurve would have accepted the curve in the first place.
                            Transform offsetTransform = Transform.CreateTranslation(-startPoint.Z * XYZ.BasisZ);
                            Curve     projectedCurve  = curve.CreateTransformed(offsetTransform);

                            // We may have missed a case above - for example, a curve whose end points have the same Z value, and whose normal at the
                            // start point is in +/-Z, but is regardless non-planar.  ValidateCurve has a final chance to reject such curves here.
                            if (projectedCurve == null || !ViewShapeBuilder.ValidateCurve(projectedCurve))
                            {
                                throw new InvalidOperationException("Invalid curve in footprint representation.");
                            }
                            ViewShapeBuilder.AddCurve(projectedCurve);
                            continue;
                        }
                        catch
                        {
                        }

                        Importer.TheLog.LogError(id, "Invalid curve in FootPrint representation, ignoring.", false);
                        numCurves--;
                    }
                }

                if (numCurves == 0)
                {
                    ViewShapeBuilder = null;
                }
            }

            return(ViewShapeBuilder != null);
        }
예제 #19
0
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>Zero or more created geometries.</returns>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            Transform sweptDiskPosition = (lcs == null) ? Transform.Identity : lcs;

            CurveLoop baseProfileCurve = Directrix.GetCurveLoop();

            if (baseProfileCurve == null)
            {
                return(null);
            }

            CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(baseProfileCurve, StartParameter, EndParameter);

            if (trimmedDirectrix == null)
            {
                return(null);
            }

            CurveLoop trimmedDirectrixInLCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, sweptDiskPosition);

            // Create the disk.
            Transform originTrf  = null;
            double    startParam = 0.0; // If the directrix isn't bound, this arbitrary parameter will do.

            foreach (Curve curve in trimmedDirectrixInLCS)
            {
                if (curve.IsBound)
                {
                    startParam = curve.GetEndParameter(0);
                }
                originTrf = curve.ComputeDerivatives(startParam, false);
                break;
            }

            if (originTrf == null)
            {
                return(null);
            }

            // The X-dir of the transform of the start of the directrix will form the normal of the disk.
            Plane diskPlane = new Plane(originTrf.BasisX, originTrf.Origin);

            IList <CurveLoop> profileCurveLoops = new List <CurveLoop>();

            CurveLoop diskOuterCurveLoop = new CurveLoop();

            diskOuterCurveLoop.Append(Arc.Create(diskPlane, Radius, 0, Math.PI));
            diskOuterCurveLoop.Append(Arc.Create(diskPlane, Radius, Math.PI, 2.0 * Math.PI));
            profileCurveLoops.Add(diskOuterCurveLoop);

            if (InnerRadius.HasValue)
            {
                CurveLoop diskInnerCurveLoop = new CurveLoop();
                diskInnerCurveLoop.Append(Arc.Create(diskPlane, InnerRadius.Value, 0, Math.PI));
                diskInnerCurveLoop.Append(Arc.Create(diskPlane, InnerRadius.Value, Math.PI, 2.0 * Math.PI));
                profileCurveLoops.Add(diskInnerCurveLoop);
            }

            SolidOptions solidOptions   = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            Solid        sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInLCS, 0, startParam, profileCurveLoops,
                                                                                        solidOptions);

            IList <GeometryObject> myObjs = new List <GeometryObject>();

            if (sweptDiskSolid != null)
            {
                myObjs.Add(sweptDiskSolid);
            }
            return(myObjs);
        }
예제 #20
0
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            Transform objectPosition = (lcs == null) ? Position : lcs.Multiply(Position);

            CurveLoop baseProfileCurve = Directrix.GetCurveLoop();

            if (baseProfileCurve == null)
            {
                return(null);
            }

            CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(baseProfileCurve, StartParameter, EndParameter);

            if (trimmedDirectrix == null)
            {
                return(null);
            }

            CurveLoop trimmedDirectrixInLCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, objectPosition);

            // Create the sweep.
            double    startParam = 0.0; // If the directrix isn't bound, this arbitrary parameter will do.
            Transform originTrf  = null;
            Curve     firstCurve = trimmedDirectrixInLCS.First();

            if (firstCurve.IsBound)
            {
                startParam = firstCurve.GetEndParameter(0);
            }
            originTrf = firstCurve.ComputeDerivatives(startParam, false);

            if (originTrf == null)
            {
                return(null);
            }

            Transform referenceSurfaceLocalTransform = ReferenceSurface.GetTransformAtPoint(originTrf.Origin);
            Transform referenceSurfaceTransform      = objectPosition.Multiply(referenceSurfaceLocalTransform);

            Transform profileCurveLoopsTransform = Transform.CreateTranslation(originTrf.Origin);

            profileCurveLoopsTransform.BasisX = referenceSurfaceTransform.BasisZ;
            profileCurveLoopsTransform.BasisZ = originTrf.BasisX.Normalize();
            profileCurveLoopsTransform.BasisY = profileCurveLoopsTransform.BasisZ.CrossProduct(profileCurveLoopsTransform.BasisX);

            ISet <IList <CurveLoop> > profileCurveLoops = GetTransformedCurveLoops(profileCurveLoopsTransform);

            if (profileCurveLoops == null || profileCurveLoops.Count == 0)
            {
                return(null);
            }

            SolidOptions           solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            IList <GeometryObject> myObjs       = new List <GeometryObject>();

            foreach (IList <CurveLoop> loops in profileCurveLoops)
            {
                GeometryObject myObj = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInLCS, 0, startParam, loops, solidOptions);
                if (myObj != null)
                {
                    myObjs.Add(myObj);
                }
            }

            return(myObjs);
        }
예제 #21
0
        private void CreateTessellatedShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform scaledLcs)
        {
            TessellatedShapeBuilderScope tsBuilderScope = shapeEditScope.BuilderScope as TessellatedShapeBuilderScope;

            if (tsBuilderScope == null)
            {
                throw new InvalidOperationException("Expect a TessellatedShapeBuilderScope, but get a BrepBuilderScope instead");
            }

            IList <XYZ> loopVertices = Bound.LoopVertices;
            int         count        = 0;

            if (loopVertices == null || ((count = loopVertices.Count) == 0))
            {
                throw new InvalidOperationException("#" + Id + ": missing loop vertices, ignoring.");
            }

            if (count < 3)
            {
                throw new InvalidOperationException("#" + Id + ": too few loop vertices (" + count + "), ignoring.");
            }

            if (!Orientation)
            {
                loopVertices.Reverse();
            }

            // Apply the transform
            IList <XYZ> transformedVertices = new List <XYZ>();

            foreach (XYZ vertex in loopVertices)
            {
                transformedVertices.Add(scaledLcs.OfPoint(vertex));
            }

            // Check that the loop vertices don't contain points that are very close to one another;
            // if so, throw the point away and hope that the TessellatedShapeBuilder can repair the result.
            // Warn in this case.  If the entire boundary is bad, report an error and don't add the loop vertices.

            IList <XYZ> validVertices;

            IFCGeometryUtil.CheckAnyDistanceVerticesWithinTolerance(Id, shapeEditScope, transformedVertices, out validVertices);

            // We are going to catch any exceptions if the loop is invalid.
            // We are going to hope that we can heal the parent object in the TessellatedShapeBuilder.
            bool bPotentiallyAbortFace = false;

            count = validVertices.Count;
            if (validVertices.Count < 3)
            {
                Importer.TheLog.LogComment(Id, "Too few distinct loop vertices (" + count + "), ignoring.", false);
                bPotentiallyAbortFace = true;
            }
            else
            {
                if (!tsBuilderScope.AddLoopVertices(Id, validVertices))
                {
                    bPotentiallyAbortFace = true;
                }
            }

            if (bPotentiallyAbortFace && IsOuter)
            {
                tsBuilderScope.AbortCurrentFace();
            }
        }
예제 #22
0
        /// <summary>
        /// Creates or populates Revit elements based on the information contained in this class.
        /// </summary>
        /// <param name="doc">The document.</param>
        protected override void Create(Document doc)
        {
            Transform lcs = (ObjectLocation != null) ? ObjectLocation.TotalTransform : Transform.Identity;

            if (ProductRepresentation != null)
            {
                if (ProductRepresentation.IsValid())
                {
                    using (IFCImportShapeEditScope shapeEditScope = IFCImportShapeEditScope.Create(doc, this))
                    {
                        shapeEditScope.GraphicsStyleId = m_GraphicsStyleId;
                        shapeEditScope.CategoryId      = CategoryId;

                        // The name can be added as well. but it is usually less useful than 'oid'
                        string myId = GlobalId; // + "(" + Name + ")";

                        ProductRepresentation.CreateProductRepresentation(shapeEditScope, lcs, lcs, myId);

                        int numSolids = Solids.Count;
                        int numVoids  = Voids.Count;
                        if ((numSolids > 0) && (numVoids > 0))
                        {
                            // We may have some GeometryInstances.  These need to be "exploded" to do the cutting.
                            for (int solidIdx = 0; solidIdx < numSolids; solidIdx++)
                            {
                                if (Solids[solidIdx].GeometryObject is GeometryInstance)
                                {
                                    //// This code currently doesn't work, so commented out.
                                    //GeometryInstance geomInst = Solids[solidIdx].GeometryObject as GeometryInstance;
                                    //GeometryElement geomElem = geomInst.GetInstanceGeometry();

                                    //foreach (GeometryObject geomObj in geomElem)
                                    //{
                                    //if (geomObj is Solid)
                                    //Solids.Add(IFCSolidInfo.Create(Solids[solidIdx].Id, geomObj as Solid));
                                    //else if (geomObj is Mesh)
                                    //Solids.Add(IFCSolidInfo.Create(Solids[solidIdx].Id, geomObj as Mesh));
                                    //else if (geomObj is GeometryInstance)
                                    //IFCImportFile.TheLog.LogError(Solids[solidIdx].Id, "Can't cut nested mapped items, ignoring " + numVoids + " void(s).", false);

                                    // Other items are irrelevant here.
                                    //}

                                    //Solids.RemoveAt(solidIdx);
                                    //solidIdx--;
                                    //numSolids--;
                                }
                            }

                            // This may be different than before, with the addition of solids from FamilyInstances.
                            numSolids = Solids.Count;

                            // Attempt to cut each solid with each void.
                            for (int solidIdx = 0; solidIdx < numSolids; solidIdx++)
                            {
                                if (!(Solids[solidIdx].GeometryObject is Solid))
                                {
                                    // Assume that we only deal with solids, meshes and instances.
                                    string typeName = (Solids[solidIdx].GeometryObject is Mesh) ? "mesh" : "instance";
                                    IFCImportFile.TheLog.LogError(Id, "Can't cut " + typeName + " geometry, ignoring " + numVoids + " void(s).", false);
                                    continue;
                                }

                                for (int voidIdx = 0; voidIdx < numVoids; voidIdx++)
                                {
                                    if (!(Voids[voidIdx].GeometryObject is Solid))
                                    {
                                        IFCImportFile.TheLog.LogError(Id, "Can't cut Solid geometry with a Mesh (# " + Voids[voidIdx].Id + "), ignoring.", false);
                                        continue;
                                    }

                                    Solids[solidIdx].GeometryObject =
                                        IFCGeometryUtil.ExecuteSafeBooleanOperation(Solids[solidIdx].Id, Voids[voidIdx].Id,
                                                                                    Solids[solidIdx].GeometryObject as Solid, Voids[voidIdx].GeometryObject as Solid,
                                                                                    BooleanOperationsType.Difference);
                                    if ((Solids[solidIdx].GeometryObject as Solid).Faces.IsEmpty)
                                    {
                                        Solids.RemoveAt(solidIdx);
                                        solidIdx--;
                                        numSolids--;
                                        break;
                                    }
                                }
                            }
                        }

                        bool addedCurves = shapeEditScope.AddPlanViewCurves(FootprintCurves, Id);

                        if ((numSolids > 0 || addedCurves))
                        {
                            if (GlobalId != null)
                            {
                                // If the GlobalId is null, this is a fake IfcProduct that we don't want to create into a DirectShape, or
                                // add to the caches in any way.  We only wanted to gather its geometry.
                                DirectShape shape = Importer.TheCache.UseElementByGUID <DirectShape>(doc, GlobalId);

                                if (shape == null)
                                {
                                    shape = IFCElementUtil.CreateElement(doc, CategoryId, Importer.ImportAppGUID(), GlobalId);
                                }

                                List <GeometryObject> directShapeGeometries = new List <GeometryObject>();
                                foreach (IFCSolidInfo geometryObject in Solids)
                                {
                                    // We need to check if the solid created is good enough for DirectShape.  If not, warn and use a fallback Mesh.
                                    GeometryObject currObject = geometryObject.GeometryObject;
                                    if (currObject is Solid)
                                    {
                                        Solid solid = currObject as Solid;
                                        if (!shape.IsValidGeometry(solid))
                                        {
                                            IFCImportFile.TheLog.LogWarning(Id, "Couldn't create valid solid, reverting to mesh.", false);
                                            directShapeGeometries.AddRange(IFCGeometryUtil.CreateMeshesFromSolid(solid));
                                            currObject = null;
                                        }
                                    }

                                    if (currObject != null)
                                    {
                                        directShapeGeometries.Add(currObject);
                                    }
                                }

                                // We will use the first IfcTypeObject id, if it exists.  In general, there should be 0 or 1.
                                ElementId typeId = ElementId.InvalidElementId;
                                foreach (IFCTypeObject typeObject in TypeObjects)
                                {
                                    if (typeObject.IsValidForCreation && typeObject.CreatedElementId != ElementId.InvalidElementId)
                                    {
                                        typeId = typeObject.CreatedElementId;
                                        break;
                                    }
                                }

                                shape.SetShape(directShapeGeometries);
                                shapeEditScope.SetPlanViewRep(shape);

                                if (typeId != ElementId.InvalidElementId)
                                {
                                    shape.SetTypeId(typeId);
                                }

                                PresentationLayerNames.UnionWith(shapeEditScope.PresentationLayerNames);
                                m_CreatedElementId = shape.Id;
                            }
                        }
                    }
                }
                else
                {
                    IFCImportFile.TheLog.LogWarning(Id, "There is no valid geometry for this " + EntityType.ToString() + "; entity will not be built.", false);
                }
            }

            base.Create(doc);
        }
예제 #23
0
        /// <summary>
        /// Cut a IFCSolidInfo by the voids in this IFCProduct, if any.
        /// </summary>
        /// <param name="solidInfo">The solid information.</param>
        /// <returns>False if the return solid is empty; true otherwise.</returns>
        protected override bool CutSolidByVoids(IFCSolidInfo solidInfo)
        {
            // We only cut "Body" representation items.
            if (solidInfo.RepresentationType != IFCRepresentationIdentifier.Body)
            {
                return(true);
            }

            IList <IFCVoidInfo> voidsToUse = null;
            List <IFCVoidInfo>  partVoids  = null;

            IList <IFCVoidInfo> parentVoids = (Decomposes as IFCProduct)?.Voids;

            if (parentVoids != null)
            {
                partVoids = new List <IFCVoidInfo>();
                partVoids.AddRange(Voids);
                partVoids.AddRange(parentVoids);
                voidsToUse = partVoids;
            }
            else
            {
                voidsToUse = Voids;
            }

            int numVoids = voidsToUse.Count;

            if (numVoids == 0)
            {
                return(true);
            }

            if (!(solidInfo.GeometryObject is Solid))
            {
                string typeName = (solidInfo.GeometryObject is Mesh) ? "mesh" : "instance";
                Importer.TheLog.LogError(Id, "Can't cut " + typeName + " geometry, ignoring " + numVoids + " void(s).", false);
                return(true);
            }

            foreach (IFCVoidInfo voidInfo in voidsToUse)
            {
                Solid voidObject = voidInfo.GeometryObject as Solid;
                if (voidObject == null)
                {
                    Importer.TheLog.LogError(Id, "Can't cut Solid geometry with a Mesh (# " + voidInfo.Id + "), ignoring.", false);
                    continue;
                }

                var voidTransform = voidInfo.TotalTransform;

                if (voidTransform != null && voidTransform.IsIdentity == false)
                {
                    // Transform the void into the space of the solid.
                    var t = ObjectLocation.TotalTransform.Inverse.Multiply(voidTransform);
                    voidObject = SolidUtils.CreateTransformed(voidObject, t);
                }

                solidInfo.GeometryObject = IFCGeometryUtil.ExecuteSafeBooleanOperation(solidInfo.Id, voidInfo.Id,
                                                                                       (solidInfo.GeometryObject as Solid), voidObject, BooleanOperationsType.Difference, null);

                if (solidInfo.GeometryObject == null || (solidInfo.GeometryObject as Solid).Faces.IsEmpty)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #24
0
        /// <summary>
        /// Create geometry for an IfcHalfSpaceSolid.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>A list containing one geometry for the IfcHalfSpaceSolid.</returns>
        protected virtual IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs, Transform scaledLcs, string guid)
        {
            IFCPlane ifcPlane = BaseSurface as IFCPlane;
            Plane    plane    = ifcPlane.Plane;
            XYZ      origin   = plane.Origin;
            XYZ      xVec     = plane.XVec;
            XYZ      yVec     = plane.YVec;

            // Set some huge boundaries for now.
            const double largeCoordinateValue = 100000;

            XYZ[] corners = new XYZ[4] {
                unscaledLcs.OfPoint((xVec * -largeCoordinateValue) + (yVec * -largeCoordinateValue) + origin),
                unscaledLcs.OfPoint((xVec * largeCoordinateValue) + (yVec * -largeCoordinateValue) + origin),
                unscaledLcs.OfPoint((xVec * largeCoordinateValue) + (yVec * largeCoordinateValue) + origin),
                unscaledLcs.OfPoint((xVec * -largeCoordinateValue) + (yVec * largeCoordinateValue) + origin)
            };

            IList <CurveLoop> loops = new List <CurveLoop>();
            CurveLoop         loop  = new CurveLoop();

            for (int ii = 0; ii < 4; ii++)
            {
                if (AgreementFlag)
                {
                    loop.Append(Line.CreateBound(corners[(5 - ii) % 4], corners[(4 - ii) % 4]));
                }
                else
                {
                    loop.Append(Line.CreateBound(corners[ii], corners[(ii + 1) % 4]));
                }
            }
            loops.Add(loop);

            XYZ          normal       = unscaledLcs.OfVector(AgreementFlag ? -plane.Normal : plane.Normal);
            SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            Solid        baseSolid    = GeometryCreationUtilities.CreateExtrusionGeometry(loops, normal, largeCoordinateValue, solidOptions);

            if (BaseBoundingCurve != null)
            {
                CurveLoop polygonalBoundary = BaseBoundingCurve.CurveLoop;

                Transform unscaledTotalTransform = unscaledLcs.Multiply(BaseBoundingCurveTransform);
                Transform scaledTotalTransform   = scaledLcs.Multiply(BaseBoundingCurveTransform);

                // Make sure this bounding polygon extends below base of half-space soild.
                Transform moveBaseTransform = Transform.Identity;
                moveBaseTransform.Origin = new XYZ(0, 0, -largeCoordinateValue);

                unscaledTotalTransform = unscaledTotalTransform.Multiply(moveBaseTransform);
                scaledTotalTransform   = scaledTotalTransform.Multiply(moveBaseTransform);

                CurveLoop         transformedPolygonalBoundary = IFCGeometryUtil.CreateTransformed(polygonalBoundary, Id, unscaledTotalTransform, scaledTotalTransform);
                IList <CurveLoop> boundingLoops = new List <CurveLoop>();
                boundingLoops.Add(transformedPolygonalBoundary);

                Solid boundingSolid = GeometryCreationUtilities.CreateExtrusionGeometry(boundingLoops, unscaledTotalTransform.BasisZ, 2.0 * largeCoordinateValue,
                                                                                        solidOptions);
                baseSolid = IFCGeometryUtil.ExecuteSafeBooleanOperation(Id, BaseBoundingCurve.Id, baseSolid, boundingSolid, BooleanOperationsType.Intersect, null);
            }

            IList <GeometryObject> returnList = new List <GeometryObject>();

            returnList.Add(baseSolid);
            return(returnList);
        }
예제 #25
0
        /// <summary>
        /// Creates or populates Revit elements based on the information contained in this class.
        /// </summary>
        /// <param name="doc">The document.</param>
        protected override void Create(Document doc)
        {
            bool       preventInstances = false;
            IFCElement element          = this as IFCElement;

            if (element != null)
            {
                preventInstances = this is IFCOpeningElement;
                foreach (IFCFeatureElement opening in element.Openings)
                {
                    try
                    {
                        preventInstances = true;
                        // Create the actual Revit element based on the IFCFeatureElement here.
                        ElementId openingId = CreateElement(doc, opening);

                        // This gets around the issue that the Boolean operation between the void(s) in the IFCFeatureElement and
                        // the solid(s) in the IFCElement may use the Graphics Style of the voids in the resulting Solid(s), meaning
                        // that some faces may disappear when we turn off the visibility of IfcOpeningElements.
                        IList <IFCSolidInfo> voids = IFCElement.CloneElementGeometry(doc, opening, this, true);
                        if (voids != null)
                        {
                            foreach (IFCSolidInfo voidGeom in voids)
                            {
                                IFCVoidInfo voidInfo = new IFCVoidInfo(voidGeom);
                                if (!Importer.TheProcessor.ApplyTransforms)
                                {
                                    // If we aren't applying transforms, then the Voids and Solids will be
                                    // in different coordinate spaces, so we need the transform of the
                                    // void, so we can transform it into the Solid coordinate space
                                    voidInfo.TotalTransform = opening?.ObjectLocation?.TotalTransform;
                                }

                                Voids.Add(voidInfo);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Importer.TheLog.LogError(opening.Id, ex.Message, false);
                    }
                }
            }
            if (HasValidTopLevelGeometry())
            {
                using (IFCImportShapeEditScope shapeEditScope = IFCImportShapeEditScope.Create(doc, this))
                {
                    shapeEditScope.GraphicsStyleId  = GraphicsStyleId;
                    shapeEditScope.CategoryId       = CategoryId;
                    shapeEditScope.PreventInstances = preventInstances;

                    // The name can be added as well. but it is usually less useful than 'oid'
                    string myId = GlobalId; // + "(" + Name + ")";

                    Transform lcs = IFCImportFile.TheFile.IFCProject.WorldCoordinateSystem;
                    if (lcs == null)
                    {
                        lcs = (ObjectLocation != null) ? ObjectLocation.TotalTransform : Transform.Identity;
                    }
                    else if (ObjectLocation != null)
                    {
                        lcs = lcs.Multiply(ObjectLocation.TotalTransform);
                    }

                    // If we are not applying transforms to the geometry, then pass in the identity matrix.
                    // Lower down this method we then pass lcs to the consumer element, so that it can apply
                    // the transform as required.
                    Transform transformToUse = Importer.TheProcessor.ApplyTransforms ? lcs : Transform.Identity;
                    ProductRepresentation.CreateProductRepresentation(shapeEditScope, transformToUse, transformToUse, myId);

                    int numSolids = Solids.Count;
                    // Attempt to cut each solid with each void.
                    for (int solidIdx = 0; solidIdx < numSolids; solidIdx++)
                    {
                        if (!CutSolidByVoids(Solids[solidIdx]))
                        {
                            Solids.RemoveAt(solidIdx);
                            solidIdx--;
                            numSolids--;
                        }
                    }

                    bool addedCurves = shapeEditScope.AddPlanViewCurves(FootprintCurves, Id);

                    if ((numSolids > 0 || addedCurves))
                    {
                        if (GlobalId != null)
                        {
                            // If the GlobalId is null, this is a fake IfcProduct that we don't want to create into a DirectShape, or
                            // add to the caches in any way.  We only wanted to gather its geometry.
                            DirectShape shape = Importer.TheCache.UseElementByGUID <DirectShape>(doc, GlobalId);

                            if (shape == null)
                            {
                                shape = IFCElementUtil.CreateElement(doc, CategoryId, GlobalId, null, Id, EntityType);
                            }

                            List <GeometryObject> directShapeGeometries = new List <GeometryObject>();
                            foreach (IFCSolidInfo geometryObject in Solids)
                            {
                                // We need to check if the solid created is good enough for DirectShape.  If not, warn and use a fallback Mesh.
                                GeometryObject currObject = geometryObject.GeometryObject;
                                if (currObject is Solid)
                                {
                                    Solid solid = currObject as Solid;
                                    if (!shape.IsValidGeometry(solid))
                                    {
                                        Importer.TheLog.LogWarning(Id, "Couldn't create valid solid, reverting to mesh.", false);
                                        directShapeGeometries.AddRange(IFCGeometryUtil.CreateMeshesFromSolid(solid));
                                        currObject = null;
                                    }
                                }

                                if (currObject != null)
                                {
                                    directShapeGeometries.Add(currObject);
                                }
                            }

                            // We will use the first IfcTypeObject id, if it exists.  In general, there should be 0 or 1.
                            IFCTypeObject typeObjectToUse = null;
                            foreach (IFCTypeObject typeObject in TypeObjects)
                            {
                                if (typeObject.IsValidForCreation && typeObject.CreatedElementId != ElementId.InvalidElementId)
                                {
                                    typeObjectToUse = typeObject;
                                    break;
                                }
                            }

                            if (!Importer.TheProcessor.PostProcessProduct(Id, typeObjectToUse?.Id, lcs,
                                                                          directShapeGeometries))
                            {
                                if (shape != null)
                                {
                                    shape.SetShape(directShapeGeometries);
                                    shapeEditScope.SetPlanViewRep(shape);

                                    if (typeObjectToUse != null && typeObjectToUse.CreatedElementId != ElementId.InvalidElementId)
                                    {
                                        shape.SetTypeId(typeObjectToUse.CreatedElementId);
                                    }
                                }
                            }

                            PresentationLayerNames.UnionWith(shapeEditScope.PresentationLayerNames);

                            CreatedElementId = shape.Id;
                            CreatedGeometry  = directShapeGeometries;
                        }
                    }
                }
            }
            else
            {
                if (this is IFCElement || this is IFCGrid)
                {
                    IList <IFCEntity> visitedEntities = new List <IFCEntity>();
                    visitedEntities.Add(this);
                    if (!HasValidSubElementGeometry(visitedEntities))
                    {
                        // We will not warn if this is an IfcSpatialStructureElement; those aren't expected to have their own geometry.
                        Importer.TheLog.LogWarning(Id, "There is no valid geometry for this " + EntityType.ToString() + "; entity will not be built.", false);
                    }
                }
            }

            base.Create(doc);
        }
예제 #26
0
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        public IList <GeometryObject> CreateGeometry(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            IList <GeometryObject> firstSolids = FirstOperand.CreateGeometry(shapeEditScope, lcs, scaledLcs, guid);

            if (firstSolids != null)
            {
                foreach (GeometryObject potentialSolid in firstSolids)
                {
                    if (!(potentialSolid is Solid))
                    {
                        IFCImportFile.TheLog.LogError((FirstOperand as IFCRepresentationItem).Id, "Can't perform Boolean operation on a Mesh.", false);
                        return(firstSolids);
                    }
                }
            }

            IList <GeometryObject> secondSolids = null;

            if (SecondOperand != null)
            {
                try
                {
                    using (IFCImportShapeEditScope.IFCTargetSetter setter =
                               new IFCImportShapeEditScope.IFCTargetSetter(shapeEditScope, TessellatedShapeBuilderTarget.Solid, TessellatedShapeBuilderFallback.Abort))
                    {
                        secondSolids = SecondOperand.CreateGeometry(shapeEditScope, lcs, scaledLcs, guid);
                    }
                }
                catch (Exception ex)
                {
                    // We will allow something to be imported, in the case where the second operand is invalid.
                    // If the first (base) operand is invalid, we will still fail the import of this solid.
                    if (SecondOperand is IFCRepresentationItem)
                    {
                        IFCImportFile.TheLog.LogError((SecondOperand as IFCRepresentationItem).Id, ex.Message, false);
                    }
                    else
                    {
                        throw ex;
                    }
                    secondSolids = null;
                }
            }

            IList <GeometryObject> resultSolids = null;

            if (firstSolids == null)
            {
                resultSolids = secondSolids;
            }
            else if (secondSolids == null)
            {
                resultSolids = firstSolids;
            }
            else
            {
                BooleanOperationsType booleanOperationsType = BooleanOperationsType.Difference;
                switch (BooleanOperator)
                {
                case IFCBooleanOperator.Difference:
                    booleanOperationsType = BooleanOperationsType.Difference;
                    break;

                case IFCBooleanOperator.Intersection:
                    booleanOperationsType = BooleanOperationsType.Intersect;
                    break;

                case IFCBooleanOperator.Union:
                    booleanOperationsType = BooleanOperationsType.Union;
                    break;

                default:
                    IFCImportFile.TheLog.LogError(Id, "Invalid BooleanOperationsType.", true);
                    break;
                }

                resultSolids = new List <GeometryObject>();
                foreach (GeometryObject firstSolid in firstSolids)
                {
                    Solid resultSolid = (firstSolid as Solid);

                    int secondId = (SecondOperand == null) ? -1 : (SecondOperand as IFCRepresentationItem).Id;
                    foreach (GeometryObject secondSolid in secondSolids)
                    {
                        resultSolid = IFCGeometryUtil.ExecuteSafeBooleanOperation(Id, secondId, resultSolid, secondSolid as Solid, booleanOperationsType);
                        if (resultSolid == null)
                        {
                            break;
                        }
                    }

                    if (resultSolid != null)
                    {
                        resultSolids.Add(resultSolid);
                    }
                }
            }

            return(resultSolids);
        }
예제 #27
0
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        public IList <GeometryObject> CreateGeometry(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            IList <GeometryObject> firstSolids = FirstOperand.CreateGeometry(shapeEditScope, lcs, scaledLcs, guid);

            if (firstSolids != null)
            {
                foreach (GeometryObject potentialSolid in firstSolids)
                {
                    if (!(potentialSolid is Solid))
                    {
                        Importer.TheLog.LogError((FirstOperand as IFCRepresentationItem).Id, "Can't perform Boolean operation on a Mesh.", false);
                        return(firstSolids);
                    }
                }
            }

            IList <GeometryObject> secondSolids = null;

            if (SecondOperand != null)
            {
                try
                {
                    using (IFCImportShapeEditScope.BuildPreferenceSetter setter =
                               new IFCImportShapeEditScope.BuildPreferenceSetter(shapeEditScope, IFCImportShapeEditScope.BuildPreferenceType.ForceSolid))
                    {
                        // Before we process the second operand, we are going to see if there is a uniform material set for the first operand
                        // (corresponding to the solid in the Boolean operation).  We will try to suggest the same material for the voids to avoid arbitrary
                        // setting of material information for the cut faces.
                        IFCStyledItem firstOperandStyledItem = GetStyledItemFromOperand(FirstOperand as IFCRepresentationItem);
                        using (IFCImportShapeEditScope.IFCMaterialStack stack =
                                   new IFCImportShapeEditScope.IFCMaterialStack(shapeEditScope, firstOperandStyledItem, null))
                        {
                            secondSolids = SecondOperand.CreateGeometry(shapeEditScope, lcs, scaledLcs, guid);
                        }
                    }
                }
                catch (Exception ex)
                {
                    // We will allow something to be imported, in the case where the second operand is invalid.
                    // If the first (base) operand is invalid, we will still fail the import of this solid.
                    if (SecondOperand is IFCRepresentationItem)
                    {
                        Importer.TheLog.LogError((SecondOperand as IFCRepresentationItem).Id, ex.Message, false);
                    }
                    else
                    {
                        throw ex;
                    }
                    secondSolids = null;
                }
            }

            IList <GeometryObject> resultSolids = null;

            if (firstSolids == null)
            {
                resultSolids = secondSolids;
            }
            else if (secondSolids == null || BooleanOperator == null)
            {
                if (BooleanOperator == null)
                {
                    Importer.TheLog.LogError(Id, "Invalid BooleanOperationsType.", false);
                }
                resultSolids = firstSolids;
            }
            else
            {
                BooleanOperationsType booleanOperationsType = BooleanOperationsType.Difference;
                switch (BooleanOperator)
                {
                case IFCBooleanOperator.Difference:
                    booleanOperationsType = BooleanOperationsType.Difference;
                    break;

                case IFCBooleanOperator.Intersection:
                    booleanOperationsType = BooleanOperationsType.Intersect;
                    break;

                case IFCBooleanOperator.Union:
                    booleanOperationsType = BooleanOperationsType.Union;
                    break;

                default:
                    Importer.TheLog.LogError(Id, "Invalid BooleanOperationsType.", true);
                    break;
                }

                resultSolids = new List <GeometryObject>();
                foreach (GeometryObject firstSolid in firstSolids)
                {
                    Solid resultSolid = (firstSolid as Solid);

                    int secondId = (SecondOperand == null) ? -1 : (SecondOperand as IFCRepresentationItem).Id;
                    XYZ suggestedShiftDirection = (SecondOperand == null) ? null : SecondOperand.GetSuggestedShiftDirection(lcs);
                    foreach (GeometryObject secondSolid in secondSolids)
                    {
                        resultSolid = IFCGeometryUtil.ExecuteSafeBooleanOperation(Id, secondId, resultSolid, secondSolid as Solid, booleanOperationsType, suggestedShiftDirection);
                        if (resultSolid == null)
                        {
                            break;
                        }
                    }

                    if (resultSolid != null)
                    {
                        resultSolids.Add(resultSolid);
                    }
                }
            }

            return(resultSolids);
        }
예제 #28
0
        protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder))
            {
                base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid);

                TessellatedShapeBuilderScope tsBuilderScope = bs as TessellatedShapeBuilderScope;

                tsBuilderScope.StartCollectingFaceSet();

                // Create the face set from IFCIndexedPolygonalFace
                foreach (IFCIndexedPolygonalFace face in Faces)
                {
                    // TODO: Consider adding ability to triangulate here.
                    tsBuilderScope.StartCollectingFace(GetMaterialElementId(shapeEditScope), false);

                    IList <XYZ> loopVertices = new List <XYZ>();
                    foreach (int vertInd in face.CoordIndex)
                    {
                        int actualVIdx = vertInd - 1; // IFC starts the list position at 1
                        if (PnIndex != null)
                        {
                            actualVIdx = PnIndex[actualVIdx] - 1;
                        }
                        XYZ vertex = Coordinates.CoordList[actualVIdx];
                        loopVertices.Add(scaledLcs.OfPoint(vertex));
                    }
                    List <XYZ> validVertices;
                    IFCGeometryUtil.CheckAnyDistanceVerticesWithinTolerance(Id, shapeEditScope, loopVertices, out validVertices);

                    bool bPotentiallyAbortFace = false;
                    if (!tsBuilderScope.AddLoopVertices(Id, validVertices))
                    {
                        bPotentiallyAbortFace = true;
                    }

                    // Handle holes
                    if (face.InnerCoordIndices != null)
                    {
                        foreach (IList <int> innerLoop in face.InnerCoordIndices)
                        {
                            IList <XYZ> innerLoopVertices = new List <XYZ>();
                            foreach (int innerVerIdx in innerLoop)
                            {
                                int actualVIdx = innerVerIdx - 1;
                                if (PnIndex != null)
                                {
                                    actualVIdx = PnIndex[actualVIdx] - 1;
                                }
                                XYZ vertex = Coordinates.CoordList[actualVIdx];
                                // add vertex to the loop
                                innerLoopVertices.Add(scaledLcs.OfPoint(vertex));
                            }
                            List <XYZ> validInnerV;
                            IFCGeometryUtil.CheckAnyDistanceVerticesWithinTolerance(Id, shapeEditScope, innerLoopVertices, out validInnerV);

                            if (!tsBuilderScope.AddLoopVertices(Id, validInnerV))
                            {
                                bPotentiallyAbortFace = true;
                            }
                        }
                    }

                    tsBuilderScope.StopCollectingFace(!bPotentiallyAbortFace, false);
                }

                IList <GeometryObject> createdGeometries = tsBuilderScope.CreateGeometry(guid);
                if (createdGeometries != null)
                {
                    foreach (GeometryObject createdGeometry in createdGeometries)
                    {
                        shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, createdGeometry));
                    }
                }
            }
        }
예제 #29
0
        /// <summary>
        /// Perform end of import/link cleanup.
        /// </summary>
        /// <param name="doc">The document.</param>
        /// <param name="fileName">The full path of the original IFC file.</param>
        public void EndImport(Document doc, string fileName)
        {
            // Remove an unupdated Elements as a result of a reload operation.
            try
            {
                // We are working around a limitation in deleting unused DirectShapeTypes.
                IList <ElementId> otherElementsToDelete = new List <ElementId>();
                IList <ElementId> typesToDelete         = new List <ElementId>();

                foreach (ElementId elementId in Importer.TheCache.GUIDToElementMap.Values)
                {
                    if (DontDeleteSpecialElement(elementId))
                    {
                        continue;
                    }

                    Element element = doc.GetElement(elementId);
                    if (element == null)
                    {
                        continue;
                    }

                    if (element is DirectShapeType)
                    {
                        typesToDelete.Add(elementId);
                    }
                    else
                    {
                        otherElementsToDelete.Add(elementId);
                    }
                }

                foreach (ElementId elementId in Importer.TheCache.GridNameToElementMap.Values)
                {
                    Element element = doc.GetElement(elementId);
                    if (element == null)
                    {
                        continue;
                    }

                    otherElementsToDelete.Add(elementId);
                }

                // Don't expect this to fail.
                try
                {
                    if (otherElementsToDelete.Count > 0)
                    {
                        doc.Delete(otherElementsToDelete);
                    }
                }
                catch (Exception ex)
                {
                    Importer.TheLog.LogError(-1, ex.Message, false);
                }

                // Delete the temporary element we used for validation purposes.
                IFCGeometryUtil.DeleteSolidValidator();

                // This might fail.
                if (typesToDelete.Count > 0)
                {
                    doc.Delete(typesToDelete);
                }

                UpdateDocumentFileMetrics(doc, fileName);
            }
            catch // (Exception ex)
            {
                // Catch, but don't report, since this is an internal limitation in the API.
                //TheLog.LogError(-1, ex.Message, false);
            }

            if (m_Transaction != null)
            {
                m_Transaction.Commit();
            }
        }
예제 #30
0
        protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder))
            {
                base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid);

                TessellatedShapeBuilderScope tsBuilderScope = bs as TessellatedShapeBuilderScope;

                tsBuilderScope.StartCollectingFaceSet();

                // Create triangle face set from CoordIndex. We do not support the Normals yet at this point
                foreach (List <int> triIndex in CoordIndex)
                {
                    // This is a defensive check in an unlikely situation that the index is larger than the data
                    if (triIndex[0] > Coordinates.CoordList.Count || triIndex[1] > Coordinates.CoordList.Count || triIndex[2] > Coordinates.CoordList.Count)
                    {
                        continue;
                    }

                    tsBuilderScope.StartCollectingFace(GetMaterialElementId(shapeEditScope));

                    IList <XYZ> loopVertices = new List <XYZ>();

                    for (int ii = 0; ii < 3; ++ii)
                    {
                        int actualVIdx = triIndex[ii] - 1;
                        if (PnIndex != null)
                        {
                            actualVIdx = PnIndex[actualVIdx] - 1;
                        }
                        IList <double> v = Coordinates.CoordList[actualVIdx];
                        loopVertices.Add(new XYZ(v[0], v[1], v[2]));
                    }

                    IList <XYZ> transformedVertices = new List <XYZ>();
                    foreach (XYZ vertex in loopVertices)
                    {
                        // Need to apply the project unit scaling here
                        XYZ scaledVertex = applyProjectUnitScaleVertex(vertex);
                        transformedVertices.Add(scaledLcs.OfPoint(scaledVertex));
                    }

                    // Check triangle that is too narrow (2 vertices are within the tolerance
                    IList <XYZ> validVertices;
                    IFCGeometryUtil.CheckAnyDistanceVerticesWithinTolerance(Id, shapeEditScope, transformedVertices, out validVertices);

                    // We are going to catch any exceptions if the loop is invalid.
                    // We are going to hope that we can heal the parent object in the TessellatedShapeBuilder.
                    bool bPotentiallyAbortFace = false;

                    int count = validVertices.Count;
                    if (validVertices.Count < 3)
                    {
                        Importer.TheLog.LogComment(Id, "Too few distinct loop vertices (" + count + "), ignoring.", false);
                        bPotentiallyAbortFace = true;
                    }
                    else
                    {
                        if (!tsBuilderScope.AddLoopVertices(Id, validVertices))
                        {
                            bPotentiallyAbortFace = true;
                        }
                    }

                    if (bPotentiallyAbortFace)
                    {
                        tsBuilderScope.AbortCurrentFace();
                    }
                    else
                    {
                        tsBuilderScope.StopCollectingFace();
                    }
                }

                IList <GeometryObject> createdGeometries = tsBuilderScope.CreateGeometry(guid);
                if (createdGeometries != null)
                {
                    foreach (GeometryObject createdGeometry in createdGeometries)
                    {
                        shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, createdGeometry));
                    }
                }
            }
        }