예제 #1
0
        /// <summary>
        /// Creates or updates the IfcLocalPlacement associated with the current origin offset.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="bbox">The bounding box.</param>
        /// <param name="ecData">The extrusion creation data which contains the local placement.</param>
        /// <param name="lpOrig">The local placement origin.</param>
        /// <param name="unscaledTrfOrig">The unscaled local placement origin.</param>
        public void CreateLocalPlacementFromOffset(ExporterIFC exporterIFC, BoundingBoxXYZ bbox, IFCExtrusionCreationData ecData, XYZ lpOrig, XYZ unscaledTrfOrig)
        {
            if (ecData == null)
            {
                return;
            }

            IFCAnyHandle localPlacement = ecData.GetLocalPlacement();

            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(localPlacement))
            {
                IFCFile file = exporterIFC.GetFile();

                // If the BBox passes through (0,0, 0), or no bbox, do nothing.
                if (bbox == null ||
                    ((bbox.Min.X < MathUtil.Eps() && bbox.Max.X > -MathUtil.Eps()) &&
                     (bbox.Min.Y < MathUtil.Eps() && bbox.Max.Y > -MathUtil.Eps()) &&
                     (bbox.Min.Z < MathUtil.Eps() && bbox.Max.Z > -MathUtil.Eps())))
                {
                    if (!ecData.ReuseLocalPlacement)
                    {
                        ecData.SetLocalPlacement(ExporterUtil.CopyLocalPlacement(file, localPlacement));
                    }
                    return;
                }

                if (!MathUtil.IsAlmostZero(unscaledTrfOrig.DotProduct(unscaledTrfOrig)))
                {
                    if (!ecData.ReuseLocalPlacement)
                    {
                        ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, lpOrig, null, null));
                    }
                    else
                    {
                        IFCAnyHandle relativePlacement = GeometryUtil.GetRelativePlacementFromLocalPlacement(localPlacement);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(relativePlacement))
                        {
                            IFCAnyHandle newRelativePlacement = ExporterUtil.CreateAxis(file, lpOrig, null, null);
                            GeometryUtil.SetRelativePlacement(localPlacement, newRelativePlacement);
                        }
                        else
                        {
                            IFCAnyHandle newOriginHnd = ExporterUtil.CreateCartesianPoint(file, lpOrig);
                            IFCAnyHandleUtil.SetAttribute(relativePlacement, "Location", newOriginHnd);
                        }
                    }
                }
                else if (ecData.ForceOffset)
                {
                    ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, null));
                }
                else if (!ecData.ReuseLocalPlacement)
                {
                    ecData.SetLocalPlacement(ExporterUtil.CopyLocalPlacement(file, localPlacement));
                }
            }
        }
예제 #2
0
        /// <summary>
        ///  Creates a new IfcAnnotation object.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="curveElement">The curve element.</param>
        /// <param name="categoryId">The category id.</param>
        /// <param name="sketchPlaneId">The sketch plane id.</param>
        /// <param name="curveLCS">The curve local coordinate system.</param>
        /// <param name="curveStyle">The curve style.</param>
        /// <param name="placementSetter">The placemenet setter.</param>
        /// <param name="localPlacement">The local placement.</param>
        /// <param name="repItemHnd">The representation item.</param>
        /// <returns>The handle.</returns>
        static IFCAnyHandle CreateCurveAnnotation(ExporterIFC exporterIFC, Element curveElement, ElementId categoryId, ElementId sketchPlaneId,
                                                  Transform curveLCS, IFCAnyHandle curveStyle, PlacementSetter placementSetter, IFCAnyHandle localPlacement, IFCAnyHandle repItemHnd)
        {
            HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>();

            bodyItems.Add(repItemHnd);
            IFCAnyHandle bodyRepHnd = RepresentationUtil.CreateAnnotationSetRep(exporterIFC, curveElement, categoryId, exporterIFC.Get2DContextHandle(), bodyItems);

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd))
            {
                throw new Exception("Failed to create shape representation.");
            }

            List <IFCAnyHandle> shapes = new List <IFCAnyHandle>();

            shapes.Add(bodyRepHnd);

            IFCFile      file         = exporterIFC.GetFile();
            IFCAnyHandle prodShapeHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapes);

            XYZ xDir = curveLCS.BasisX; XYZ zDir = curveLCS.BasisZ; XYZ origin = curveLCS.Origin;

            // subtract out level origin if we didn't already before.
            IFCLevelInfo levelInfo         = placementSetter.LevelInfo;

            if (levelInfo != null && !MathUtil.IsAlmostEqual(zDir.Z, 1.0))
            {
                zDir -= new XYZ(0, 0, levelInfo.Elevation);
            }

            origin = UnitUtil.ScaleLength(origin);
            IFCAnyHandle relativePlacement = ExporterUtil.CreateAxis(file, origin, zDir, xDir);

            GeometryUtil.SetRelativePlacement(localPlacement, relativePlacement);

            string       guid              = GUIDUtil.CreateGUID(curveElement);
            IFCAnyHandle annotation        = IFCInstanceExporter.CreateAnnotation(exporterIFC, curveElement, guid,
                                                                                  ExporterCacheManager.OwnerHistoryHandle, localPlacement, prodShapeHnd);

            return(annotation);
        }
예제 #3
0
        /// <summary>
        /// Exports text note elements.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="textNote">
        /// The text note element.
        /// </param>
        /// <param name="productWrapper">
        /// The ProductWrapper.
        /// </param>
        public static void Export(ExporterIFC exporterIFC, TextNote textNote, ProductWrapper productWrapper)
        {
            // Check the intended IFC entity or type name is in the exclude list specified in the UI
            string            predefinedType = null;
            IFCExportInfoPair exportType     = ExporterUtil.GetProductExportType(exporterIFC, textNote, out predefinedType);

            if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(exportType.ExportInstance))
            {
                return;
            }

            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                string textString = textNote.Text;
                if (String.IsNullOrEmpty(textString))
                {
                    throw new Exception("TextNote does not have test string.");
                }

                ElementId symId = textNote.GetTypeId();
                if (symId == ElementId.InvalidElementId)
                {
                    throw new Exception("TextNote does not have valid type id.");
                }

                PresentationStyleAssignmentCache cache = ExporterCacheManager.PresentationStyleAssignmentCache;
                IFCAnyHandle presHnd = cache.Find(symId);
                if (IFCAnyHandleUtil.IsNullOrHasNoValue(presHnd))
                {
                    TextElementType textElemType = textNote.Symbol;
                    CreatePresentationStyleAssignmentForTextElementType(exporterIFC, textElemType, cache);
                    presHnd = cache.Find(symId);
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(presHnd))
                    {
                        throw new Exception("Failed to create presentation style assignment for TextElementType.");
                    }
                }

                HashSet <IFCAnyHandle> presHndSet = new HashSet <IFCAnyHandle>();
                presHndSet.Add(presHnd);

                using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, textNote))
                {
                    const double planScale = 100.0; // currently hardwired.

                    XYZ orig = UnitUtil.ScaleLength(textNote.Coord);
                    XYZ yDir = textNote.UpDirection;
                    XYZ xDir = textNote.BaseDirection;
                    XYZ zDir = xDir.CrossProduct(yDir);

                    double sizeX = UnitUtil.ScaleLength(textNote.Width * planScale);
                    double sizeY = UnitUtil.ScaleLength(textNote.Height * planScale);

                    // When we display text on screen, we "flip" it if the xDir is negative with relation to
                    // the X-axis.  So if it is, we'll flip x and y.
                    bool flipOrig = false;
                    if (xDir.X < 0)
                    {
                        xDir     = xDir.Multiply(-1.0);
                        yDir     = yDir.Multiply(-1.0);
                        flipOrig = true;
                    }

                    // xFactor, yFactor only used if flipOrig.
                    double xFactor = 0.0, yFactor = 0.0;
                    string boxAlignment = ConvertTextNoteAlignToBoxAlign(textNote, out xFactor, out yFactor);

                    // modify the origin to match the alignment.  In Revit, the origin is at the top-left (unless flipped,
                    // then bottom-right).
                    if (flipOrig)
                    {
                        orig = orig.Add(xDir.Multiply(sizeX * xFactor));
                        orig = orig.Add(yDir.Multiply(sizeY * yFactor));
                    }

                    IFCAnyHandle origin = ExporterUtil.CreateAxis(file, orig, zDir, xDir);

                    IFCAnyHandle extent         = IFCInstanceExporter.CreatePlanarExtent(file, sizeX, sizeY);
                    IFCAnyHandle repItemHnd     = IFCInstanceExporter.CreateTextLiteralWithExtent(file, textString, origin, Toolkit.IFCTextPath.Left, extent, boxAlignment);
                    IFCAnyHandle annoTextOccHnd = IFCInstanceExporter.CreateStyledItem(file, repItemHnd, presHndSet, null);

                    ElementId catId = textNote.Category != null ? textNote.Category.Id : ElementId.InvalidElementId;
                    HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>();
                    bodyItems.Add(repItemHnd);
                    IFCAnyHandle bodyRepHnd = RepresentationUtil.CreateAnnotationSetRep(exporterIFC, textNote, catId, exporterIFC.Get2DContextHandle(), bodyItems);

                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd))
                    {
                        throw new Exception("Failed to create shape representation.");
                    }

                    IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>();
                    shapeReps.Add(bodyRepHnd);

                    IFCAnyHandle prodShapeHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps);
                    IFCAnyHandle instHnd;
                    if (exportType.ExportInstance == Common.Enums.IFCEntityType.IfcAnnotation)
                    {
                        instHnd = IFCInstanceExporter.CreateAnnotation(exporterIFC, textNote, GUIDUtil.CreateGUID(), ExporterCacheManager.OwnerHistoryHandle,
                                                                       setter.LocalPlacement, prodShapeHnd);
                    }
                    else
                    {
                        instHnd = IFCInstanceExporter.CreateGenericIFCEntity(exportType, exporterIFC, textNote, GUIDUtil.CreateGUID(), ExporterCacheManager.OwnerHistoryHandle,
                                                                             setter.LocalPlacement, prodShapeHnd);
                    }

                    productWrapper.AddAnnotation(instHnd, setter.LevelInfo, true);
                }

                tr.Commit();
            }
        }
예제 #4
0
        /// <summary>
        /// Creates a simple swept solid from a list of curve loops.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="profileName">The profile name.</param>
        /// <param name="profileCurveLoops">The profile curve loops.</param>
        /// <param name="normal">The normal of the plane that the path lies on.</param>
        /// <param name="directrix">The path curve.</param>
        /// <returns>The swept solid handle.</returns>
        public static IFCAnyHandle CreateSimpleSweptSolid(ExporterIFC exporterIFC, string profileName, IList <CurveLoop> profileCurveLoops,
                                                          XYZ normal, Curve directrix)
        {
            // see definition of IfcSurfaceCurveSweptAreaSolid from
            // http://www.buildingsmart-tech.org/ifc/IFC2x4/rc4/html/schema/ifcgeometricmodelresource/lexical/ifcsurfacecurvesweptareasolid.htm

            IFCAnyHandle simpleSweptSolidHnd = null;

            if (!CanCreateSimpleSweptSolid(profileCurveLoops, normal, directrix))
            {
                return(simpleSweptSolidHnd);
            }

            bool   isBound            = directrix.IsBound;
            double originalStartParam = isBound ? directrix.GetEndParameter(0) : 0.0;

            Plane axisPlane, profilePlane;

            CreateAxisAndProfileCurvePlanes(directrix, originalStartParam, out axisPlane, out profilePlane);

            IList <CurveLoop> curveLoops = null;

            try
            {
                // Check that curve loops are valid.
                curveLoops = ExporterIFCUtils.ValidateCurveLoops(profileCurveLoops, profilePlane.Normal);
            }
            catch (Exception)
            {
                return(null);
            }

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

            double startParam = 0.0, endParam = 1.0;

            if (directrix is Arc)
            {
                // This effectively resets the start parameter to 0.0, and end parameter = length of curve.
                if (isBound)
                {
                    endParam = UnitUtil.ScaleAngle(MathUtil.PutInRange(directrix.GetEndParameter(1), Math.PI, 2 * Math.PI) -
                                                   MathUtil.PutInRange(originalStartParam, Math.PI, 2 * Math.PI));
                }
                else
                {
                    endParam = 2.0 * Math.PI;
                }
            }

            // Start creating IFC entities.

            IFCAnyHandle sweptArea = ExtrusionExporter.CreateSweptArea(exporterIFC, profileName, curveLoops, profilePlane, profilePlane.Normal);

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(sweptArea))
            {
                return(simpleSweptSolidHnd);
            }

            IFCAnyHandle curveHandle            = null;
            IFCAnyHandle referenceSurfaceHandle = ExtrusionExporter.CreateSurfaceOfLinearExtrusionFromCurve(exporterIFC, directrix, axisPlane, 1.0, 1.0,
                                                                                                            out curveHandle);

            // Should this be moved up?  Check.
            Plane scaledAxisPlane = GeometryUtil.GetScaledPlane(exporterIFC, axisPlane);

            IFCFile file = exporterIFC.GetFile();

            IFCAnyHandle solidAxis = ExporterUtil.CreateAxis(file, scaledAxisPlane.Origin, scaledAxisPlane.Normal, scaledAxisPlane.XVec);

            simpleSweptSolidHnd = IFCInstanceExporter.CreateSurfaceCurveSweptAreaSolid(file, sweptArea, solidAxis, curveHandle, startParam,
                                                                                       endParam, referenceSurfaceHandle);
            return(simpleSweptSolidHnd);
        }
예제 #5
0
        /// <summary>
        ///    Initializes the transformation in the transform setter.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="geometryList">The set of geometry used to determine the bounding box.</param>
        /// <param name="ecData">The extrusion creation data which contains the local placement.</param>
        /// <returns>The transform corresponding to the movement, if any.</returns>
        /// <remarks>This method will eventually be obsoleted by the InitializeFromBoundingBox/CreateLocalPlacementFromOffset pair below, which delays creating or updating the local placement
        /// until we are certain we will use it, saving time and reducing wasted line numbers.</remarks>
        public Transform InitializeFromBoundingBox(ExporterIFC exporterIFC, IList <GeometryObject> geometryList, IFCExtrusionCreationData ecData)
        {
            if (ecData == null)
            {
                return(null);
            }
            Transform trf = Transform.Identity;

            IFCAnyHandle localPlacement = ecData.GetLocalPlacement();

            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(localPlacement))
            {
                IFCFile        file = exporterIFC.GetFile();
                BoundingBoxXYZ bbox = GeometryUtil.GetBBoxOfGeometries(geometryList);

                // If the BBox passes through (0,0, 0), or no bbox, do nothing.
                if (bbox == null ||
                    ((bbox.Min.X < MathUtil.Eps() && bbox.Max.X > -MathUtil.Eps()) &&
                     (bbox.Min.Y < MathUtil.Eps() && bbox.Max.Y > -MathUtil.Eps()) &&
                     (bbox.Min.Z < MathUtil.Eps() && bbox.Max.Z > -MathUtil.Eps())))
                {
                    if (!ecData.ReuseLocalPlacement)
                    {
                        ecData.SetLocalPlacement(ExporterUtil.CopyLocalPlacement(file, localPlacement));
                    }
                    return(trf);
                }

                XYZ bboxMin    = bbox.Min;
                XYZ scaledOrig = UnitUtil.ScaleLength(bboxMin);

                Transform scaledTrf = GeometryUtil.GetScaledTransform(exporterIFC);

                XYZ lpOrig = scaledTrf.OfPoint(scaledOrig);
                if (!ecData.AllowVerticalOffsetOfBReps)
                {
                    lpOrig = new XYZ(lpOrig.X, lpOrig.Y, 0.0);
                }

                Transform scaledTrfInv  = scaledTrf.Inverse;
                XYZ       scaledInvOrig = scaledTrfInv.OfPoint(XYZ.Zero);

                XYZ unscaledInvOrig = UnitUtil.UnscaleLength(scaledInvOrig);

                XYZ trfOrig = unscaledInvOrig - bboxMin;
                if (!ecData.AllowVerticalOffsetOfBReps)
                {
                    trfOrig = new XYZ(trfOrig.X, trfOrig.Y, 0.0);
                }

                if (!MathUtil.IsAlmostZero(trfOrig.DotProduct(trfOrig)))
                {
                    Initialize(exporterIFC, trfOrig, XYZ.BasisX, XYZ.BasisY);
                    if (!ecData.ReuseLocalPlacement)
                    {
                        ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, lpOrig, null, null));
                    }
                    else
                    {
                        IFCAnyHandle relativePlacement = GeometryUtil.GetRelativePlacementFromLocalPlacement(localPlacement);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(relativePlacement))
                        {
                            IFCAnyHandle newRelativePlacement = ExporterUtil.CreateAxis(file, lpOrig, null, null);
                            GeometryUtil.SetRelativePlacement(localPlacement, newRelativePlacement);
                        }
                        else
                        {
                            IFCAnyHandle oldOriginHnd, zDirHnd, xDirHnd;
                            xDirHnd      = IFCAnyHandleUtil.GetInstanceAttribute(relativePlacement, "RefDirection");
                            zDirHnd      = IFCAnyHandleUtil.GetInstanceAttribute(relativePlacement, "Axis");
                            oldOriginHnd = IFCAnyHandleUtil.GetInstanceAttribute(relativePlacement, "Location");

                            bool trfSet = false;
                            XYZ  xDir = XYZ.BasisX; XYZ zDir = XYZ.BasisZ; XYZ oldCoords = XYZ.Zero;
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(xDirHnd))
                            {
                                xDir   = GeometryUtil.GetDirectionRatios(xDirHnd);
                                trfSet = true;
                            }
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(zDirHnd))
                            {
                                zDir   = GeometryUtil.GetDirectionRatios(zDirHnd);
                                trfSet = true;
                            }
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(oldOriginHnd))
                            {
                                oldCoords = GeometryUtil.GetCoordinates(oldOriginHnd);
                            }

                            if (trfSet)
                            {
                                XYZ       yDir            = zDir.CrossProduct(xDir);
                                Transform relPlacementTrf = Transform.Identity;
                                relPlacementTrf.Origin = oldCoords; relPlacementTrf.BasisX = xDir;
                                relPlacementTrf.BasisY = yDir; relPlacementTrf.BasisZ = zDir;
                                lpOrig = relPlacementTrf.OfPoint(lpOrig);
                            }
                            else
                            {
                                lpOrig = oldCoords + lpOrig;
                            }

                            IFCAnyHandle newOriginHnd = ExporterUtil.CreateCartesianPoint(file, lpOrig);
                            IFCAnyHandleUtil.SetAttribute(relativePlacement, "Location", newOriginHnd);
                        }
                    }

                    trf.Origin = lpOrig;
                }
                else if (ecData.ForceOffset)
                {
                    ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, null));
                }
                else if (!ecData.ReuseLocalPlacement)
                {
                    ecData.SetLocalPlacement(ExporterUtil.CopyLocalPlacement(file, localPlacement));
                }
            }
            return(trf);
        }
예제 #6
0
        /// <summary>
        /// Creates a simple swept solid from a list of curve loops.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="profileName">The profile name.</param>
        /// <param name="profileCurveLoops">The profile curve loops.</param>
        /// <param name="normal">The normal of the plane that the path lies on.</param>
        /// <param name="directrix">The path curve.</param>
        /// <returns>The swept solid handle.</returns>
        public static IFCAnyHandle CreateSimpleSweptSolid(ExporterIFC exporterIFC, string profileName, IList <CurveLoop> profileCurveLoops,
                                                          XYZ normal, Curve directrix)
        {
            // see definition of IfcSurfaceCurveSweptAreaSolid from
            // http://www.buildingsmart-tech.org/ifc/IFC2x4/rc4/html/schema/ifcgeometricmodelresource/lexical/ifcsurfacecurvesweptareasolid.htm

            IFCAnyHandle simpleSweptSolidHnd = null;

            if (!CanCreateSimpleSweptSolid(profileCurveLoops, normal, directrix))
            {
                return(simpleSweptSolidHnd);
            }

            bool   isBound            = directrix.IsBound;
            double originalStartParam = isBound ? directrix.GetEndParameter(0) : 0.0;

            Transform axisLCS, profileLCS;

            CreateAxisAndProfileCurveLCS(directrix, originalStartParam, out axisLCS, out profileLCS);

            IList <CurveLoop> curveLoops = null;

            try
            {
                // Check that curve loops are valid.
                curveLoops = ExporterIFCUtils.ValidateCurveLoops(profileCurveLoops, profileLCS.BasisZ);
            }
            catch (Exception)
            {
                return(null);
            }

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

            double startParam = 0.0, endParam = 1.0;

            if (directrix is Arc)
            {
                // This effectively resets the start parameter to 0.0, and end parameter = length of curve.
                if (isBound)
                {
                    // Put the parameters in range of [0, 2*Pi]
                    double inRangeStarParam = (directrix.GetEndParameter(0) % (2 * Math.PI));
                    double inRangeEndParam  = (directrix.GetEndParameter(1) % (2 * Math.PI));
                    // We want the angle direction is anti-clockwise (+ direction), therefore we will always start with the smaller one
                    if (inRangeEndParam < inRangeStarParam)
                    {
                        double tmp = inRangeStarParam;
                        inRangeStarParam = inRangeEndParam;
                        inRangeEndParam  = tmp;
                    }
                    // If start param is negative, we will reset it to 0 and shift the end accordingly
                    if (inRangeStarParam < 0)
                    {
                        double parRange = inRangeEndParam - inRangeStarParam;
                        inRangeStarParam = 0.0;
                        inRangeEndParam  = parRange;
                    }
                    endParam = UnitUtil.ScaleAngle(inRangeEndParam);
                    //endParam = UnitUtil.ScaleAngle(MathUtil.PutInRange(directrix.GetEndParameter(1), Math.PI, 2 * Math.PI) -
                    //   MathUtil.PutInRange(originalStartParam, Math.PI, 2 * Math.PI));
                }
                else
                {
                    endParam = 2.0 * Math.PI;
                }
            }

            // Start creating IFC entities.

            IFCAnyHandle sweptArea = ExtrusionExporter.CreateSweptArea(exporterIFC, profileName, curveLoops, profileLCS, profileLCS.BasisZ);

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(sweptArea))
            {
                return(simpleSweptSolidHnd);
            }

            IFCAnyHandle curveHandle            = null;
            IFCAnyHandle referenceSurfaceHandle = ExtrusionExporter.CreateSurfaceOfLinearExtrusionFromCurve(exporterIFC, directrix, axisLCS, 1.0, 1.0,
                                                                                                            out curveHandle);

            // Should this be moved up?  Check.
            XYZ scaledOrigin = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, axisLCS.Origin);
            XYZ scaledXDir   = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, axisLCS.BasisX).Normalize();
            XYZ scaledNormal = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, axisLCS.BasisZ).Normalize();

            IFCFile file = exporterIFC.GetFile();

            IFCAnyHandle solidAxis = ExporterUtil.CreateAxis(file, scaledOrigin, scaledNormal, scaledXDir);

            simpleSweptSolidHnd = IFCInstanceExporter.CreateSurfaceCurveSweptAreaSolid(file, sweptArea, solidAxis, curveHandle, startParam,
                                                                                       endParam, referenceSurfaceHandle);
            return(simpleSweptSolidHnd);
        }
        /// <summary>
        /// Creates a simple swept solid from a list of curve loops.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="profileName">The profile name.</param>
        /// <param name="profileCurveLoops">The profile curve loops.</param>
        /// <param name="normal">The normal of the plane that the path lies on.</param>
        /// <param name="directrix">The path curve.</param>
        /// <returns>The swept solid handle.</returns>
        public static IFCAnyHandle CreateSimpleSweptSolid(ExporterIFC exporterIFC, string profileName, IList <CurveLoop> profileCurveLoops,
                                                          XYZ normal, Curve directrix)
        {
            // see definition of IfcSurfaceCurveSweptAreaSolid from
            // http://www.buildingsmart-tech.org/ifc/IFC2x4/rc4/html/schema/ifcgeometricmodelresource/lexical/ifcsurfacecurvesweptareasolid.htm

            IFCAnyHandle simpleSweptSolidHnd = null;

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

            IFCFile file = exporterIFC.GetFile();

            XYZ startPoint         = directrix.get_EndPoint(0);
            XYZ profilePlaneNormal = null;
            XYZ profilePlaneXDir   = null;
            XYZ profilePlaneYDir   = null;

            IFCAnyHandle curveHandle = null;

            double startParam = 0, endParam = 1;
            Plane  scaledReferencePlane = null;

            if (directrix is Line)
            {
                Line line = directrix as Line;
                startParam         = 0.0;
                endParam           = 1.0;
                profilePlaneNormal = line.Direction;
                profilePlaneYDir   = normal;
                profilePlaneXDir   = profilePlaneNormal.CrossProduct(profilePlaneYDir);

                XYZ linePlaneNormal = profilePlaneYDir;
                XYZ linePlaneXDir   = profilePlaneXDir;
                XYZ linePlaneYDir   = linePlaneNormal.CrossProduct(linePlaneXDir);
                XYZ linePlaneOrig   = startPoint;

                scaledReferencePlane = GeometryUtil.CreateScaledPlane(exporterIFC, linePlaneXDir, linePlaneYDir, linePlaneOrig);
                curveHandle          = GeometryUtil.CreateLine(exporterIFC, line, scaledReferencePlane);
            }
            else if (directrix is Arc)
            {
                Arc arc = directrix as Arc;

                // profilePlaneXDir is set relative to the startPoint of the directrix.  This effectively resets the start parameter to 0.0, and end parameter = length of curve.
                startParam = 0.0;
                endParam   = (MathUtil.PutInRange(arc.get_EndParameter(1), Math.PI, 2 * Math.PI) - MathUtil.PutInRange(arc.get_EndParameter(0), Math.PI, 2 * Math.PI)) * (180 / Math.PI);

                profilePlaneNormal = directrix.ComputeDerivatives(0, true).BasisX;
                profilePlaneXDir   = (arc.Center - startPoint).Normalize();
                profilePlaneYDir   = profilePlaneNormal.CrossProduct(profilePlaneXDir).Normalize();

                XYZ arcPlaneNormal = arc.Normal;
                XYZ arcPlaneXDir   = profilePlaneXDir;
                XYZ arcPlaneYDir   = arcPlaneNormal.CrossProduct(arcPlaneXDir);
                XYZ arcPlaneOrig   = startPoint;

                scaledReferencePlane = GeometryUtil.CreateScaledPlane(exporterIFC, arcPlaneXDir, arcPlaneYDir, arcPlaneOrig);
                curveHandle          = GeometryUtil.CreateArc(exporterIFC, arc, scaledReferencePlane);
            }
            else
            {
                return(simpleSweptSolidHnd);
            }

            IFCAnyHandle referencePlaneAxisHandle = ExporterUtil.CreateAxis(file, scaledReferencePlane.Origin, scaledReferencePlane.Normal, scaledReferencePlane.XVec);
            IFCAnyHandle referencePlaneHandle     = IFCInstanceExporter.CreatePlane(file, referencePlaneAxisHandle);

            Plane profilePlane = new Plane(profilePlaneXDir, profilePlaneYDir, startPoint);

            IList <CurveLoop> curveLoops = null;

            try
            {
                // Check that curve loops are valid.
                curveLoops = ExporterIFCUtils.ValidateCurveLoops(profileCurveLoops, profilePlaneNormal);
            }
            catch (Exception)
            {
                return(null);
            }

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

            IFCAnyHandle sweptArea = ExtrusionExporter.CreateSweptArea(exporterIFC, profileName, curveLoops, profilePlane, profilePlaneNormal);

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(sweptArea))
            {
                return(simpleSweptSolidHnd);
            }

            profilePlane = GeometryUtil.GetScaledPlane(exporterIFC, profilePlane);
            IFCAnyHandle solidAxis = ExporterUtil.CreateAxis(file, profilePlane.Origin, profilePlane.Normal, profilePlane.XVec);

            simpleSweptSolidHnd = IFCInstanceExporter.CreateSurfaceCurveSweptAreaSolid(file, sweptArea, solidAxis, curveHandle, startParam,
                                                                                       endParam, referencePlaneHandle);
            return(simpleSweptSolidHnd);
        }