/// <summary>
        /// Initializes property sets.
        /// </summary>
        /// <param name="propertySetsToExport">Existing functions to call for property set initialization.</param>
        /// <param name="fileVersion">The IFC file version.</param>
        public static void InitPropertySets(Exporter.PropertySetsToExport propertySetsToExport, IFCVersion fileVersion)
        {
            ParameterCache cache = ExporterCacheManager.ParameterCache;

            if (ExporterCacheManager.ExportOptionsCache.PropertySetOptions.ExportIFCCommon)
            {
                if (propertySetsToExport == null)
                    propertySetsToExport = InitCommonPropertySets;
                else
                    propertySetsToExport += InitCommonPropertySets;
            }

            if (ExporterCacheManager.ExportOptionsCache.PropertySetOptions.ExportSchedulesAsPsets)
            {
                if (propertySetsToExport == null)
                    propertySetsToExport = InitCustomPropertySets;
                else
                    propertySetsToExport += InitCustomPropertySets;
            }

            if (ExporterCacheManager.ExportOptionsCache.PropertySetOptions.ExportUserDefinedPsets)
            {
                if (propertySetsToExport == null)
                    propertySetsToExport = InitUserDefinedPropertySets;
                else
                    propertySetsToExport += InitUserDefinedPropertySets;
            }

            if (ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE)
            {
                if (propertySetsToExport == null)
                    propertySetsToExport = InitCOBIEPropertySets;
                else
                    propertySetsToExport += InitCOBIEPropertySets;
            }

            if (propertySetsToExport != null)
                propertySetsToExport(cache.PropertySets, fileVersion);
        }
        /// <summary>
        /// Initializes quantities.
        /// </summary>
        /// <param name="fileVersion">The IFC file version.</param>
        /// <param name="exportBaseQuantities">True if export base quantities.</param>
        public static void InitQuantities(Exporter.QuantitiesToExport quantitiesToExport, IFCVersion fileVersion, bool exportBaseQuantities)
        {
            ParameterCache cache = ExporterCacheManager.ParameterCache;

            if (exportBaseQuantities)
            {
                if (quantitiesToExport == null)
                    quantitiesToExport = InitBaseQuantities;
                else
                    quantitiesToExport += InitBaseQuantities;
            }

            if (fileVersion == IFCVersion.IFCCOBIE)
            {
                if (quantitiesToExport == null)
                    quantitiesToExport = InitCOBIEQuantities;
                else
                    quantitiesToExport += InitCOBIEQuantities; 
            }

            if (quantitiesToExport != null)
                quantitiesToExport(cache.Quantities, fileVersion);
        }
        /// <summary>
        /// Exports spatial elements, including rooms, areas and spaces. 2nd level space boundaries.
        /// </summary>
        /// <param name="ifcExporter">The Exporter object.</param>
        /// <param name="exporterIFC"> The ExporterIFC object.</param>
        /// <param name="document">The Revit document.</param>
        /// <returns>The set of exported spaces.  This is used to try to export using the standard routine for spaces that failed.</returns>
        public static ISet<ElementId> ExportSpatialElement2ndLevel(Exporter ifcExporter, ExporterIFC exporterIFC, Document document)
        {
            ISet<ElementId> exportedSpaceIds = new HashSet<ElementId>();

            using (SubTransaction st = new SubTransaction(document))
            {
                st.Start();

                EnergyAnalysisDetailModel model = null;
                try
                {
                    View filterView = ExporterCacheManager.ExportOptionsCache.FilterViewForExport;
                    IFCFile file = exporterIFC.GetFile();
                    using (IFCTransaction transaction = new IFCTransaction(file))
                    {

                        EnergyAnalysisDetailModelOptions options = new EnergyAnalysisDetailModelOptions();
                        options.Tier = EnergyAnalysisDetailModelTier.SecondLevelBoundaries; //2nd level space boundaries
                        options.SimplifyCurtainSystems = true;
                        try
                        {
                            model = EnergyAnalysisDetailModel.Create(document, options);
                        }
                        catch (System.Exception)
                        {
                            return exportedSpaceIds;
                        }

                        IList<EnergyAnalysisSpace> spaces = model.GetAnalyticalSpaces();
                        foreach (EnergyAnalysisSpace space in spaces)
                        {
                            SpatialElement spatialElement = document.GetElement(space.SpatialElementId) as SpatialElement;

                            if (spatialElement == null)
                                continue;

                            //current view only
                            if (!ElementFilteringUtil.IsElementVisible(spatialElement))
                                continue;

                            if (!ElementFilteringUtil.ShouldElementBeExported(exporterIFC, spatialElement, false))
                                continue;

                            if (ElementFilteringUtil.IsRoomInInvalidPhase(spatialElement))
                                continue;

                            Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions();
                            View ownerView = spatialElement.Document.GetElement(spatialElement.OwnerViewId) as View;
                            if (ownerView != null)
                                geomOptions.View = ownerView;
                            GeometryElement geomElem = spatialElement.get_Geometry(geomOptions);

                            try
                            {
                                exporterIFC.PushExportState(spatialElement, geomElem);

                                using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true))
                                {
                                    ElementId levelId = ExporterUtil.GetBaseLevelIdForElement(spatialElement);
                                    using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, spatialElement, null, null, levelId))
                                    {
                                        if (!CreateIFCSpace(exporterIFC, spatialElement, productWrapper, setter))
                                            continue;

                                        exportedSpaceIds.Add(spatialElement.Id);

                                        XYZ offset = GetSapceBoundaryOffset(setter);

                                        //get boundary information from surfaces
                                        IList<EnergyAnalysisSurface> surfaces = space.GetAnalyticalSurfaces();
                                        foreach (EnergyAnalysisSurface surface in surfaces)
                                        {
                                            Element boundingElement = GetBoundaryElement(document, surface.OriginatingElementId);

                                            IList<EnergyAnalysisOpening> openings = surface.GetAnalyticalOpenings();
                                            IFCAnyHandle connectionGeometry = CreateConnectionSurfaceGeometry(file, surface, openings, offset);
                                            CreateIFCSpaceBoundary(file, exporterIFC, spatialElement, boundingElement, setter.LevelId, connectionGeometry);

                                            // try to add doors and windows for host objects if appropriate.
                                            if (boundingElement is HostObject)
                                            {
                                                foreach (EnergyAnalysisOpening opening in openings)
                                                {
                                                    Element openingBoundingElem = GetBoundaryElement(document, opening.OriginatingElementId);
                                                    IFCAnyHandle openingConnectionGeom = CreateConnectionSurfaceGeometry(file, opening, offset);
                                                    CreateIFCSpaceBoundary(file, exporterIFC, spatialElement, openingBoundingElem, setter.LevelId, openingConnectionGeom);
                                                }
                                            }
                                        }
                                        CreateZoneInfos(exporterIFC, file, spatialElement, productWrapper);
                                        CreateSpaceOccupantInfo(exporterIFC, file, spatialElement, productWrapper);

                                        ExporterUtil.ExportRelatedProperties(exporterIFC, spatialElement, productWrapper);
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                ifcExporter.HandleUnexpectedException(ex, exporterIFC, spatialElement);
                            }
                            finally
                            {
                                exporterIFC.PopExportState();
                            }
                        }
                        transaction.Commit();
                    }
                }
                finally
                {
                    if (model != null)
                        EnergyAnalysisDetailModel.Destroy(model);
                }

                st.RollBack();
                return exportedSpaceIds;
            }
        }