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);
        }
Example #2
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);
        }
        /// <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);
        }
        /// <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);
        }
Example #5
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);
        }
Example #6
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);
        }
Example #7
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)
        {
            List <GeometryObject> myObjs = null;

            if (scaledLcs == null || scaledLcs.IsConformal && MathUtil.IsAlmostEqual(scaledLcs.Scale, 1.0))
            {
                myObjs = CreateConformalGeometryIfPossible(shapeEditScope, unscaledLcs);
                if (myObjs != null)
                {
                    return(myObjs);
                }
            }

            Transform unscaledSweptDiskPosition = (unscaledLcs == null) ? Transform.Identity : unscaledLcs;
            Transform scaledSweptDiskPosition   = (scaledLcs == null) ? Transform.Identity : scaledLcs;

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

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

            foreach (CurveLoop trimmedDirectrix in trimmedDirectrices)
            {
                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);
                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") || ex.Message.Contains("Failed to create"))
                    {
                        (IList <GeometryObject>, bool)solidSegments = SplitSweptDiskIntoValidPieces(trimmedDirectrixInWCS, profileCurveLoops, solidOptions);
                        if (solidSegments.Item1 != null)
                        {
                            myObjs.AddRange(solidSegments.Item1);
                        }

                        // If Item2 is true, that means that the backup SplitSweptDiskIntoValidPieces routine was
                        // able to create (probably slightly self-intersecting) geometry for all of the pieces
                        // of the directrix.  If it is false, then there was some part of the directrix that we
                        // couldn't create geometry for.  Log a warning in the first case and an error in the
                        // second.
                        if (solidSegments.Item2)
                        {
                            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);
                        }
                        else
                        {
                            Importer.TheLog.LogError(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 as much of the geometry as possible.", false);
                        }
                    }
                    else
                    {
                        throw ex;
                    }
                }
            }

            return(myObjs);
        }