static public void RegisterSpaceBoundingElementHandle(ExporterIFC exporterIFC, IFCAnyHandle elemHnd, ElementId elementId,
            ElementId levelId)
        {
            int idx;
            if (!ExporterCacheManager.HostObjectsLevelIndex.TryGetValue(levelId, out idx))
            {
                int nextIndex = ExporterCacheManager.HostObjectsLevelIndex.Count;
                ExporterCacheManager.HostObjectsLevelIndex.Add(levelId, nextIndex);
            }

            exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, elementId, levelId);
        }
        static public void RegisterSpaceBoundingElementHandle(ExporterIFC exporterIFC, IFCAnyHandle elemHnd, ElementId elementId,
                                                              ElementId levelId)
        {
            int idx;

            if (!ExporterCacheManager.HostObjectsLevelIndex.TryGetValue(levelId, out idx))
            {
                int nextIndex = ExporterCacheManager.HostObjectsLevelIndex.Count;
                ExporterCacheManager.HostObjectsLevelIndex.Add(levelId, nextIndex);
            }

            exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, elementId, levelId);
        }
        /// <summary>
        /// Exports a family instance as a mapped item.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="familyInstance">
        /// The family instance to be exported.
        /// </param>
        /// <param name="exportType">
        /// The export type.
        /// </param>
        /// <param name="ifcEnumType">
        /// The string value represents the IFC type.
        /// </param>
        /// <param name="wrapper">
        /// The ProductWrapper.
        /// </param>
        /// <param name="overrideLevelId">
        /// The level id.
        /// </param>
        /// <param name="range">
        /// The range of this family instance to be exported.
        /// </param>
        public static void ExportFamilyInstanceAsMappedItem(ExporterIFC exporterIFC,
            FamilyInstance familyInstance, IFCExportType exportType, string ifcEnumType,
            ProductWrapper wrapper, ElementId overrideLevelId, IFCRange range, IFCAnyHandle parentLocalPlacement)
        {
            bool exportParts = PartExporter.CanExportParts(familyInstance);
            bool isSplit = range != null;
            if (exportParts && !PartExporter.CanExportElementInPartExport(familyInstance, isSplit ? overrideLevelId : familyInstance.Level.Id, isSplit))
                return;

            Document doc = familyInstance.Document;
            IFCFile file = exporterIFC.GetFile();

            FamilySymbol familySymbol = ExporterIFCUtils.GetOriginalSymbol(familyInstance);
            if (familySymbol == null)
                return;

            ProductWrapper familyProductWrapper = ProductWrapper.Create(wrapper);
            double scale = exporterIFC.LinearScale;
            Options options = GeometryUtil.GetIFCExportGeometryOptions();

            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

            HostObject hostElement = familyInstance.Host as HostObject; //hostElement could be null
            ElementId categoryId = CategoryUtil.GetSafeCategoryId(familySymbol);

            //string emptyString = "";
            string familyName = familySymbol.Name;
            string objectType = familyName;

            // A Family Instance can have its own copy of geometry, or use the symbol's copy with a transform.
            // The routine below tells us whether to use the Instance's copy or the Symbol's copy.
            bool useInstanceGeometry = ExporterIFCUtils.UsesInstanceGeometry(familyInstance);

            IList<IFCExtrusionData> cutPairOpeningsForColumns = new List<IFCExtrusionData>();
            using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData())
            {
                Transform trf = familyInstance.GetTransform();

                // Extra information if we are exporting a door or a window.
                IFCDoorWindowInfo doorWindowInfo = null;
                if (exportType == IFCExportType.ExportDoorType)
                    doorWindowInfo = IFCDoorWindowInfo.CreateDoorInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf);
                else if (exportType == IFCExportType.ExportWindowType)
                    doorWindowInfo = IFCDoorWindowInfo.CreateWindowInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf);

                FamilyTypeInfo typeInfo = new FamilyTypeInfo();
                XYZ extraOffset = XYZ.Zero;

                bool flipped = doorWindowInfo != null ? doorWindowInfo.IsSymbolFlipped : false;
                FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(familySymbol.Id, flipped);
                bool found = currentTypeInfo.IsValid();

                Family family = familySymbol.Family;

                // TODO: this code to be removed by ExtrusionAnalyzer code.
                bool trySpecialColumnCreation = ((exportType == IFCExportType.ExportColumnType) && (!family.IsInPlace));
                IList<GeometryObject> geomObjects = new List<GeometryObject>();
                Transform brepOffsetTransform = null;

                Transform doorWindowTrf = Transform.Identity;
                // We will create a new mapped type if:
                // 1.  We are exporting part of a column or in-place wall (range != null), OR
                // 2.  We are using the instance's copy of the geometry (that it, it has unique geometry), OR
                // 3.  We haven't already created the type.
                bool creatingType = ((range != null) || useInstanceGeometry || !found);
                if (creatingType)
                {
                    IFCAnyHandle bodyRepresentation = null;
                    IFCAnyHandle planRepresentation = null;

                    // If we are using the instance geometry, ignore the transformation.
                    if (useInstanceGeometry)
                        trf = Transform.Identity;

                    // TODO: this code to be removed by ExtrusionAnalyzer code.
                    if (trySpecialColumnCreation)
                    {
                        XYZ rangeOffset = trf.Origin;
                        IFCFamilyInstanceExtrusionExportResults results;

                        results = ExporterIFCUtils.ExportFamilyInstanceAsExtrusion(exporterIFC, familyInstance, useInstanceGeometry, range, overrideLevelId, extraParams);

                        bodyRepresentation = results.GetExtrusionHandle();
                        extraOffset = results.ExtraOffset;
                        cutPairOpeningsForColumns = results.GetCutPairOpenings();

                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation))
                        {
                            typeInfo.MaterialIds.Add(results.MaterialId);
                            // add in level for real columns, not in-place ones.
                            Element actualLevel =
                               (overrideLevelId == ElementId.InvalidElementId) ? familyInstance.Level : doc.GetElement(overrideLevelId);
                            if (actualLevel != null)
                            {
                                IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(actualLevel.Id);
                                double nonStoryLevelOffset = LevelUtil.GetNonStoryLevelOffsetIfAny(exporterIFC, actualLevel as Level);
                                if (range != null)
                                {
                                    rangeOffset = new XYZ(rangeOffset.X, rangeOffset.Y, levelInfo.Elevation + nonStoryLevelOffset);
                                }
                            }
                        }

                        rangeOffset += extraOffset;
                        trf.Origin = rangeOffset;
                    }

                    IFCAnyHandle dummyPlacement = null;
                    if (doorWindowInfo != null)
                    {
                        doorWindowTrf = ExporterIFCUtils.GetTransformForDoorOrWindow(familyInstance, familySymbol, doorWindowInfo);
                    }
                    else
                    {
                        dummyPlacement = IFCInstanceExporter.CreateLocalPlacement(file, null, ExporterUtil.CreateAxis2Placement3D(file));
                        extraParams.SetLocalPlacement(dummyPlacement);
                    }

                    bool needToCreate2d = ExporterCacheManager.ExportOptionsCache.ExportAnnotations;
                    bool needToCreate3d = IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation);

                    if (needToCreate2d || needToCreate3d)
                    {
                        using (IFCTransformSetter trfSetter = IFCTransformSetter.Create())
                        {
                            if (doorWindowInfo != null)
                            {
                                trfSetter.Initialize(exporterIFC, doorWindowTrf);
                            }

                            GeometryElement exportGeometry =
                               useInstanceGeometry ? familyInstance.get_Geometry(options) : familySymbol.get_Geometry(options);
                            if (exportGeometry == null)
                                return;

                            if (needToCreate3d)
                            {
                                SolidMeshGeometryInfo solidMeshCapsule = null;

                                if (range == null)
                                {
                                    solidMeshCapsule = GeometryUtil.GetSolidMeshGeometry(exportGeometry, Transform.Identity);
                                }
                                else
                                {
                                    solidMeshCapsule = GeometryUtil.GetClippedSolidMeshGeometry(exportGeometry, range);
                                }

                                IList<Solid> solids = solidMeshCapsule.GetSolids();
                                IList<Mesh> polyMeshes = solidMeshCapsule.GetMeshes();

                                if (range != null && (solids.Count == 0 && polyMeshes.Count == 0))
                                    return; // no proper split geometry

                                geomObjects = FamilyExporterUtil.RemoveSolidsAndMeshesSetToDontExport(doc, exporterIFC, solids, polyMeshes);
                                if (geomObjects.Count == 0 && (solids.Count > 0 || polyMeshes.Count > 0))
                                    return;

                                bool tryToExportAsExtrusion = (!exporterIFC.ExportAs2x2 || (exportType == IFCExportType.ExportColumnType));

                                if (exportType == IFCExportType.ExportColumnType)
                                {
                                    extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ;

                                    if (ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 &&
                                        solids.Count > 0)
                                    {
                                        LocationPoint point = familyInstance.Location as LocationPoint;
                                        XYZ orig = XYZ.Zero;
                                        if (point != null)
                                            orig = point.Point;

                                        Plane plane = new Plane(XYZ.BasisX, XYZ.BasisY, orig);
                                        bool completelyClipped = false;
                                        HashSet<ElementId> materialIds = null;
                                        bodyRepresentation = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, familyInstance,
                                            categoryId, solids, plane, XYZ.BasisZ, null, out completelyClipped, out materialIds);
                                        typeInfo.MaterialIds = materialIds;
                                    }
                                }
                                else
                                {
                                    extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryXYZ;
                                }

                                BodyData bodyData = null;
                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation))
                                {
                                    BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(tryToExportAsExtrusion);
                                    if (geomObjects.Count > 0)
                                    {
                                        bodyData = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, familyInstance, categoryId, ElementId.InvalidElementId,
                                            geomObjects, bodyExporterOptions, extraParams);
                                        typeInfo.MaterialIds = bodyData.MaterialIds;
                                    }
                                    else
                                    {
                                        IList<GeometryObject> exportedGeometries = new List<GeometryObject>();
                                        exportedGeometries.Add(exportGeometry);
                                        bodyData = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, familyInstance, categoryId, ElementId.InvalidElementId,
                                            exportedGeometries, bodyExporterOptions, extraParams);
                                    }
                                    bodyRepresentation = bodyData.RepresentationHnd;
                                    brepOffsetTransform = bodyData.BrepOffsetTransform;
                                }

                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation))
                                {
                                    extraParams.ClearOpenings();
                                    return;
                                }
                            }

                            // By default: if exporting IFC2x3 or later, export 2D plan rep of family, if it exists, unless we are exporting Coordination View V2.
                            // This default can be overridden in the export options.
                            if (needToCreate2d)
                            {
                                XYZ curveOffset = new XYZ(0, 0, 0);
                                if (brepOffsetTransform != null)
                                    curveOffset = -brepOffsetTransform.Origin / scale;

                                HashSet<IFCAnyHandle> curveSet = new HashSet<IFCAnyHandle>();
                                {
                                    Transform planeTrf = doorWindowTrf.Inverse;
                                    Plane plane = new Plane(planeTrf.get_Basis(0), planeTrf.get_Basis(1), planeTrf.Origin);
                                    XYZ projDir = new XYZ(0, 0, 1);

                                    IFCGeometryInfo IFCGeometryInfo = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, true);
                                    ExporterIFCUtils.CollectGeometryInfo(exporterIFC, IFCGeometryInfo, exportGeometry, curveOffset, false);

                                    IList<IFCAnyHandle> curves = IFCGeometryInfo.GetCurves();
                                    foreach (IFCAnyHandle curve in curves)
                                        curveSet.Add(curve);

                                    if (curveSet.Count > 0)
                                    {
                                        IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle();
                                        IFCAnyHandle curveRepresentationItem = IFCInstanceExporter.CreateGeometricSet(file, curveSet);
                                        HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>();
                                        bodyItems.Add(curveRepresentationItem);
                                        planRepresentation = RepresentationUtil.CreateGeometricSetRep(exporterIFC, familyInstance, categoryId, "Annotation",
                                           contextOfItems2d, bodyItems);
                                    }
                                }
                            }
                        }
                    }

                    if (doorWindowInfo != null)
                    {
                        typeInfo.StyleTransform = doorWindowTrf.Inverse;
                    }
                    else
                    {
                        if (!MathUtil.IsAlmostZero(extraOffset.DotProduct(extraOffset)))
                        {
                            Transform newTransform = typeInfo.StyleTransform;
                            XYZ newOrig = newTransform.Origin + extraOffset;
                            newTransform.Origin = newOrig;
                            typeInfo.StyleTransform = newTransform;
                        }
                        typeInfo.StyleTransform = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement());
                    }

                    IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file);
                    IFCAnyHandle repMap2dHnd = null;
                    IFCAnyHandle repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRepresentation);

                    IList<IFCAnyHandle> repMapList = new List<IFCAnyHandle>();
                    repMapList.Add(repMap3dHnd);
                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(planRepresentation))
                    {
                        repMap2dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, planRepresentation);
                        repMapList.Add(repMap2dHnd);
                    }

                    // for Door, Window
                    bool paramTakesPrecedence = false; // For Revit, this is currently always false.
                    bool sizeable = false;

                    // for many
                    HashSet<IFCAnyHandle> propertySets = new HashSet<IFCAnyHandle>();

                    string guid = GUIDUtil.CreateGUID(familySymbol);
                    string symId = NamingUtil.CreateIFCElementId(familySymbol);

                    // This covers many generic types.  If we can't find it in the list here, do custom exports.
                    IFCAnyHandle typeStyle = FamilyExporterUtil.ExportGenericType(file, exportType, ifcEnumType, guid,
                       ownerHistory, objectType, null, null, propertySets, repMapList, symId, objectType,
                       familyInstance, familySymbol);

                    // Cover special cases not covered above.
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle))
                    {
                        switch (exportType)
                        {
                            case IFCExportType.ExportColumnType:
                                {
                                    // If we are using the instance GRep, then we have to create a generic GUID for the
                                    // column type, as they share the same ElementId.
                                    string colGUID = null;
                                    string colElemId = null;

                                    if (useInstanceGeometry)
                                        colGUID = GUIDUtil.CreateGUID();
                                    else
                                        colGUID = guid;
                                    colElemId = NamingUtil.CreateIFCElementId(familySymbol);

                                    string columnType = "Column";
                                    typeStyle = IFCInstanceExporter.CreateColumnType(file, colGUID, ownerHistory, objectType,
                                       null, null, propertySets, repMapList, colElemId,
                                       objectType, GetColumnType(familyInstance, columnType));

                                    break;
                                }
                            case IFCExportType.ExportDoorType:
                                {
                                    string constructionType = string.Empty;
                                    ParameterUtil.GetStringValueFromElementOrSymbol(familyInstance, "Construction", out constructionType);

                                    IFCAnyHandle doorLining = DoorWindowUtil.CreateDoorLiningProperties(exporterIFC, familyInstance);
                                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(doorLining))
                                        propertySets.Add(doorLining);

                                    IList<IFCAnyHandle> doorPanels = DoorWindowUtil.CreateDoorPanelProperties(exporterIFC, doorWindowInfo,
                                       familyInstance);
                                    propertySets.UnionWith(doorPanels);

                                    string doorStyleGUID = GUIDUtil.CreateGUID();
                                    string doorStyleElemId = NamingUtil.CreateIFCElementId(familySymbol);
                                    typeStyle = IFCInstanceExporter.CreateDoorStyle(file, doorStyleGUID, ownerHistory, objectType,
                                       null, null, propertySets, repMapList, doorStyleElemId,
                                       GetDoorStyleOperation(doorWindowInfo.DoorOperationType), GetDoorStyleConstruction(familyInstance, constructionType),
                                       paramTakesPrecedence, sizeable);
                                    break;
                                }
                            case IFCExportType.ExportSystemFurnitureElementType:
                                {
                                    string furnitureId = NamingUtil.CreateIFCElementId(familySymbol);
                                    typeStyle = IFCInstanceExporter.CreateSystemFurnitureElementType(file, guid, ownerHistory, objectType,
                                       null, null, propertySets, repMapList, furnitureId,
                                       objectType);
                                    break;
                                }
                            case IFCExportType.ExportWindowType:
                                {
                                    Toolkit.IFCWindowStyleOperation operationType = DoorWindowUtil.GetIFCWindowStyleOperation(familySymbol);
                                    IFCWindowStyleConstruction constructionType = DoorWindowUtil.GetIFCWindowStyleConstruction(familyInstance, "");

                                    IFCAnyHandle windowLining = DoorWindowUtil.CreateWindowLiningProperties(exporterIFC, familyInstance, null);
                                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(windowLining))
                                        propertySets.Add(windowLining);

                                    IList<IFCAnyHandle> windowPanels =
                                       DoorWindowUtil.CreateWindowPanelProperties(exporterIFC, familyInstance, null);
                                    propertySets.UnionWith(windowPanels);

                                    string windowStyleGUID = GUIDUtil.CreateGUID();
                                    string windowStyleElemId = NamingUtil.CreateIFCElementId(familySymbol);
                                    typeStyle = IFCInstanceExporter.CreateWindowStyle(file, windowStyleGUID, ownerHistory, objectType,
                                       null, null, propertySets, repMapList, windowStyleElemId,
                                       constructionType, operationType, paramTakesPrecedence, sizeable);
                                    break;
                                }
                            case IFCExportType.ExportBuildingElementProxy:
                            default:
                                {
                                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd))
                                        typeInfo.Map2DHandle = repMap2dHnd;
                                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd))
                                        typeInfo.Map3DHandle = repMap3dHnd;
                                    break;
                                }
                        }
                    }

                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle))
                    {
                        CategoryUtil.CreateMaterialAssociations(doc, exporterIFC, typeStyle, typeInfo.MaterialIds);

                        typeInfo.Style = typeStyle;

                        if (((exportType == IFCExportType.ExportColumnType) && trySpecialColumnCreation) ||
                           (exportType == IFCExportType.ExportMemberType))
                        {
                            typeInfo.ScaledArea = extraParams.ScaledArea;
                            typeInfo.ScaledDepth = extraParams.ScaledLength;
                            typeInfo.ScaledInnerPerimeter = extraParams.ScaledInnerPerimeter;
                            typeInfo.ScaledOuterPerimeter = extraParams.ScaledOuterPerimeter;
                        }

                        ClassificationUtil.CreateUniformatClassification(exporterIFC, file, familySymbol, typeStyle);
                    }
                }
                else if (!creatingType && (trySpecialColumnCreation))
                {
                    // still need to modify instance trf for columns.
                    trf.Origin += GetLevelOffsetForExtrudedColumns(exporterIFC, familyInstance, overrideLevelId, extraParams);
                }

                if (found && !typeInfo.IsValid())
                {
                    typeInfo = currentTypeInfo;
                }

                // we'll pretend we succeeded, but we'll do nothing.
                if (!typeInfo.IsValid())
                    return;

                // add to the map, as long as we are not using range, not using instance geometry, and don't have extra openings.
                if ((range == null) && !useInstanceGeometry && (extraParams.GetOpenings().Count == 0))
                    ExporterCacheManager.TypeObjectsCache.Register(familySymbol.Id, flipped, typeInfo);

                Transform oldTrf = new Transform(trf);
                XYZ scaledMapOrigin = XYZ.Zero;

                trf = trf.Multiply(typeInfo.StyleTransform);

                // create instance.
                IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>();
                {
                    IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle();
                    IFCAnyHandle contextOfItems3d = exporterIFC.Get3DContextHandle("Body");

                    // for proxies, we store the IfcRepresentationMap directly since there is no style.
                    IFCAnyHandle style = typeInfo.Style;
                    IList<IFCAnyHandle> repMapList = !IFCAnyHandleUtil.IsNullOrHasNoValue(style) ?
                        GeometryUtil.GetRepresentationMaps(style) : null;
                    int numReps = repMapList != null ? repMapList.Count : 0;

                    IFCAnyHandle repMap2dHnd = typeInfo.Map2DHandle;
                    IFCAnyHandle repMap3dHnd = typeInfo.Map3DHandle;
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd) && (numReps > 0))
                        repMap3dHnd = repMapList[0];
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd) && (numReps > 1))
                        repMap2dHnd = repMapList[1];

                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd))
                    {
                        IList<IFCAnyHandle> representations = new List<IFCAnyHandle>();
                        representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap3dHnd, scaledMapOrigin));
                        IFCAnyHandle shapeRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, familyInstance, categoryId, contextOfItems3d,
                            representations);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep))
                            return;
                        shapeReps.Add(shapeRep);
                    }

                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd))
                    {
                        HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>();
                        representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap2dHnd, scaledMapOrigin));
                        IFCAnyHandle shapeRep = RepresentationUtil.CreatePlanMappedItemRep(exporterIFC, familyInstance, categoryId, contextOfItems2d,
                            representations);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep))
                            return;
                        shapeReps.Add(shapeRep);
                    }
                }

                IFCAnyHandle boundingBoxRep = null;
                Transform boundingBoxTrf = (brepOffsetTransform != null) ? brepOffsetTransform.Inverse : Transform.Identity;
                if (geomObjects.Count > 0)
                    boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomObjects, boundingBoxTrf);
                else
                {
                    boundingBoxTrf = boundingBoxTrf.Multiply(trf.Inverse);
                    boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, familyInstance.get_Geometry(options), boundingBoxTrf);
                }

                if (boundingBoxRep != null)
                    shapeReps.Add(boundingBoxRep);

                IFCAnyHandle rep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps);

                IFCAnyHandle instanceHandle = null;
                using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, familyInstance, trf, null, overrideLevelId))
                {
                    string instanceGUID = GUIDUtil.CreateGUID(familyInstance);
                    string instanceName = NamingUtil.GetIFCName(familyInstance);
                    string instanceDescription = NamingUtil.GetDescriptionOverride(familyInstance, null);
                    string instanceObjectType = NamingUtil.GetObjectTypeOverride(familyInstance, objectType);
                    string instanceElemId = NamingUtil.CreateIFCElementId(familyInstance);

                    IFCAnyHandle localPlacement = setter.GetPlacement();
                    IFCAnyHandle overrideLocalPlacement = null;

                    if (parentLocalPlacement != null)
                    {
                        Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(parentLocalPlacement, localPlacement);
                        Transform inverseTrf = relTrf.Inverse;

                        IFCAnyHandle relativePlacement = ExporterUtil.CreateAxis2Placement3D(file, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX);
                        IFCAnyHandle plateLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, parentLocalPlacement, relativePlacement);
                        overrideLocalPlacement = plateLocalPlacement;
                    }

                    instanceHandle = FamilyExporterUtil.ExportGenericInstance(exportType, exporterIFC, familyInstance,
                       wrapper, setter, extraParams, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType,
                       exportParts ? null : rep, instanceElemId, overrideLocalPlacement);

                    if (exportParts)
                    {
                        PartExporter.ExportHostPart(exporterIFC, familyInstance, instanceHandle, familyProductWrapper, setter, setter.GetPlacement(), overrideLevelId);
                    }

                    if (ElementFilteringUtil.IsMEPType(exportType))
                        ExporterCacheManager.MEPCache.Register(familyInstance, instanceHandle);

                    switch (exportType)
                    {
                        case IFCExportType.ExportColumnType:
                            {
                                IFCAnyHandle placementToUse = localPlacement;
                                if (!useInstanceGeometry)
                                {
                                    bool needToCreateOpenings =
                                        (cutPairOpeningsForColumns.Count != 0) || OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams);
                                    if (needToCreateOpenings)
                                    {
                                        Transform openingTrf = new Transform(oldTrf);
                                        Transform extraRot = new Transform(oldTrf);
                                        extraRot.Origin = XYZ.Zero;
                                        openingTrf = openingTrf.Multiply(extraRot);
                                        openingTrf = openingTrf.Multiply(typeInfo.StyleTransform);

                                        IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, openingTrf.Origin * scale,
                                           openingTrf.get_Basis(2), openingTrf.get_Basis(0));
                                        IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement);
                                        GeometryUtil.SetRelativePlacement(openingPlacement, openingRelativePlacement);
                                        placementToUse = openingPlacement;
                                    }
                                }

                                OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, cutPairOpeningsForColumns,
                                   exporterIFC, placementToUse, setter, wrapper);
                                OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                                   placementToUse, setter, wrapper);

                                //export Base Quantities.
                                PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo);

                                PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper);
                                break;
                            }
                        case IFCExportType.ExportDoorType:
                        case IFCExportType.ExportWindowType:
                            {
                                double doorHeight = doorWindowInfo.OpeningHeight;
                                if (doorHeight < MathUtil.Eps())
                                    doorHeight = GetMinSymbolHeight(familySymbol);
                                double doorWidth = doorWindowInfo.OpeningWidth;
                                if (doorWidth < MathUtil.Eps())
                                    doorWidth = GetMinSymbolWidth(familySymbol);

                                double height = doorHeight * scale;
                                double width = doorWidth * scale;

                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetLocalPlacement()))
                                    doorWindowInfo.SetLocalPlacement(localPlacement);

                                IFCAnyHandle doorWindowOrigLocalPlacement = doorWindowInfo.GetLocalPlacement();
                                Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, doorWindowOrigLocalPlacement);

                                IFCAnyHandle doorWindowRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, relTrf.Origin, relTrf.BasisZ, relTrf.BasisX);
                                IFCAnyHandle doorWindowLocalPlacement =
                                   IFCInstanceExporter.CreateLocalPlacement(file, doorWindowOrigLocalPlacement, doorWindowRelativePlacement);
                                if (exportType == IFCExportType.ExportDoorType)
                                    instanceHandle = IFCInstanceExporter.CreateDoor(file, instanceGUID, ownerHistory,
                                       instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement,
                                       rep, instanceElemId, height, width);
                                else if (exportType == IFCExportType.ExportWindowType)
                                    instanceHandle = IFCInstanceExporter.CreateWindow(file, instanceGUID, ownerHistory,
                                       instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement,
                                       rep, instanceElemId, height, width);
                                wrapper.AddElement(instanceHandle, setter, extraParams, true);

                                exporterIFC.RegisterSpaceBoundingElementHandle(instanceHandle, familyInstance.Id, setter.LevelId);

                                IFCAnyHandle placementToUse = doorWindowLocalPlacement;
                                if (!useInstanceGeometry)
                                {
                                    // correct the placement to the symbol space
                                    bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams);
                                    if (needToCreateOpenings)
                                    {
                                        Transform openingTrf = Transform.Identity;
                                        openingTrf.Origin = new XYZ(0, 0, setter.Offset);
                                        openingTrf = openingTrf.Multiply(doorWindowTrf);
                                        XYZ scaledOrigin = openingTrf.Origin * exporterIFC.LinearScale;
                                        IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, scaledOrigin, openingTrf.BasisZ, openingTrf.BasisX);
                                        IFCAnyHandle openingLocalPlacement =
                                           IFCInstanceExporter.CreateLocalPlacement(file, doorWindowLocalPlacement, openingRelativePlacement);
                                        placementToUse = openingLocalPlacement;
                                    }
                                }
                                // only necessary when exporting as possible breps.
                                OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                                   placementToUse, setter, wrapper);
                                if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities)
                                    ExporterIFCUtils.CreateDoorWindowBaseQuantities(exporterIFC, instanceHandle, (doorHeight * scale), (doorWidth * scale));

                                PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper);
                                break;
                            }
                        case IFCExportType.ExportMemberType:
                            {
                                OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                                   localPlacement, setter, wrapper);

                                //export Base Quantities.
                                PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo);
                                // TODO: create PropertySet!
                                //createMemberPropertySet(exporter, pFamInst, pWrapper, extraParams);
                                PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper);
                                break;
                            }
                        case IFCExportType.ExportPlateType:
                            {
                                OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                                   localPlacement, setter, wrapper);

                                // TODO: create PropertySet!
                                //createPlatePropertySet(exporter, pFamInst, pWrapper, extraParams);
                                PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper);
                                break;
                            }
                        case IFCExportType.ExportTransportElementType:
                            {
                                IFCAnyHandle localPlacementToUse;
                                ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse);

                                instanceHandle = IFCInstanceExporter.CreateTransportElement(file, instanceGUID, ownerHistory,
                                   instanceName, instanceDescription, instanceObjectType,
                                   localPlacementToUse, rep, instanceElemId, null, null, null);

                                if (roomId == ElementId.InvalidElementId)
                                {
                                    wrapper.AddElement(instanceHandle, setter, extraParams, true);
                                }
                                else
                                {
                                    exporterIFC.RelateSpatialElement(roomId, instanceHandle);
                                    wrapper.AddElement(instanceHandle, setter, extraParams, false);
                                }

                                PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper);
                                break;
                            }
                        case IFCExportType.ExportBuildingElementProxy:
                        default:
                            {
                                bool isBuildingElementProxy = (exportType == IFCExportType.ExportBuildingElementProxy);

                                IFCAnyHandle localPlacementToUse;
                                ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse);

                                if (!isBuildingElementProxy)
                                {
                                    if (FamilyExporterUtil.IsDistributionControlElementSubType(exportType))
                                    {
                                        instanceHandle = IFCInstanceExporter.CreateDistributionControlElement(file, instanceGUID,
                                           ownerHistory, instanceName, instanceDescription, instanceObjectType,
                                           localPlacementToUse, rep, instanceElemId, null);

                                        if (roomId == ElementId.InvalidElementId)
                                        {
                                            wrapper.AddElement(instanceHandle, setter, extraParams, true);
                                        }
                                        else
                                        {
                                            exporterIFC.RelateSpatialElement(roomId, instanceHandle);
                                            wrapper.AddElement(instanceHandle, setter, extraParams, false);
                                        }
                                    }
                                    else if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle))
                                    {
                                        isBuildingElementProxy = true;
                                    }
                                }

                                if (isBuildingElementProxy)
                                {
                                    Toolkit.IFCElementComposition proxyType = Toolkit.IFCElementComposition.Element;

                                    instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(file, instanceGUID,
                                       ownerHistory, instanceName, instanceDescription, instanceObjectType,
                                       localPlacementToUse, rep, instanceElemId, proxyType);

                                    if (roomId == ElementId.InvalidElementId)
                                    {
                                        wrapper.AddElement(instanceHandle, setter, extraParams, true);
                                    }
                                    else
                                    {
                                        exporterIFC.RelateSpatialElement(roomId, instanceHandle);
                                        wrapper.AddElement(instanceHandle, setter, extraParams, false);
                                    }
                                }

                                IFCAnyHandle placementToUse = localPlacement;
                                if (!useInstanceGeometry)
                                {
                                    bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams);
                                    if (needToCreateOpenings)
                                    {
                                        Transform openingTrf = new Transform(oldTrf);
                                        Transform extraRot = new Transform(oldTrf);
                                        extraRot.Origin = XYZ.Zero;
                                        openingTrf = openingTrf.Multiply(extraRot);
                                        openingTrf = openingTrf.Multiply(typeInfo.StyleTransform);

                                        IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, openingTrf.Origin * scale,
                                           openingTrf.get_Basis(2), openingTrf.get_Basis(0));
                                        IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement);
                                        GeometryUtil.SetRelativePlacement(openingPlacement, openingRelativePlacement);
                                        placementToUse = openingPlacement;
                                    }
                                }

                                OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                                   placementToUse, setter, wrapper);
                                PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper);
                                break;
                            }
                    }

                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle))
                    {
                        if (doorWindowInfo != null)
                        {
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetOpening()))
                            {
                                string relGUID = GUIDUtil.CreateGUID();
                                IFCInstanceExporter.CreateRelFillsElement(file, relGUID, ownerHistory, null, null, doorWindowInfo.GetOpening(), instanceHandle);
                            }
                            else if (doorWindowInfo.NeedsOpening)
                            {
                                bool added = doorWindowInfo.SetDelayedFamilyInstance(instanceHandle, localPlacement, doorWindowInfo.AssignedLevelId);
                                if (added)
                                    exporterIFC.RegisterDoorWindowForOpeningUpdate(doorWindowInfo);
                                else
                                {
                                    // we need to fill a later opening.
                                    exporterIFC.RegisterDoorWindowForUncreatedOpening(familyInstance.Id, instanceHandle);
                                }
                            }
                        }

                        if (!exportParts)
                            CategoryUtil.CreateMaterialAssociations(doc, exporterIFC, instanceHandle, typeInfo.MaterialIds);

                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style))
                            ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle);
                    }
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Export the dummy wall to host an orphan part. It usually happens in the cases of associated parts are higher than split sub-wall.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="element">The wall element.</param>
        /// <param name="geometryElement">The geometry of wall.</param>
        /// <param name="origWrapper">The IFCProductWrapper.</param>
        /// <param name="overrideLevelId">The ElementId that will crate the dummy wall.</param>
        /// <param name="range">The IFCRange corresponding to the dummy wall.</param>
        /// <returns>The handle of dummy wall.</returns>
        public static IFCAnyHandle ExportDummyWall(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement,
           IFCProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range)
        {
            using (IFCProductWrapper localWrapper = IFCProductWrapper.Create(origWrapper))
            {
                ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                Wall wallElement = element as Wall;
                if (wallElement == null)
                    return null;

                if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range))
                    return null;

                // get global values.
                Document doc = element.Document;
                double scale = exporterIFC.LinearScale;

                IFCFile file = exporterIFC.GetFile();
                IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

                bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End));

                bool exportParts = PartExporter.CanExportParts(wallElement);
                if (exportParts && !PartExporter.CanExportElementInPartExport(wallElement, validRange ? overrideLevelId : wallElement.Level.Id, validRange))
                    return null;

                string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element);
                IFCAnyHandle wallHnd = null;

                string elemGUID = (validRange) ? ExporterIFCUtils.CreateGUID() : ExporterIFCUtils.CreateGUID(element);
                string elemName = NamingUtil.GetNameOverride(element, exporterIFC.GetName());
                string elemDesc = NamingUtil.GetDescriptionOverride(element, null);
                string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType);
                string elemId = NamingUtil.CreateIFCElementId(element);

                Transform orientationTrf = Transform.Identity;

                using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId))
                {
                    IFCAnyHandle localPlacement = setter.GetPlacement();
                    wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType,
                                    localPlacement, null, elemId);

                    if (exportParts)
                        PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId);

                    IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData();
                    extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ;   // only allow vertical extrusions!
                    extraParams.AreInnerRegionsOpenings = true;
                    localWrapper.AddElement(wallHnd, setter, extraParams, true);

                    PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, localWrapper);

                    ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId;
                    exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId);
                }
                
                return wallHnd;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Main implementation to export walls.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="element">
        /// The element.
        /// </param>
        /// <param name="geometryElement">
        /// The geometry element.
        /// </param>
        /// <param name="origWrapper">
        /// The IFCProductWrapper.
        /// </param>
        /// <param name="overrideLevelId">
        /// The level id.
        /// </param>
        /// <param name="range">
        /// The range to be exported for the element.
        /// </param>
        /// <returns>
        /// The exported wall handle.
        /// </returns>
        public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement,
           IFCProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range)
        {
            using (IFCProductWrapper localWrapper = IFCProductWrapper.Create(origWrapper))
            {
                ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                Wall wallElement = element as Wall;
                FamilyInstance famInstWallElem = element as FamilyInstance;

                if (wallElement == null && famInstWallElem == null)
                    return null;

                if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range))
                    return null;

                // get global values.
                Document doc = element.Document;
                double scale = exporterIFC.LinearScale;

                IFCFile file = exporterIFC.GetFile();
                IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();
                IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis");
                IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body");
              
                IFCRange zSpan = new IFCRange();
                double depth = 0.0;
                bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End));

                bool exportParts = PartExporter.CanExportParts(wallElement);
                if (exportParts && !PartExporter.CanExportElementInPartExport(wallElement, validRange? overrideLevelId : wallElement.Level.Id, validRange))
                    return null;

                // get bounding box height so that we can subtract out pieces properly.
                // only for Wall, not FamilyInstance.
                if (wallElement != null && geometryElement != null)
                {
                    BoundingBoxXYZ boundingBox = element.get_BoundingBox(null);
                    if (boundingBox == null)
                        return null;
                    zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z);

                    // if we have a top clipping plane, modify depth accordingly.
                    double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start;
                    double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End;
                    depth = topHeight - bottomHeight;
                    if (MathUtil.IsAlmostZero(depth))
                        return null;
                    depth *= scale;
                }

                IFCAnyHandle axisRep = null;
                IFCAnyHandle bodyRep = null;

                bool exportingAxis = false;
                Curve curve = null;

                bool exportedAsWallWithAxis = false;
                bool exportedBodyDirectly = false;
                bool exportingInplaceOpenings = false;

                Curve centerCurve = GetWallAxis(wallElement);

                XYZ localXDir = new XYZ(1, 0, 0);
                XYZ localYDir = new XYZ(0, 1, 0);
                XYZ localZDir = new XYZ(0, 0, 1);
                XYZ localOrig = new XYZ(0, 0, 0);
                double eps = MathUtil.Eps();

                if (centerCurve != null)
                {
                    Curve baseCurve = GetWallAxisAtBaseHeight(wallElement);
                    curve = GetWallTrimmedCurve(wallElement, baseCurve);

                    IFCRange curveBounds;
                    XYZ oldOrig;
                    GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig);

                    localOrig = oldOrig;
                    if (baseCurve != null)
                    {
                        if (!validRange || (MathUtil.IsAlmostEqual(range.Start, zSpan.Start)))
                        {
                            XYZ newOrig = baseCurve.Evaluate(curveBounds.Start, false);
                            if (!validRange && (zSpan.Start < newOrig[2] - eps))
                                localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan.Start);
                            else
                                localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]);
                        }
                        else
                        {
                            localOrig = new XYZ(localOrig.X, localOrig.Y, range.Start);
                        }
                    }

                    double dist = localOrig[2] - oldOrig[2];
                    if (!MathUtil.IsAlmostZero(dist))
                    {
                        XYZ moveVec = new XYZ(0, 0, dist);
                        curve = GeometryUtil.MoveCurve(curve, moveVec);
                    }
                    localYDir = localZDir.CrossProduct(localXDir);

                    // ensure that X and Z axes are orthogonal.
                    double xzDot = localZDir.DotProduct(localXDir);
                    if (!MathUtil.IsAlmostZero(xzDot))
                        localXDir = localYDir.CrossProduct(localZDir);
                }

                Transform orientationTrf = Transform.Identity;
                orientationTrf.BasisX = localXDir;
                orientationTrf.BasisY = localYDir;
                orientationTrf.BasisZ = localZDir;
                orientationTrf.Origin = localOrig;

                using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId))
                {
                    IFCAnyHandle localPlacement = setter.GetPlacement();

                    Plane plane = new Plane(localXDir, localYDir, localOrig);  // project curve to XY plane.
                    XYZ projDir = XYZ.BasisZ;

                    // two representations: axis, body.         
                    {
                        if ((centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve)))
                        {
                            exportingAxis = true;

                            string identifierOpt = "Axis";	// IFC2x2 convention
                            string representationTypeOpt = "Curve2D";  // IFC2x2 convention

                            IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false);
                            ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true);
                            IList<IFCAnyHandle> axisItems = info.GetCurves();

                            if (axisItems.Count == 0)
                            {
                                exportingAxis = false;
                            }
                            else
                            {
                                HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>();
                                foreach (IFCAnyHandle axisItem in axisItems)
                                    axisItemSet.Add(axisItem);

                                axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis,
                                   identifierOpt, representationTypeOpt, axisItemSet);
                            }
                        }
                    }

                    IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>();
                    Document document = element.Document;

                    if (wallElement != null && exportingAxis && curve != null)
                    {
                        SolidMeshGeometryInfo solidMeshInfo = 
                            (range == null) ? GeometryUtil.GetSolidMeshGeometry(geometryElement, Transform.Identity) :
                                GeometryUtil.GetClippedSolidMeshGeometry(geometryElement, range);
                                
                        IList<Solid> solids = solidMeshInfo.GetSolids();
                        IList<Mesh> meshes = solidMeshInfo.GetMeshes();
                        if (solids.Count == 0 && meshes.Count == 0)
                            return null;

                        bool useNewCode = false;
                        if (useNewCode && solids.Count == 1 && meshes.Count == 0)
                        {
                            bool completelyClipped;
                            bodyRep = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, wallElement, catId, solids[0], 
                                plane, projDir, range, out completelyClipped);

                            if (completelyClipped)
                                return null;

                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep))
                            {
                                exportedAsWallWithAxis = true;
                                exportedBodyDirectly = true;
                            }
                            else
                            {
                                exportedAsWallWithAxis = false;
                                exportedBodyDirectly = false;
                            }
                        }
                            
                        if (!exportedAsWallWithAxis)
                        {
                            // Fallback - use native routines to try to export wall.
                            bool isCompletelyClipped;
                            bodyRep = FallbackTryToCreateAsExtrusion(exporterIFC, wallElement, solidMeshInfo,
                                catId, curve, plane, depth, zSpan, range, setter, 
                                out cutPairOpenings, out isCompletelyClipped);
                            if (isCompletelyClipped)
                                return null;
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep))
                                exportedAsWallWithAxis = true;
                        }
                    }
                
                    using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData())
                    {
                        ElementId matId = ElementId.InvalidElementId;

                        if (!exportedAsWallWithAxis)
                        {
                            SolidMeshGeometryInfo solidMeshCapsule = null;

                            if (wallElement != null)
                            {
                                if (validRange)
                                {
                                    solidMeshCapsule = GeometryUtil.GetClippedSolidMeshGeometry(geometryElement, range);
                                }
                                else
                                {
                                    solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement);
                                }
                                if (solidMeshCapsule.SolidsCount() == 0 && solidMeshCapsule.MeshesCount() == 0)
                                {
                                    return null;
                                }
                            }
                            else
                            {
                                GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem);
                                if (geomElemToUse != null)
                                {
                                    exportingInplaceOpenings = true;
                                }
                                else
                                {
                                    exportingInplaceOpenings = false;
                                    geomElemToUse = geometryElement;
                                }
                                Transform trf = Transform.Identity;
                                if (geomElemToUse != geometryElement)
                                    trf = famInstWallElem.GetTransform();
                                solidMeshCapsule = GeometryUtil.GetSolidMeshGeometry(geomElemToUse, trf);
                            }

                            IList<Solid> solids = solidMeshCapsule.GetSolids();
                            IList<Mesh> meshes = solidMeshCapsule.GetMeshes();

                            extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ;   // only allow vertical extrusions!
                            extraParams.AreInnerRegionsOpenings = true;

                            BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true);
                            if ((solids.Count > 0) || (meshes.Count > 0))
                            {
                                matId = BodyExporter.GetBestMaterialIdForGeometry(solids, meshes);
                                bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId,
                                    solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd;
                            }
                            else
                            {
                                IList<GeometryObject> geomElemList = new List<GeometryObject>();
                                geomElemList.Add(geometryElement);
                                BodyData bodyData = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId,
                                    geomElemList, bodyExporterOptions, extraParams);
                                bodyRep = bodyData.RepresentationHnd;
                            }

                            if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep))
                            {
                                extraParams.ClearOpenings();
                                return null;
                            }

                            // We will be able to export as a IfcWallStandardCase as long as we have an axis curve.
                            XYZ extrDirUsed = XYZ.Zero;
                            if (extraParams.HasExtrusionDirection)
                            {
                                extrDirUsed = extraParams.ExtrusionDirection;
                                if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0))
                                {
                                    if ((solids.Count == 1) && (meshes.Count == 0))
                                        exportedAsWallWithAxis = exportingAxis;
                                    exportedBodyDirectly = true;
                                }
                            }
                        }

                        IFCAnyHandle prodRep = null;
                        IList<IFCAnyHandle> representations = new List<IFCAnyHandle>();
                        if (exportingAxis)
                            representations.Add(axisRep);

                        representations.Add(bodyRep);
                        prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations);

                        string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element);
                        IFCAnyHandle wallHnd = null;

                        string elemGUID = (validRange) ? ExporterIFCUtils.CreateGUID() : ExporterIFCUtils.CreateGUID(element);
                        string elemName = NamingUtil.GetNameOverride(element, exporterIFC.GetName());
                        string elemDesc = NamingUtil.GetDescriptionOverride(element, null);
                        string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType);
                        string elemId = NamingUtil.CreateIFCElementId(element);

                        if (exportedAsWallWithAxis)
                        {
                            wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType,
                                localPlacement, exportParts ? null : prodRep, elemId);

                            if (exportParts)
                                PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId);

                            localWrapper.AddElement(wallHnd, setter, extraParams, true);

                            OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, exporterIFC, localPlacement, setter, localWrapper);
                            if (exportedBodyDirectly)
                            {
                                OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper);
                            }
                            else
                            {
                                double scaledWidth = wallElement.Width * scale;
                                ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper);
                            }

                            // export Base Quantities
                            if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities)
                            {
                                CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth);
                            }
                        }
                        else
                        {
                            wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType,
                                localPlacement, exportParts ? null : prodRep, elemId);

                            if (exportParts)
                                PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId);

                            localWrapper.AddElement(wallHnd, setter, extraParams, true);

                            // Only export one material for 2x2; for future versions, export the whole list.
                            if (exporterIFC.ExportAs2x2 && (matId != ElementId.InvalidElementId) && !exportParts)
                            {
                                CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, wallHnd, matId);
                            }

                            if (exportingInplaceOpenings)
                            {
                                ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, 0.0, range, setter, localPlacement, localWrapper);
                            }

                            if (exportedBodyDirectly)
                                OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper);
                        }

                        PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, localWrapper);

                        ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId;

                        if (wallElement != null && !exportParts)
                        {
                            if (!exporterIFC.ExportAs2x2 || exportedAsWallWithAxis) //will move this check into ExportHostObject
                                HostObjectExporter.ExportHostObjectMaterials(exporterIFC, wallElement, localWrapper.GetAnElement(),
                                    geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2);
                        }

                        exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId);
                        return wallHnd;
                    }
                }
            }
        }
        /// <summary>
        /// Export Curtain Walls and Roofs.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="allSubElements">Collection of elements contained in the host curtain element.</param>
        /// <param name="element">The element to be exported.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        private static void ExportBase(ExporterIFC exporterIFC, ICollection <ElementId> allSubElements, Element element, ProductWrapper wrapper)
        {
            IFCFile      file         = exporterIFC.GetFile();
            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

            IFCPlacementSetter setter = null;

            using (ProductWrapper curtainWallSubWrapper = ProductWrapper.Create(wrapper, false))
            {
                try
                {
                    Transform    orientationTrf = Transform.Identity;
                    IFCAnyHandle localPlacement = null;
                    setter         = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, ExporterUtil.GetBaseLevelIdForElement(element));
                    localPlacement = setter.GetPlacement();

                    string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element);

                    IFCAnyHandle prodRepHnd = null;
                    IFCAnyHandle elemHnd    = null;
                    string       elemGUID   = GUIDUtil.CreateGUID(element);
                    string       elemName   = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                    string       elemDesc   = NamingUtil.GetDescriptionOverride(element, null);
                    string       elemType   = NamingUtil.GetObjectTypeOverride(element, objectType);
                    string       elemTag    = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element));
                    if (element is Wall || element is CurtainSystem || IsLegacyCurtainElement(element))
                    {
                        elemHnd = IFCInstanceExporter.CreateCurtainWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemTag);
                    }
                    else if (element is RoofBase)
                    {
                        //need to convert the string to enum
                        string ifcEnumType = ExporterUtil.GetIFCTypeFromExportTable(exporterIFC, element);
                        elemHnd = IFCInstanceExporter.CreateRoof(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement,
                                                                 prodRepHnd, elemTag, RoofExporter.GetIFCRoofType(ifcEnumType));
                    }
                    else
                    {
                        return;
                    }

                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd))
                    {
                        return;
                    }

                    wrapper.AddElement(element, elemHnd, setter, null, true);

                    bool         canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements, element.Document);
                    IFCAnyHandle rep = null;
                    if (!canExportCurtainWallAsContainer)
                    {
                        rep = ExportCurtainObjectCommonAsOneBRep(allSubElements, element, exporterIFC, setter, localPlacement);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(rep))
                        {
                            return;
                        }
                    }
                    else
                    {
                        ExportCurtainObjectCommonAsContainer(allSubElements, element, exporterIFC, curtainWallSubWrapper, setter);
                    }

                    ICollection <IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects();
                    if (relatedElementIds.Count > 0)
                    {
                        string guid = GUIDUtil.CreateSubElementGUID(element, (int)IFCCurtainWallSubElements.RelAggregates);
                        HashSet <IFCAnyHandle> relatedElementIdSet = new HashSet <IFCAnyHandle>(relatedElementIds);
                        IFCInstanceExporter.CreateRelAggregates(file, guid, ownerHistory, null, null, elemHnd, relatedElementIdSet);
                    }
                    exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, element.Id, ElementId.InvalidElementId);

                    ExportCurtainWallType(exporterIFC, wrapper, elemHnd, element);
                }
                finally
                {
                    if (setter != null)
                    {
                        setter.Dispose();
                    }
                }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Exports materials for host object.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="hostObject">
        /// The host object.
        /// </param>
        /// <param name="elemHnds">
        /// The host IFC handles.
        /// </param>
        /// <param name="geometryElement">
        /// The geometry element.
        /// </param>
        /// <param name="productWrapper">
        /// The IFCProductWrapper.
        /// </param>
        /// <param name="levelId">
        /// The level id.
        /// </param>
        /// <param name="direction">
        /// The IFCLayerSetDirection.
        /// </param>
        /// <returns>
        /// True if exported successfully, false otherwise.
        /// </returns>
        public static bool ExportHostObjectMaterials(ExporterIFC exporterIFC, HostObject hostObject,
                                                     IList <IFCAnyHandle> elemHnds, GeometryElement geometryElement, IFCProductWrapper productWrapper,
                                                     ElementId levelId, Toolkit.IFCLayerSetDirection direction)
        {
            if (hostObject == null)
            {
                return(true); //nothing to do
            }
            if (elemHnds == null || (elemHnds.Count == 0))
            {
                return(true); //nothing to do
            }
            IFCFile file = exporterIFC.GetFile();

            // Roofs with no components are only allowed one material.  We will arbitrarily choose the thickest material.
            IFCAnyHandle primaryMaterialHnd = null;

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                if (productWrapper != null)
                {
                    productWrapper.ClearFinishMaterials();
                }

                double scale = exporterIFC.LinearScale;

                double scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0;
                Wall   wall = hostObject as Wall;
                if (wall != null)
                {
                    scaledWallWidth = wall.Width * scale;
                    scaledOffset    = -scaledWallWidth / 2.0;
                    BoundingBoxXYZ boundingBox = wall.get_BoundingBox(null);
                    if (boundingBox != null)
                    {
                        wallHeight = boundingBox.Max.Z - boundingBox.Min.Z;
                    }
                }

                ElementId    typeElemId       = hostObject.GetTypeId();
                IFCAnyHandle materialLayerSet = ExporterCacheManager.MaterialLayerSetCache.Find(typeElemId);
                if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet))
                {
                    HostObjAttributes hostObjAttr = hostObject.Document.GetElement(typeElemId) as HostObjAttributes;
                    if (hostObjAttr == null)
                    {
                        return(true); //nothing to do
                    }
                    List <ElementId> matIds = new List <ElementId>();
                    List <double>    widths = new List <double>();
                    List <MaterialFunctionAssignment> functions = new List <MaterialFunctionAssignment>();
                    ElementId         baseMatId = CategoryUtil.GetBaseMaterialIdForElement(hostObject);
                    CompoundStructure cs        = hostObjAttr.GetCompoundStructure();
                    if (cs != null)
                    {
                        //TODO: Vertically compound structures are not yet supported by export.
                        if (!cs.IsVerticallyHomogeneous() && !MathUtil.IsAlmostZero(wallHeight))
                        {
                            cs = cs.GetSimpleCompoundStructure(wallHeight, wallHeight / 2.0);
                        }

                        for (int i = 0; i < cs.LayerCount; ++i)
                        {
                            ElementId matId = cs.GetMaterialId(i);
                            if (matId != ElementId.InvalidElementId)
                            {
                                matIds.Add(matId);
                            }
                            else
                            {
                                matIds.Add(baseMatId);
                            }
                            widths.Add(cs.GetLayerWidth(i));
                            // save layer function into IFCProductWrapper,
                            // it's used while exporting "Function" of Pset_CoveringCommon
                            functions.Add(cs.GetLayerFunction(i));
                        }
                    }

                    if (matIds.Count == 0)
                    {
                        matIds.Add(baseMatId);
                        widths.Add(cs != null ? cs.GetWidth() : 0);
                        functions.Add(MaterialFunctionAssignment.None);
                    }

                    List <IFCAnyHandle> layers = new List <IFCAnyHandle>();
                    double thickestLayer       = 0.0;
                    for (int i = 0; i < matIds.Count; ++i)
                    {
                        if (widths[i] < MathUtil.Eps())
                        {
                            continue;
                        }

                        IFCAnyHandle materialHnd = CategoryUtil.GetOrCreateMaterialHandle(hostObjAttr.Document, exporterIFC, matIds[i]);
                        if (primaryMaterialHnd == null || (widths[i] > thickestLayer))
                        {
                            primaryMaterialHnd = materialHnd;
                            thickestLayer      = widths[i];
                        }

                        double       scaledWidth   = widths[i] * scale;
                        IFCAnyHandle materialLayer = IFCInstanceExporter.CreateMaterialLayer(file, materialHnd, scaledWidth, null);
                        layers.Add(materialLayer);
                        if ((productWrapper != null) && (functions[i] == MaterialFunctionAssignment.Finish1 || functions[i] == MaterialFunctionAssignment.Finish2))
                        {
                            productWrapper.AddFinishMaterial(materialHnd);
                        }
                    }

                    if (layers.Count == 0)
                    {
                        return(false);
                    }

                    string layerSetName = NamingUtil.CreateIFCFamilyName(exporterIFC, -1);
                    materialLayerSet = IFCInstanceExporter.CreateMaterialLayerSet(file, layers, layerSetName);

                    ExporterCacheManager.MaterialLayerSetCache.Register(typeElemId, materialLayerSet);
                }

                // IfcMaterialLayerSetUsage is not supported for IfcWall, only IfcWallStandardCase.
                IFCAnyHandle layerSetUsage = null;
                for (int ii = 0; ii < elemHnds.Count; ii++)
                {
                    IFCAnyHandle elemHnd = elemHnds[ii];
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd))
                    {
                        continue;
                    }

                    HashSet <IFCAnyHandle> relDecomposesSet = IFCAnyHandleUtil.GetRelDecomposes(elemHnd);

                    IList <IFCAnyHandle> subElemHnds = new List <IFCAnyHandle>();
                    if (relDecomposesSet != null && relDecomposesSet.Count == 1)
                    {
                        IFCAnyHandle relAggregates = relDecomposesSet.First();
                        if (IFCAnyHandleUtil.IsTypeOf(relAggregates, IFCEntityType.IfcRelAggregates))
                        {
                            IFCData ifcData = relAggregates.GetAttribute("RelatedObjects");
                            if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
                            {
                                IFCAggregate aggregate = ifcData.AsAggregate();
                                if (aggregate != null && aggregate.Count > 0)
                                {
                                    foreach (IFCData val in aggregate)
                                    {
                                        if (val.PrimitiveType == IFCDataPrimitiveType.Instance)
                                        {
                                            subElemHnds.Add(val.AsInstance());
                                        }
                                    }
                                }
                            }
                        }
                    }

                    bool hasSubElems = !(subElemHnds.Count == 0);
                    bool isRoof      = IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcRoof);
                    if (!hasSubElems && !isRoof && !IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcWall))
                    {
                        if (layerSetUsage == null)
                        {
                            bool flipDirSense = true;
                            if (wall != null)
                            {
                                // if we have flipped the center curve on export, we need to take that into account here.
                                // We flip the center curve on export if it is an arc and it has a negative Z direction.
                                LocationCurve locCurve = wall.Location as LocationCurve;
                                if (locCurve != null)
                                {
                                    Curve curve        = locCurve.Curve;
                                    Plane defPlane     = new Plane(XYZ.BasisX, XYZ.BasisY, XYZ.Zero);
                                    bool  curveFlipped = GeometryUtil.MustFlipCurve(defPlane, curve);
                                    flipDirSense = !(wall.Flipped ^ curveFlipped);
                                }
                            }
                            else if (hostObject is Floor)
                            {
                                flipDirSense = false;
                            }

                            double            offsetFromReferenceLine = flipDirSense ? -scaledOffset : scaledOffset;
                            IFCDirectionSense sense = flipDirSense ? IFCDirectionSense.Negative : IFCDirectionSense.Positive;

                            layerSetUsage = IFCInstanceExporter.CreateMaterialLayerSetUsage(file, materialLayerSet, direction, sense, offsetFromReferenceLine);
                        }
                        ExporterCacheManager.MaterialLayerRelationsCache.Add(layerSetUsage, elemHnd);
                    }
                    else
                    {
                        if (hasSubElems)
                        {
                            foreach (IFCAnyHandle subElemHnd in subElemHnds)
                            {
                                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(subElemHnd))
                                {
                                    ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, subElemHnd);
                                }
                            }
                        }
                        else if (!isRoof)
                        {
                            ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, elemHnd);
                        }
                        else if (primaryMaterialHnd != null)
                        {
                            ExporterCacheManager.MaterialLayerRelationsCache.Add(primaryMaterialHnd, elemHnd);
                        }
                    }

                    exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, hostObject.Id, levelId);
                }

                tr.Commit();
                return(true);
            }
        }
        /// <summary>
        /// Export Curtain Walls and Roofs.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="allSubElements">Collection of elements contained in the host curtain element.</param>
        /// <param name="element">The element to be exported.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        private static void ExportBase(ExporterIFC exporterIFC, ICollection<ElementId> allSubElements, Element element, ProductWrapper wrapper)
        {
            IFCFile file = exporterIFC.GetFile();
            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

            IFCPlacementSetter setter = null;

            using (ProductWrapper curtainWallSubWrapper = ProductWrapper.Create(wrapper, false))
            {
                try
                {
                    ElementId curtainWallLevel = ElementId.InvalidElementId;
                    if (element.Level != null)
                    {
                        curtainWallLevel = element.Level.Id;
                    }
                    Transform orientationTrf = Transform.Identity;
                    IFCAnyHandle localPlacement = null;
                    setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, curtainWallLevel);
                    localPlacement = setter.GetPlacement();

                    string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element);

                    IFCAnyHandle prodRepHnd = null;
                    IFCAnyHandle elemHnd = null;
                    string elemGUID = GUIDUtil.CreateGUID(element);
                    string elemName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                    string elemDesc = NamingUtil.GetDescriptionOverride(element, null);
                    string elemType = NamingUtil.GetObjectTypeOverride(element, objectType);
                    string elemTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element));
                    if (element is Wall || element is CurtainSystem || IsLegacyCurtainElement(element))
                    {
                        elemHnd = IFCInstanceExporter.CreateCurtainWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemTag);
                    }
                    else if (element is RoofBase)
                    {
                        //need to convert the string to enum
                        string ifcEnumType = CategoryUtil.GetIFCEnumTypeName(exporterIFC, element);
                        elemHnd = IFCInstanceExporter.CreateRoof(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement,
                            prodRepHnd, elemTag, RoofExporter.GetIFCRoofType(ifcEnumType));
                    }
                    else
                    {
                        return;
                    }

                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd))
                        return;

                    wrapper.AddElement(elemHnd, setter, null, true);

                    bool canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements, element.Document);
                    IFCAnyHandle rep = null;
                    if (!canExportCurtainWallAsContainer)
                    {
                        rep = ExportCurtainObjectCommonAsOneBRep(allSubElements, element, exporterIFC, setter, localPlacement);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(rep))
                            return;
                    }
                    else
                    {
                        ExportCurtainObjectCommonAsContainer(allSubElements, element, exporterIFC, curtainWallSubWrapper, setter);
                    }

                    PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, wrapper);
                    ICollection<IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects();
                    if (relatedElementIds.Count > 0)
                    {
                        string guid = ExporterIFCUtils.CreateSubElementGUID(element, (int)IFCCurtainWallSubElements.RelAggregates);
                        HashSet<IFCAnyHandle> relatedElementIdSet = new HashSet<IFCAnyHandle>(relatedElementIds);
                        IFCInstanceExporter.CreateRelAggregates(file, guid, ownerHistory, null, null, elemHnd, relatedElementIdSet);
                    }
                    exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, element.Id, ElementId.InvalidElementId);

                }
                finally
                {
                    if (setter != null)
                        setter.Dispose();
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Exports materials for host object.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="hostObject">
        /// The host object.
        /// </param>
        /// <param name="elemHnds">
        /// The host IFC handles.
        /// </param>
        /// <param name="geometryElement">
        /// The geometry element.
        /// </param>
        /// <param name="productWrapper">
        /// The ProductWrapper.
        /// </param>
        /// <param name="levelId">
        /// The level id.
        /// </param>
        /// <param name="direction">
        /// The IFCLayerSetDirection.
        /// </param>
        /// <returns>
        /// True if exported successfully, false otherwise.
        /// </returns>
        public static bool ExportHostObjectMaterials(ExporterIFC exporterIFC, HostObject hostObject,
            IList<IFCAnyHandle> elemHnds, GeometryElement geometryElement, ProductWrapper productWrapper,
            ElementId levelId, Toolkit.IFCLayerSetDirection direction)
        {
            if (hostObject == null)
                return true; //nothing to do

            if (elemHnds == null || (elemHnds.Count == 0))
                return true; //nothing to do

            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                if (productWrapper != null)
                    productWrapper.ClearFinishMaterials();

                double scale = exporterIFC.LinearScale;

                double scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0;
                Wall wall = hostObject as Wall;
                if (wall != null)
                {
                    scaledWallWidth = wall.Width * scale;
                    scaledOffset = -scaledWallWidth / 2.0;
                    BoundingBoxXYZ boundingBox = wall.get_BoundingBox(null);
                    if (boundingBox != null)
                        wallHeight = boundingBox.Max.Z - boundingBox.Min.Z;
                }

                ElementId typeElemId = hostObject.GetTypeId();
                IFCAnyHandle materialLayerSet = ExporterCacheManager.MaterialLayerSetCache.Find(typeElemId);
                // Roofs with no components are only allowed one material.  We will arbitrarily choose the thickest material.
                IFCAnyHandle primaryMaterialHnd = ExporterCacheManager.MaterialLayerSetCache.FindPrimaryMaterialHnd(typeElemId);
                if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet))
                {
                    HostObjAttributes hostObjAttr = hostObject.Document.GetElement(typeElemId) as HostObjAttributes;
                    if (hostObjAttr == null)
                        return true; //nothing to do

                    List<ElementId> matIds = new List<ElementId>();
                    List<double> widths = new List<double>();
                    List<MaterialFunctionAssignment> functions = new List<MaterialFunctionAssignment>();
                    ElementId baseMatId = CategoryUtil.GetBaseMaterialIdForElement(hostObject);
                    CompoundStructure cs = hostObjAttr.GetCompoundStructure();
                    if (cs != null)
                    {
                        //TODO: Vertically compound structures are not yet supported by export.
                        if (!cs.IsVerticallyHomogeneous() && !MathUtil.IsAlmostZero(wallHeight))
                            cs = cs.GetSimpleCompoundStructure(wallHeight, wallHeight / 2.0);

                        for (int i = 0; i < cs.LayerCount; ++i)
                        {
                            ElementId matId = cs.GetMaterialId(i);
                            if (matId != ElementId.InvalidElementId)
                            {
                                matIds.Add(matId);
                            }
                            else
                            {
                                matIds.Add(baseMatId);
                            }
                            widths.Add(cs.GetLayerWidth(i));
                            // save layer function into ProductWrapper,
                            // it's used while exporting "Function" of Pset_CoveringCommon
                            functions.Add(cs.GetLayerFunction(i));
                        }
                    }

                    if (matIds.Count == 0)
                    {
                        matIds.Add(baseMatId);
                        widths.Add(cs != null ? cs.GetWidth() : 0);
                        functions.Add(MaterialFunctionAssignment.None);
                    }

                    List<IFCAnyHandle> layers = new List<IFCAnyHandle>();
                    double thickestLayer = 0.0;
                    for (int i = 0; i < matIds.Count; ++i)
                    {
                        if (widths[i] < MathUtil.Eps())
                            continue;

                        IFCAnyHandle materialHnd = CategoryUtil.GetOrCreateMaterialHandle(hostObjAttr.Document, exporterIFC, matIds[i], true);
                        if (primaryMaterialHnd == null || (widths[i] > thickestLayer))
                        {
                            primaryMaterialHnd = materialHnd;
                            thickestLayer = widths[i];
                        }

                        double scaledWidth = widths[i] * scale;
                        IFCAnyHandle materialLayer = IFCInstanceExporter.CreateMaterialLayer(file, materialHnd, scaledWidth, null);
                        layers.Add(materialLayer);
                        if ((productWrapper != null) && (functions[i] == MaterialFunctionAssignment.Finish1 || functions[i] == MaterialFunctionAssignment.Finish2))
                        {
                            productWrapper.AddFinishMaterial(materialHnd);
                        }
                    }

                    if (layers.Count == 0)
                        return false;

                    string layerSetName = exporterIFC.GetFamilyName();
                    materialLayerSet = IFCInstanceExporter.CreateMaterialLayerSet(file, layers, layerSetName);

                    ExporterCacheManager.MaterialLayerSetCache.Register(typeElemId, materialLayerSet);
                    ExporterCacheManager.MaterialLayerSetCache.RegisterPrimaryMaterialHnd(typeElemId, primaryMaterialHnd);
                }

                // IfcMaterialLayerSetUsage is not supported for IfcWall, only IfcWallStandardCase.
                IFCAnyHandle layerSetUsage = null;
                for (int ii = 0; ii < elemHnds.Count; ii++)
                {
                    IFCAnyHandle elemHnd = elemHnds[ii];
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd))
                        continue;

                    HashSet<IFCAnyHandle> relDecomposesSet = IFCAnyHandleUtil.GetRelDecomposes(elemHnd);

                    IList<IFCAnyHandle> subElemHnds = new List<IFCAnyHandle>();
                    if (relDecomposesSet != null && relDecomposesSet.Count == 1)
                    {
                        IFCAnyHandle relAggregates = relDecomposesSet.First();
                        if (IFCAnyHandleUtil.IsTypeOf(relAggregates, IFCEntityType.IfcRelAggregates))
                        {
                            IFCData ifcData = relAggregates.GetAttribute("RelatedObjects");
                            if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
                            {
                                IFCAggregate aggregate = ifcData.AsAggregate();
                                if (aggregate != null && aggregate.Count > 0)
                                {
                                    foreach (IFCData val in aggregate)
                                    {
                                        if (val.PrimitiveType == IFCDataPrimitiveType.Instance)
                                        {
                                            subElemHnds.Add(val.AsInstance());
                                        }
                                    }
                                }
                            }
                        }
                    }

                    bool hasSubElems = !(subElemHnds.Count == 0);
                    bool isRoof = IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcRoof);
                    if (!hasSubElems && !isRoof && !IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcWall))
                    {
                        if (layerSetUsage == null)
                        {
                            bool flipDirSense = true;
                            if (wall != null)
                            {
                                // if we have flipped the center curve on export, we need to take that into account here.
                                // We flip the center curve on export if it is an arc and it has a negative Z direction.
                                LocationCurve locCurve = wall.Location as LocationCurve;
                                if (locCurve != null)
                                {
                                    Curve curve = locCurve.Curve;
                                    Plane defPlane = new Plane(XYZ.BasisX, XYZ.BasisY, XYZ.Zero);
                                    bool curveFlipped = GeometryUtil.MustFlipCurve(defPlane, curve);
                                    flipDirSense = !(wall.Flipped ^ curveFlipped);
                                }
                            }
                            else if (hostObject is Floor)
                            {
                                flipDirSense = false;
                            }

                            double offsetFromReferenceLine = flipDirSense ? -scaledOffset : scaledOffset;
                            IFCDirectionSense sense = flipDirSense ? IFCDirectionSense.Negative : IFCDirectionSense.Positive;

                            layerSetUsage = IFCInstanceExporter.CreateMaterialLayerSetUsage(file, materialLayerSet, direction, sense, offsetFromReferenceLine);
                        }
                        ExporterCacheManager.MaterialLayerRelationsCache.Add(layerSetUsage, elemHnd);
                    }
                    else
                    {
                        if (hasSubElems)
                        {
                            foreach (IFCAnyHandle subElemHnd in subElemHnds)
                            {
                                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(subElemHnd))
                                    ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, subElemHnd);
                            }
                        }
                        else if (!isRoof)
                        {
                            ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, elemHnd);
                        }
                        else if (primaryMaterialHnd != null)
                        {
                            ExporterCacheManager.MaterialLayerRelationsCache.Add(primaryMaterialHnd, elemHnd);
                        }
                    }

                    exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, hostObject.Id, levelId);
                }

                tr.Commit();
                return true;
            }
        }
        /// <summary>
        /// Exports a family instance as a mapped item.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="familyInstance">
        /// The family instance to be exported.
        /// </param>
        /// <param name="exportType">
        /// The export type.
        /// </param>
        /// <param name="ifcEnumType">
        /// The string value represents the IFC type.
        /// </param>
        /// <param name="wrapper">
        /// The IFCProductWrapper.
        /// </param>
        /// <param name="overrideLevelId">
        /// The level id.
        /// </param>
        /// <param name="range">
        /// The range of this family instance to be exported.
        /// </param>
        public static void ExportFamilyInstanceAsMappedItem(ExporterIFC exporterIFC,
           FamilyInstance familyInstance, IFCExportType exportType, string ifcEnumType,
           IFCProductWrapper wrapper, ElementId overrideLevelId, UV range)
        {
            Document doc = familyInstance.Document;
            IFCFile file = exporterIFC.GetFile();

            FamilySymbol familySymbol = ExporterIFCUtils.GetOriginalSymbol(familyInstance);
            if (familySymbol == null)
                return;

            IFCProductWrapper familyProductWrapper = IFCProductWrapper.Create(wrapper);
            double scale = exporterIFC.LinearScale;

            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

            HostObject hostElement = familyInstance.Host as HostObject; //hostElement could be null
            ElementId categoryId = CategoryUtil.GetSafeCategoryId(familySymbol);

            //string emptyString = "";
            string familyName = familySymbol.Name;
            IFCLabel objectType = IFCLabel.Create(familyName);

            // A Family Instance can have its own copy of geometry, or use the symbol's copy with a transform.
            // The routine below tells us whether to use the Instance's copy or the Symbol's copy.
            bool useInstanceGeometry = ExporterIFCUtils.UsesInstanceGeometry(familyInstance);

            IList<IFCExtrusionData> cutPairOpeningsForColumns = new List<IFCExtrusionData>();
            IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData();

            Transform trf = familyInstance.GetTransform();

            // Extra information if we are exporting a door or a window.
            IFCDoorWindowInfo doorWindowInfo = null;
            if (exportType == IFCExportType.ExportDoorType)
                doorWindowInfo = IFCDoorWindowInfo.CreateDoorInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf);
            else if (exportType == IFCExportType.ExportWindowType)
                doorWindowInfo = IFCDoorWindowInfo.CreateWindowInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf);

            IFCTypeInfo typeInfo = new IFCTypeInfo();
            XYZ extraOffset = XYZ.Zero;

            bool flipped = doorWindowInfo != null ? doorWindowInfo.IsSymbolFlipped : false;
            IFCTypeInfo currentTypeInfo = exporterIFC.FindType(familySymbol.Id, flipped);
            bool found = currentTypeInfo.IsValid();

            Family family = familySymbol.Family;

            // TODO: this code to be removed by ExtrusionAnalyzer code.
            bool trySpecialColumnCreation = ((exportType == IFCExportType.ExportColumnType) && (!family.IsInPlace));

            // We will create a new mapped type if:
            // 1.  We are exporting part of a column or in-place wall (range != null), OR
            // 2.  We are using the instance's copy of the geometry (that it, it has unique geometry), OR
            // 3.  We haven't already created the type.
            bool creatingType = ((range != null) || useInstanceGeometry || !found);
            if (creatingType)
            {
                IFCAnyHandle bodyRepresentation = IFCAnyHandle.Create();
                IFCAnyHandle planRepresentation = IFCAnyHandle.Create();

                // If we are using the instance geometry, ignore the transformation.
                if (useInstanceGeometry)
                    trf = Transform.Identity;

                // TODO: this code to be removed by ExtrusionAnalyzer code.
                if (trySpecialColumnCreation)
                {
                    XYZ rangeOffset = trf.Origin;
                    IFCFamilyInstanceExtrusionExportResults results;
                    if (range != null)
                    {
                        results = ExporterIFCUtils.ExportFamilyInstanceAsExtrusion(exporterIFC, familyInstance, useInstanceGeometry, range, overrideLevelId, extraParams);
                    }
                    else
                    {
                        results = ExporterIFCUtils.ExportFamilyInstanceAsExtrusion(exporterIFC, familyInstance, useInstanceGeometry, overrideLevelId, extraParams);
                    }
                    bodyRepresentation = results.GetExtrusionHandle();
                    extraOffset = results.ExtraOffset;
                    cutPairOpeningsForColumns = results.GetCutPairOpenings();

                    if (bodyRepresentation.HasValue)
                    {
                        typeInfo.MaterialId = results.MaterialId;
                        // add in level for real columns, not in-place ones.
                        Element actualLevel =
                           (overrideLevelId == ElementId.InvalidElementId) ? familyInstance.Level : doc.get_Element(overrideLevelId);
                        if (actualLevel != null)
                        {
                            IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(actualLevel.Id);
                            double nonStoryLevelOffset = LevelUtil.GetNonStoryLevelOffsetIfAny(exporterIFC, actualLevel as Level);
                            if (range != null)
                            {
                                rangeOffset = new XYZ(rangeOffset.X, rangeOffset.Y, levelInfo.Elevation + nonStoryLevelOffset);
                            }
                        }
                    }

                    rangeOffset += extraOffset;
                    trf.Origin = rangeOffset;
                }

                Transform doorWindowTrf = Transform.Identity;
                IFCAnyHandle dummyPlacement = IFCAnyHandle.Create();
                if (doorWindowInfo != null)
                {
                    doorWindowTrf = ExporterIFCUtils.GetTransformForDoorOrWindow(familyInstance, familySymbol, doorWindowInfo);
                }
                else
                {
                    dummyPlacement = file.CreateLocalPlacement(IFCAnyHandle.Create(), file.CreateAxis2Placement3D());
                    extraParams.SetLocalPlacement(dummyPlacement);
                }

                bool needToCreate2d = (!exporterIFC.ExportAs2x2);
                bool needToCreate3d = (!bodyRepresentation.HasValue);

                if (needToCreate2d || needToCreate3d)
                {
                    using (IFCTransformSetter trfSetter = IFCTransformSetter.Create())
                    {
                        if (doorWindowInfo != null)
                        {
                            trfSetter.Initialize(exporterIFC, doorWindowTrf);
                        }

                        Options options = new Options();
                        GeometryElement exportGeometry =
                           useInstanceGeometry ? familyInstance.get_Geometry(options) : familySymbol.get_Geometry(options);
                        if (exportGeometry == null)
                            return;

                        if (needToCreate3d)
                        {
                            IFCSolidMeshGeometryInfo solidMeshInfo;

                            if (range == null)
                                solidMeshInfo = ExporterIFCUtils.GetSolidMeshGeometry(exporterIFC, exportGeometry, Transform.Identity);
                            else
                                solidMeshInfo = ExporterIFCUtils.GetClippedSolidMeshGeometry(exporterIFC, range, exportGeometry);

                            IList<Solid> solids = solidMeshInfo.GetSolids();
                            IList<Mesh> polyMeshes = solidMeshInfo.GetMeshes();

                            bool tryToExportAsExtrusion = (!exporterIFC.ExportAs2x2 || (exportType == IFCExportType.ExportColumnType));

                            if (exportType == IFCExportType.ExportColumnType)
                            {
                                extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ;
                            }
                            else
                            {
                                extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryXYZ;
                            }

                            if (solids.Count > 0 || polyMeshes.Count > 0)
                            {
                                bodyRepresentation = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, categoryId, solids, polyMeshes,
                                    tryToExportAsExtrusion, extraParams);
                                typeInfo.MaterialId = BodyExporter.GetBestMaterialIdForGeometry(solids, polyMeshes);
                            }
                            else
                            {
                                IList<GeometryObject> exportedGeometries = new List<GeometryObject>();
                                exportedGeometries.Add(exportGeometry);
                                bodyRepresentation = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, categoryId, exportedGeometries,
                                   tryToExportAsExtrusion, extraParams);
                            }

                            if (!bodyRepresentation.HasValue)
                            {
                                extraParams.ClearOpenings();
                                return;
                            }
                        }

                        // if exporting IFC2x3 (or later), export 2D plan rep of family (if it exists).
                        if (needToCreate2d)
                        {
                            HashSet<IFCAnyHandle> curveSet = new HashSet<IFCAnyHandle>();
                            {
                                Transform planeTrf = doorWindowTrf.Inverse;
                                Plane plane = new Plane(planeTrf.get_Basis(0), planeTrf.get_Basis(1), planeTrf.Origin);
                                XYZ projDir = new XYZ(0, 0, 1);

                                IFCGeometryInfo IFCGeometryInfo = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, true);
                                ExporterIFCUtils.CollectGeometryInfo(exporterIFC, IFCGeometryInfo, exportGeometry, planeTrf.Origin, false);

                                IList<IFCAnyHandle> curves = IFCGeometryInfo.GetCurves();
                                foreach (IFCAnyHandle curve in curves)
                                    curveSet.Add(curve);

                                if (curveSet.Count > 0)
                                {
                                    IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle();
                                    IFCAnyHandle curveRepresentationItem = file.CreateGeometricSet(curveSet);
                                    HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>();
                                    bodyItems.Add(curveRepresentationItem);
                                    planRepresentation = RepresentationUtil.CreateGeometricSetRep(exporterIFC, categoryId, "Annotation",
                                       contextOfItems2d, bodyItems);
                                }
                            }
                        }
                    }
                }

                if (doorWindowInfo != null)
                {
                    typeInfo.SetStyleTransform(doorWindowTrf.Inverse);
                }
                else
                {
                    if (!MathUtil.IsAlmostZero(extraOffset.DotProduct(extraOffset)))
                    {
                        Transform newTransform = typeInfo.GetStyleTransform();
                        XYZ newOrig = newTransform.Origin + extraOffset;
                        newTransform.Origin = newOrig;
                        typeInfo.SetStyleTransform(newTransform);
                    }
                    typeInfo.SetStyleTransform(ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement()));
                }

                IFCLabel descriptionOpt = IFCLabel.Create();
                IFCLabel applicableOccurrenceOpt = IFCLabel.Create();

                IFCAnyHandle origin = file.CreateAxis2Placement3D();
                IFCAnyHandle repMap2dHnd = IFCAnyHandle.Create();
                IFCAnyHandle repMap3dHnd = file.CreateRepresentationMap(origin, bodyRepresentation);

                IList<IFCAnyHandle> repMapList = new List<IFCAnyHandle>();
                repMapList.Add(repMap3dHnd);
                if (planRepresentation.HasValue)
                {
                    repMap2dHnd = file.CreateRepresentationMap(origin, planRepresentation);
                    repMapList.Add(repMap2dHnd);
                }

                // for Door, Window
                bool paramTakesPrecedence = false; // For Revit, this is currently always false.
                bool sizeable = false;

                // for many
                HashSet<IFCAnyHandle> propertySets = new HashSet<IFCAnyHandle>();

                IFCLabel guid = IFCLabel.CreateGUID(familySymbol);
                IFCLabel symIdAsLabel = NamingUtil.CreateIFCElementId(familySymbol);

                // This covers many generic types.  If we can't find it in the list here, do custom exports.
                IFCAnyHandle typeStyle = FamilyExporterUtil.ExportGenericType(file, exportType, ifcEnumType, guid,
                   ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, symIdAsLabel, objectType,
                   familyInstance, familySymbol);

                // Cover special cases not covered above.
                if (!typeStyle.HasValue)
                {
                    switch (exportType)
                    {
                        case IFCExportType.ExportColumnType:
                            {
                                // If we are using the instance GRep, then we have to create a generic GUID for the
                                // column type, as they share the same ElementId.
                                IFCLabel colGUID = IFCLabel.Create();
                                IFCLabel colElemId = IFCLabel.Create();

                                if (useInstanceGeometry)
                                {
                                    colGUID = IFCLabel.CreateGUID();
                                    colElemId = NamingUtil.CreateIFCElementId(familyInstance);
                                }
                                else
                                {
                                    colGUID = guid;
                                    colElemId = NamingUtil.CreateIFCElementId(familySymbol);
                                }

                                string columnType = "Column";
                                typeStyle = file.CreateColumnType(columnType, colGUID, ownerHistory, objectType,
                                   descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, colElemId,
                                   objectType, familyInstance, familySymbol);

                                break;
                            }
                        case IFCExportType.ExportDoorType:
                            {
                                string constructionType = string.Empty;
                                ParameterUtil.GetStringValueFromElementOrSymbol(familyInstance, "Construction", out constructionType);

                                IFCAnyHandle doorLining = DoorWindowUtil.CreateDoorLiningProperties(exporterIFC, familyInstance);
                                if (doorLining.HasValue)
                                    propertySets.Add(doorLining);

                                IList<IFCAnyHandle> doorPanels = DoorWindowUtil.CreateDoorPanelProperties(exporterIFC, doorWindowInfo,
                                   familyInstance);
                                propertySets.UnionWith(doorPanels);

                                IFCLabel doorStyleGUID = IFCLabel.CreateGUID();
                                IFCLabel doorStyleElemId = NamingUtil.CreateIFCElementId(familyInstance);
                                typeStyle = file.CreateDoorStyle(doorStyleGUID, ownerHistory, objectType,
                                   descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, doorStyleElemId,
                                   doorWindowInfo.DoorOperationType, constructionType, paramTakesPrecedence, sizeable);
                                break;
                            }
                        case IFCExportType.ExportSystemFurnitureElementType:
                            {
                                IFCLabel furnitureId = NamingUtil.CreateIFCElementId(familyInstance);
                                typeStyle = file.CreateSystemFurnitureElementType(guid, ownerHistory, objectType,
                                   descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, furnitureId,
                                   objectType);
                                break;
                            }
                        case IFCExportType.ExportWindowType:
                            {
                                IFCWindowStyleOperation operationType = DoorWindowUtil.GetIFCWindowStyleOperation(familySymbol);
                                string constructionType = DoorWindowUtil.GetIFCWindowStyleConstruction(familyInstance, "");

                                IFCAnyHandle windowLining = DoorWindowUtil.CreateWindowLiningProperties(exporterIFC, familyInstance, descriptionOpt);
                                if (windowLining.HasValue)
                                    propertySets.Add(windowLining);

                                IList<IFCAnyHandle> windowPanels =
                                   DoorWindowUtil.CreateWindowPanelProperties(exporterIFC, familyInstance, descriptionOpt);
                                propertySets.UnionWith(windowPanels);

                                IFCLabel windowStyleGUID = IFCLabel.CreateGUID();
                                IFCLabel windowStyleElemId = NamingUtil.CreateIFCElementId(familyInstance);
                                typeStyle = file.CreateWindowStyle(windowStyleGUID, ownerHistory, objectType,
                                   descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, windowStyleElemId,
                                   operationType, constructionType, paramTakesPrecedence, sizeable);
                                break;
                            }
                        case IFCExportType.ExportBuildingElementProxy:
                        default:
                            {
                                typeInfo.Set2DMapHandle(repMap2dHnd);
                                typeInfo.Set3DMapHandle(repMap3dHnd);
                                break;
                            }
                    }
                }

                typeInfo.SetStyle(typeStyle);

                // Transfer extraParams information for certain types.
                if (typeStyle.HasValue)
                {
                    if (((exportType == IFCExportType.ExportColumnType) && trySpecialColumnCreation) ||
                       (exportType == IFCExportType.ExportMemberType))
                    {
                        typeInfo.ScaledArea = extraParams.ScaledArea;
                        typeInfo.ScaledDepth = extraParams.ScaledLength;
                        typeInfo.ScaledInnerPerimeter = extraParams.ScaledInnerPerimeter;
                        typeInfo.ScaledOuterPerimeter = extraParams.ScaledOuterPerimeter;
                    }
                }
            }
            else if (!creatingType && (trySpecialColumnCreation))
            {
                // still need to modify instance trf for columns.
                trf.Origin += GetLevelOffsetForExtrudedColumns(exporterIFC, familyInstance, overrideLevelId, extraParams);
            }

            if (found && !typeInfo.GetStyle().HasValue)
            {
                typeInfo = currentTypeInfo;
            }

            // we'll pretend we succeeded, but we'll do nothing.
            if (!typeInfo.GetStyle().HasValue && !typeInfo.Get2DMapHandle().HasValue && !typeInfo.Get3DMapHandle().HasValue)
                return;

            // add to the map, as long as we are not using range, not using instance geometry, and don't have extra openings.
            if ((range == null) && !useInstanceGeometry && (extraParams.GetOpenings().Count == 0))
                exporterIFC.AddType(familySymbol.Id, flipped, typeInfo);

            Transform oldTrf = new Transform(trf);
            XYZ scaledMapOrigin = XYZ.Zero;

            trf = trf.Multiply(typeInfo.GetStyleTransform());

            // create instance.  
            IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>();
            {
                IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle();
                IFCAnyHandle contextOfItems3d = exporterIFC.Get3DContextHandle();

                // for proxies, we store the IfcRepresentationMap directly since there is no style.
                IList<IFCAnyHandle> repMapList = IFCGeometryUtils.GetRepresentationMaps(typeInfo.GetStyle());
                int numReps = repMapList.Count;

                IFCAnyHandle repMap2dHnd = typeInfo.Get2DMapHandle();
                IFCAnyHandle repMap3dHnd = typeInfo.Get3DMapHandle();
                if (!repMap3dHnd.HasValue && (numReps > 0))
                    repMap3dHnd = repMapList[0];
                if (!repMap2dHnd.HasValue && (numReps > 1))
                    repMap2dHnd = repMapList[1];

                if (repMap3dHnd.HasValue)
                {
                    HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>();
                    representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap3dHnd, scaledMapOrigin));
                    IFCAnyHandle shapeRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, categoryId, contextOfItems3d, representations);
                    if (!shapeRep.HasValue)
                        return;
                    shapeReps.Add(shapeRep);
                }

                if (repMap2dHnd.HasValue)
                {
                    HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>();
                    representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap2dHnd, scaledMapOrigin));
                    IFCAnyHandle shapeRep = RepresentationUtil.CreatePlanMappedItemRep(exporterIFC, categoryId, contextOfItems2d, representations);
                    if (!shapeRep.HasValue)
                        return;
                    shapeReps.Add(shapeRep);
                }
            }

            IFCLabel noDescriptionOpt = IFCLabel.Create();
            IFCLabel noNameOpt = IFCLabel.Create();
            IFCAnyHandle rep = file.CreateProductDefinitionShape(noNameOpt, noDescriptionOpt, shapeReps);

            IFCAnyHandle instanceHandle = IFCAnyHandle.Create();
            using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, familyInstance, trf, null, overrideLevelId))
            {
                IFCLabel instanceGUID = IFCLabel.CreateGUID(familyInstance);
                IFCLabel origInstanceName = NamingUtil.CreateIFCName(exporterIFC, -1);
                IFCLabel instanceName = NamingUtil.GetNameOverride(familyInstance, origInstanceName);
                IFCLabel instanceDescription = NamingUtil.GetDescriptionOverride(familyInstance, noDescriptionOpt);
                IFCLabel instanceObjectType = NamingUtil.GetObjectTypeOverride(familyInstance, objectType);
                IFCLabel instanceElemId = NamingUtil.CreateIFCElementId(familyInstance);

                IFCAnyHandle localPlacement = setter.GetPlacement();
                instanceHandle = FamilyExporterUtil.ExportGenericInstance(exportType, exporterIFC, familyInstance,
                   wrapper, setter, extraParams, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType,
                   rep, instanceElemId);

                switch (exportType)
                {
                    case IFCExportType.ExportColumnType:
                        {
                            IFCAnyHandle placementToUse = localPlacement;
                            if (!useInstanceGeometry)
                            {
                                Transform openingTrf = new Transform(oldTrf);
                                Transform extraRot = new Transform(oldTrf);
                                extraRot.Origin = XYZ.Zero;
                                openingTrf = openingTrf.Multiply(extraRot);
                                openingTrf = openingTrf.Multiply(typeInfo.GetStyleTransform());

                                IFCAnyHandle openingRelativePlacement = file.CreateAxis2Placement3D(openingTrf.Origin * scale,
                                   openingTrf.get_Basis(2), openingTrf.get_Basis(0));
                                IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement);
                                IFCGeometryUtils.SetRelativePlacement(openingPlacement, openingRelativePlacement);
                                placementToUse = openingPlacement;
                            }

                            OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, cutPairOpeningsForColumns,
                               exporterIFC, placementToUse, setter, wrapper);
                            OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                               placementToUse, setter, wrapper);

                            //export Base Quantities.
                            ExporterIFCUtils.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo);

                            CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, instanceHandle, typeInfo.MaterialId);

                            ExporterIFCUtils.CreateColumnPropertySet(exporterIFC, familyInstance, extraParams, wrapper);
                            break;
                        }
                    case IFCExportType.ExportDoorType:
                    case IFCExportType.ExportWindowType:
                        {
                            double doorHeight = doorWindowInfo.OpeningHeight;
                            if (doorHeight < MathUtil.Eps())
                                doorHeight = GetMinSymbolHeight(familySymbol);
                            double doorWidth = doorWindowInfo.OpeningWidth;
                            if (doorWidth < MathUtil.Eps())
                                doorWidth = GetMinSymbolWidth(familySymbol);

                            IFCMeasureValue height = IFCMeasureValue.Create(doorHeight * scale);
                            IFCMeasureValue width = IFCMeasureValue.Create(doorWidth * scale);

                            if (!doorWindowInfo.GetLocalPlacement().HasValue)
                                doorWindowInfo.SetLocalPlacement(localPlacement);

                            IFCAnyHandle doorWindowOrigLocalPlacement = doorWindowInfo.GetLocalPlacement();
                            Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, doorWindowOrigLocalPlacement);

                            IFCAnyHandle doorWindowRelativePlacement = file.CreateAxis2Placement3D(relTrf);
                            IFCAnyHandle doorWindowLocalPlacement =
                               file.CreateLocalPlacement(doorWindowOrigLocalPlacement, doorWindowRelativePlacement);
                            if (exportType == IFCExportType.ExportDoorType)
                                instanceHandle = file.CreateDoor(instanceGUID, ownerHistory,
                                   instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement,
                                   rep, instanceElemId, height, width);
                            else if (exportType == IFCExportType.ExportWindowType)
                                instanceHandle = file.CreateWindow(instanceGUID, ownerHistory,
                                   instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement,
                                   rep, instanceElemId, height, width);
                            wrapper.AddElement(instanceHandle, setter, extraParams, true);

                            exporterIFC.RegisterSpaceBoundingElementHandle(instanceHandle, familyInstance.Id, setter.LevelId);

                            // only necessary when exporting as possible breps.
                            OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                               doorWindowLocalPlacement, setter, wrapper);
                            if (exporterIFC.ExportBaseQuantities)
                                ExporterIFCUtils.CreateDoorWindowBaseQuantities(exporterIFC, instanceHandle, (doorHeight * scale), (doorWidth * scale));

                            if (exportType == IFCExportType.ExportDoorType)
                                ExporterIFCUtils.CreateDoorPropertySet(exporterIFC, familyInstance, wrapper);
                            else
                                ExporterIFCUtils.CreateWindowPropertySet(exporterIFC, familyInstance, wrapper);
                            break;
                        }
                    case IFCExportType.ExportMemberType:
                        {
                            OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                              localPlacement, setter, wrapper);
                            CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, instanceHandle, typeInfo.MaterialId);

                            //export Base Quantities.
                            ExporterIFCUtils.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo);
                            // TODO: create PropertySet!
                            //createMemberPropertySet(exporter, pFamInst, pWrapper, extraParams);
                            ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper);
                            break;
                        }
                    case IFCExportType.ExportPlateType:
                        {
                            OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                              localPlacement, setter, wrapper);
                            CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, instanceHandle, typeInfo.MaterialId);

                            // TODO: create PropertySet!
                            //createPlatePropertySet(exporter, pFamInst, pWrapper, extraParams);
                            ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper);
                            break;
                        }
                    case IFCExportType.ExportTransportElementType:
                        {
                            string operationTypeOpt = "";
                            IFCMeasureValue capByWeightOpt = IFCMeasureValue.Create();
                            IFCMeasureValue capByNumOpt = IFCMeasureValue.Create();

                            IFCAnyHandle localPlacementToUse;
                            ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse);

                            instanceHandle = file.CreateTransportElement(instanceGUID, ownerHistory,
                               instanceName, instanceDescription, instanceObjectType,
                               localPlacementToUse, rep, instanceElemId, operationTypeOpt, capByWeightOpt, capByNumOpt,
                               familyInstance, familySymbol);

                            if (roomId == ElementId.InvalidElementId)
                            {
                                wrapper.AddElement(instanceHandle, setter, extraParams, true);
                            }
                            else
                            {
                                exporterIFC.RelateSpatialElement(roomId, instanceHandle);
                                wrapper.AddElement(instanceHandle, setter, extraParams, false);
                            }

                            ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper);
                            break;
                        }
                    case IFCExportType.ExportBuildingElementProxy:
                    default:
                        {
                            bool isBuildingElementProxy = (exportType == IFCExportType.ExportBuildingElementProxy);

                            if (!isBuildingElementProxy)
                            {
                                if (FamilyExporterUtil.IsDistributionControlElementSubType(exportType))
                                {
                                    IFCLabel controlElementId = IFCLabel.Create();
                                    IFCAnyHandle localPlacementToUse;
                                    ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse);

                                    instanceHandle = file.CreateDistributionControlElement(instanceGUID,
                                       ownerHistory, instanceName, instanceDescription, instanceObjectType,
                                       localPlacement, rep, instanceElemId, controlElementId);

                                    if (roomId == ElementId.InvalidElementId)
                                    {
                                        wrapper.AddElement(instanceHandle, setter, extraParams, true);
                                    }
                                    else
                                    {
                                        exporterIFC.RelateSpatialElement(roomId, instanceHandle);
                                        wrapper.AddElement(instanceHandle, setter, extraParams, false);
                                    }

                                    OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                                       localPlacement, setter, wrapper);
                                }
                                else if (!instanceHandle.HasValue)
                                {
                                    isBuildingElementProxy = true;
                                }
                            }

                            if (isBuildingElementProxy)
                            {
                                IFCElementComposition proxyType = IFCElementComposition.Element;
                                IFCAnyHandle localPlacementToUse;
                                ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse);

                                instanceHandle = file.CreateBuildingElementProxy(instanceGUID,
                                   ownerHistory, instanceName, instanceDescription, instanceObjectType,
                                   localPlacementToUse, rep, instanceElemId, proxyType);

                                if (roomId == ElementId.InvalidElementId)
                                {
                                    wrapper.AddElement(instanceHandle, setter, extraParams, true);
                                }
                                else
                                {
                                    exporterIFC.RelateSpatialElement(roomId, instanceHandle);
                                    wrapper.AddElement(instanceHandle, setter, extraParams, false);
                                }

                                OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC,
                                   localPlacement, setter, wrapper);
                            }

                            ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper);
                            break;
                        }
                }

                if (instanceHandle.HasValue)
                {
                    if (doorWindowInfo != null)
                    {
                        if (doorWindowInfo.GetOpening().HasValue)
                        {
                            IFCLabel relGUID = IFCLabel.CreateGUID();
                            file.CreateRelFillsElement(relGUID, ownerHistory, IFCLabel.Create(), IFCLabel.Create(), doorWindowInfo.GetOpening(), instanceHandle);
                        }
                        else if (doorWindowInfo.NeedsOpening)
                        {
                            bool added = doorWindowInfo.SetDelayedFamilyInstance(instanceHandle, localPlacement, doorWindowInfo.AssignedLevelId);
                            if (added)
                                exporterIFC.RegisterDoorWindowForOpeningUpdate(doorWindowInfo);
                            else
                            {
                                // we need to fill a later opening.
                                exporterIFC.RegisterDoorWindowForUncreatedOpening(familyInstance.Id, instanceHandle);
                            }
                        }
                    }

                    if (typeInfo.GetStyle().HasValue)
                        exporterIFC.AddTypeRelation(typeInfo.GetStyle(), instanceHandle);
                }
            }
        }
        /// <summary>
        /// Export Curtain Walls and Roofs.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="allSubElements">
        /// Collection of elements contained in the host curtain element.
        /// </param>
        /// <param name="hostElement">
        /// The host element to be exported.
        /// </param>
        /// <param name="productWrapper">
        /// The IFCProductWrapper.
        /// </param>
        public static void ExportBase(ExporterIFC exporterIFC, ElementSet allSubElements,
           HostObject hostElement, IFCProductWrapper wrapper)
        {
            IFCFile file = exporterIFC.GetFile();
            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

            IFCPlacementSetter setter = null;
            IFCProductWrapper curtainWallSubWrapper = null;
            try
            {
                IFCAnyHandle localPlacement = IFCAnyHandle.Create();
                bool canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements);
                IFCAnyHandle rep = IFCAnyHandle.Create();
                if (canExportCurtainWallAsContainer)
                {
                    curtainWallSubWrapper = IFCProductWrapper.Create(exporterIFC, true);
                    setter = IFCPlacementSetter.Create(exporterIFC, hostElement);
                    localPlacement = setter.GetPlacement();
                    rep = ExportCurtainObjectCommonAsOneBRep(allSubElements, hostElement, exporterIFC, setter, localPlacement);
                }
                else
                {
                    ExportCurtainObjectCommonAsContainer(allSubElements, hostElement, exporterIFC, out curtainWallSubWrapper);
                    // This has to go LAST.  Why?  Because otherwise we apply the level transform twice -- once in the familyTrf, once here.
                    // This will be used just to put the CurtainWall on the right level.
                    setter = IFCPlacementSetter.Create(exporterIFC, hostElement);
                    localPlacement = setter.GetPlacement();
                }

                if (!rep.HasValue)
                    return;

                IFCLabel objectType = NamingUtil.CreateIFCObjectName(exporterIFC, hostElement);

                IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData();
                extraParams.SetLocalPlacement(localPlacement);

                IFCAnyHandle prodRepHnd = IFCAnyHandle.Create();
                IFCAnyHandle elemHnd = IFCAnyHandle.Create();
                IFCLabel elemGUID = IFCLabel.CreateGUID(hostElement);
                IFCLabel elemName = NamingUtil.GetNameOverride(hostElement, exporterIFC.GetNameFromExportState());
                IFCLabel elemDesc = NamingUtil.GetDescriptionOverride(hostElement, IFCLabel.Create());
                IFCLabel elemType = NamingUtil.GetObjectTypeOverride(hostElement, objectType);
                IFCLabel elemId = NamingUtil.CreateIFCElementId(hostElement);
                if (hostElement is Wall || hostElement is CurtainSystem)
                {
                    elemHnd = file.CreateCurtainWall(elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, elemId, prodRepHnd);
                }
                else if (hostElement is RoofBase)
                {
                    string ifcEnumType = CategoryUtil.GetIFCEnumTypeName(exporterIFC, hostElement);
                    elemHnd = file.CreateRoof(elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, elemId, ifcEnumType, prodRepHnd);
                }
                else
                {
                    return;
                }

                if (!elemHnd.HasValue)
                    return;

                wrapper.AddElement(elemHnd, setter, extraParams, true);
                OpeningUtil.CreateOpeningsIfNecessary(elemHnd, hostElement, extraParams, exporterIFC, localPlacement, setter, wrapper);

                ExporterIFCUtils.CreateCurtainWallPropertySet(exporterIFC, hostElement, wrapper);
                ICollection<IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects();
                if (relatedElementIds.Count > 0)
                {
                    IFCLabel guid = IFCLabel.CreateGUID();
                    IFCLabel nameOpt = IFCLabel.Create();
                    IFCLabel descOpt = IFCLabel.Create();
                    file.CreateRelAggregates(guid, ownerHistory, nameOpt, descOpt, elemHnd, relatedElementIds);
                }
                exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, hostElement.Id, ElementId.InvalidElementId);
            }
            finally
            {
                if (setter != null)
                    setter.Dispose();
                if (curtainWallSubWrapper != null)
                    curtainWallSubWrapper.Dispose();
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Main implementation to export walls.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="element">
        /// The element.
        /// </param>
        /// <param name="geometryElement">
        /// The geometry element.
        /// </param>
        /// <param name="origWrapper">
        /// The ProductWrapper.
        /// </param>
        /// <param name="overrideLevelId">
        /// The level id.
        /// </param>
        /// <param name="range">
        /// The range to be exported for the element.
        /// </param>
        /// <returns>
        /// The exported wall handle.
        /// </returns>
        public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement,
           ProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range)
        {
            IFCFile file = exporterIFC.GetFile();
            using (IFCTransaction tr = new IFCTransaction(file))
            {
                using (ProductWrapper localWrapper = ProductWrapper.Create(origWrapper))
                {
                    ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                    Wall wallElement = element as Wall;
                    FamilyInstance famInstWallElem = element as FamilyInstance;
                    FaceWall faceWall = element as FaceWall;
                    
                    if (wallElement == null && famInstWallElem == null && faceWall == null)
                        return null;

                    if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range))
                        return null;

                    Document doc = element.Document;
                    double scale = exporterIFC.LinearScale;
                    
                    double baseWallElevation = 0.0;
                    ElementId baseLevelId = ExporterUtil.GetBaseLevelIdForElement(element);
                    if (baseLevelId != ElementId.InvalidElementId)
                    {
                        Element baseLevel = doc.GetElement(baseLevelId);
                        if (baseLevel is Level)
                            baseWallElevation = (baseLevel as Level).Elevation;
                    }
                    
                    IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();
                    IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis");
                    IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body");

                    IFCRange zSpan = new IFCRange();
                    double depth = 0.0;
                    bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End));

                    bool exportParts = PartExporter.CanExportParts(element);
                    if (exportParts && !PartExporter.CanExportElementInPartExport(element, validRange ? overrideLevelId : element.Level.Id, validRange))
                        return null;

                    // get bounding box height so that we can subtract out pieces properly.
                    // only for Wall, not FamilyInstance.
                    if (wallElement != null && geometryElement != null)
                    {
                        BoundingBoxXYZ boundingBox = element.get_BoundingBox(null);
                        if (boundingBox == null)
                            return null;
                        zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z);

                        // if we have a top clipping plane, modify depth accordingly.
                        double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start;
                        double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End;
                        depth = topHeight - bottomHeight;
                        if (MathUtil.IsAlmostZero(depth))
                            return null;
                        depth *= scale;
                    }

                    IFCAnyHandle axisRep = null;
                    IFCAnyHandle bodyRep = null;

                    bool exportingAxis = false;
                    Curve curve = null;

                    bool exportedAsWallWithAxis = false;
                    bool exportedBodyDirectly = false;
                    bool exportingInplaceOpenings = false;

                    Curve centerCurve = GetWallAxis(wallElement);

                    XYZ localXDir = new XYZ(1, 0, 0);
                    XYZ localYDir = new XYZ(0, 1, 0);
                    XYZ localZDir = new XYZ(0, 0, 1);
                    XYZ localOrig = new XYZ(0, 0, 0);
                    double eps = MathUtil.Eps();

                    if (centerCurve != null)
                    {
                        Curve baseCurve = GetWallAxisAtBaseHeight(wallElement);
                        curve = GetWallTrimmedCurve(wallElement, baseCurve);

                        IFCRange curveBounds;
                        XYZ oldOrig;
                        GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig);

                        localOrig = oldOrig;
                        if (baseCurve != null)
                        {
                            if (!validRange || (MathUtil.IsAlmostEqual(range.Start, zSpan.Start)))
                            {
                                XYZ newOrig = baseCurve.Evaluate(curveBounds.Start, false);
                                if (!validRange && (zSpan.Start < newOrig[2] - eps))
                                    localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan.Start);
                                else
                                    localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]);
                            }
                            else
                            {
                                localOrig = new XYZ(localOrig.X, localOrig.Y, range.Start);
                            }
                        }

                        double dist = localOrig[2] - oldOrig[2];
                        if (!MathUtil.IsAlmostZero(dist))
                        {
                            XYZ moveVec = new XYZ(0, 0, dist);
                            curve = GeometryUtil.MoveCurve(curve, moveVec);
                        }
                        localYDir = localZDir.CrossProduct(localXDir);

                        // ensure that X and Z axes are orthogonal.
                        double xzDot = localZDir.DotProduct(localXDir);
                        if (!MathUtil.IsAlmostZero(xzDot))
                            localXDir = localYDir.CrossProduct(localZDir);
                    }
                    else
                    {
                        BoundingBoxXYZ boundingBox = element.get_BoundingBox(null);
                        if (boundingBox != null)
                        {
                            XYZ bBoxMin = boundingBox.Min;
                            XYZ bBoxMax = boundingBox.Max;
                            if (validRange)
                                localOrig = new XYZ(bBoxMin.X, bBoxMin.Y, range.Start);
                            else
                                localOrig = boundingBox.Min;

                            XYZ localXDirMax = null;
                            Transform bTrf = boundingBox.Transform;
                            XYZ localXDirMax1 = new XYZ(bBoxMax.X, localOrig.Y, localOrig.Z);
                            localXDirMax1 = bTrf.OfPoint(localXDirMax1);
                            XYZ localXDirMax2 = new XYZ(localOrig.X, bBoxMax.Y, localOrig.Z);
                            localXDirMax2 = bTrf.OfPoint(localXDirMax2);
                            if (localXDirMax1.DistanceTo(localOrig) >= localXDirMax2.DistanceTo(localOrig))
                                localXDirMax = localXDirMax1;
                            else
                                localXDirMax = localXDirMax2;
                            localXDir = localXDirMax.Subtract(localOrig);
                            localXDir = localXDir.Normalize();
                            localYDir = localZDir.CrossProduct(localXDir);

                            // ensure that X and Z axes are orthogonal.
                            double xzDot = localZDir.DotProduct(localXDir);
                            if (!MathUtil.IsAlmostZero(xzDot))
                                localXDir = localYDir.CrossProduct(localZDir);
                        }
                    }

                    Transform orientationTrf = Transform.Identity;
                    orientationTrf.BasisX = localXDir;
                    orientationTrf.BasisY = localYDir;
                    orientationTrf.BasisZ = localZDir;
                    orientationTrf.Origin = localOrig;

                    if (overrideLevelId == ElementId.InvalidElementId)
                        overrideLevelId = ExporterUtil.GetBaseLevelIdForElement(element);
                    using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId))
                    {
                        IFCAnyHandle localPlacement = setter.GetPlacement();

                        Plane plane = new Plane(localXDir, localYDir, localOrig);  // project curve to XY plane.
                        XYZ projDir = XYZ.BasisZ;

                        // two representations: axis, body.         
                        {
                            if (!exportParts && (centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve)))
                            {
                                exportingAxis = true;

                                string identifierOpt = "Axis";	// IFC2x2 convention
                                string representationTypeOpt = "Curve2D";  // IFC2x2 convention

                                IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false);
                                ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true);
                                IList<IFCAnyHandle> axisItems = info.GetCurves();

                                if (axisItems.Count == 0)
                                {
                                    exportingAxis = false;
                                }
                                else
                                {
                                    HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>();
                                    foreach (IFCAnyHandle axisItem in axisItems)
                                        axisItemSet.Add(axisItem);

                                    axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis,
                                       identifierOpt, representationTypeOpt, axisItemSet);
                                }
                            }
                        }

                        IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>();
                        Document document = element.Document;

                        IList<Solid> solids = new List<Solid>();
                        IList<Mesh> meshes = new List<Mesh>();

                        if (!exportParts && wallElement != null && exportingAxis && curve != null)
                        {
                            SolidMeshGeometryInfo solidMeshInfo =
                                (range == null) ? GeometryUtil.GetSplitSolidMeshGeometry(geometryElement) :
                                    GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range);

                            solids = solidMeshInfo.GetSolids();
                            meshes = solidMeshInfo.GetMeshes();
                            if (solids.Count == 0 && meshes.Count == 0)
                                return null;

                            bool useNewCode = false;
                            if (useNewCode && solids.Count == 1 && meshes.Count == 0)
                            {
                                bool completelyClipped;
                                bodyRep = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, wallElement, catId, solids[0],
                                    plane, projDir, range, out completelyClipped);

                                if (completelyClipped)
                                    return null;

                                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep))
                                {
                                    exportedAsWallWithAxis = true;
                                    exportedBodyDirectly = true;
                                }
                                else
                                {
                                    exportedAsWallWithAxis = false;
                                    exportedBodyDirectly = false;
                                }
                            }

                            if (!exportedAsWallWithAxis)
                            {
                                // Fallback - use native routines to try to export wall.
                                bool isCompletelyClipped;
                                bodyRep = FallbackTryToCreateAsExtrusion(exporterIFC, wallElement, solidMeshInfo, baseWallElevation,
                                    catId, curve, plane, depth, zSpan, range, setter,
                                    out cutPairOpenings, out isCompletelyClipped);
                                if (isCompletelyClipped)
                                    return null;
                                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep))
                                    exportedAsWallWithAxis = true;
                            }
                        }

                        using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData())
                        {
                            BodyData bodyData = null;

                            if (!exportedAsWallWithAxis)
                            {
                                SolidMeshGeometryInfo solidMeshCapsule = null;

                                if (wallElement != null || faceWall != null)
                                {
                                    if (validRange)
                                    {
                                        solidMeshCapsule = GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range);
                                    }
                                    else
                                    {
                                        solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement);
                                    }
                                    if (solidMeshCapsule.SolidsCount() == 0 && solidMeshCapsule.MeshesCount() == 0)
                                    {
                                        return null;
                                    }
                                }
                                else
                                {
                                    GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem);
                                    if (geomElemToUse != null)
                                    {
                                        exportingInplaceOpenings = true;
                                    }
                                    else
                                    {
                                        exportingInplaceOpenings = false;
                                        geomElemToUse = geometryElement;
                                    }
                                    Transform trf = Transform.Identity;
                                    if (geomElemToUse != geometryElement)
                                        trf = famInstWallElem.GetTransform();
                                    solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geomElemToUse, trf);
                                }

                                solids = solidMeshCapsule.GetSolids();
                                meshes = solidMeshCapsule.GetMeshes();

                                extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ;   // only allow vertical extrusions!
                                extraParams.AreInnerRegionsOpenings = true;

                                BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true);
                                
                                // Swept solids are not natively exported as part of CV2.0.  
                                // We have removed the UI toggle for this, so that it is by default false, but keep for possible future use.
                                if (ExporterCacheManager.ExportOptionsCache.ExportAdvancedSweptSolids)
                                    bodyExporterOptions.TryToExportAsSweptSolid = true;

                                ElementId overrideMaterialId = ElementId.InvalidElementId;
                                if (wallElement != null)
                                    overrideMaterialId = HostObjectExporter.GetFirstLayerMaterialId(wallElement);

                                if (!exportParts)
                                {
                                    if ((solids.Count > 0) || (meshes.Count > 0))
                                    {
                                        bodyRep = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId,
                                            solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd;
                                    }
                                    else
                                    {
                                        IList<GeometryObject> geomElemList = new List<GeometryObject>();
                                        geomElemList.Add(geometryElement);
                                        bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId,
                                            geomElemList, bodyExporterOptions, extraParams);
                                        bodyRep = bodyData.RepresentationHnd;
                                    }

                                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep))
                                    {
                                        extraParams.ClearOpenings();
                                        return null;
                                    }
                                }

                                // We will be able to export as a IfcWallStandardCase as long as we have an axis curve.
                                XYZ extrDirUsed = XYZ.Zero;
                                if (extraParams.HasExtrusionDirection)
                                {
                                    extrDirUsed = extraParams.ExtrusionDirection;
                                    if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0))
                                    {
                                        if ((solids.Count == 1) && (meshes.Count == 0))
                                            exportedAsWallWithAxis = exportingAxis;
                                        exportedBodyDirectly = true;
                                    }
                                }
                            }

                            IFCAnyHandle prodRep = null;
                            if (!exportParts)
                            {
                                IList<IFCAnyHandle> representations = new List<IFCAnyHandle>();
                                if (exportingAxis)
                                    representations.Add(axisRep);

                                representations.Add(bodyRep);

                                IFCAnyHandle boundingBoxRep = null;
                                if ((solids.Count > 0) || (meshes.Count > 0))
                                    boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solids, meshes, Transform.Identity);
                                else
                                    boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity);

                                if (boundingBoxRep != null)
                                    representations.Add(boundingBoxRep);

                                prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations);
                            }

                            ElementId matId = ElementId.InvalidElementId;
                            string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element);
                            IFCAnyHandle wallHnd = null;

                            string elemGUID = (validRange) ? GUIDUtil.CreateGUID() : GUIDUtil.CreateGUID(element);
                            string elemName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                            string elemDesc = NamingUtil.GetDescriptionOverride(element, null);
                            string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType);
                            string elemTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element));

                            // For Foundation and Retaining walls, allow exporting as IfcFooting instead.
                            bool exportAsFooting = false;
                            string enumTypeValue = null;

                            if (wallElement != null)
                            {
                                WallType wallType = wallElement.WallType;

                                if (wallType != null)
                                {
                                    int wallFunction;
                                    if (ParameterUtil.GetIntValueFromElement(wallType, BuiltInParameter.FUNCTION_PARAM, out wallFunction) != null)
                                    {
                                        if (wallFunction == (int)WallFunction.Retaining || wallFunction == (int)WallFunction.Foundation)
                                        {
                                            // In this case, allow potential to export foundation and retaining walls as footing.
                                            IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, wallElement, out enumTypeValue);
                                            if (exportType == IFCExportType.ExportFooting)
                                                exportAsFooting = true;
                                        }
                                    }
                                }
                            }

                            if (exportedAsWallWithAxis)
                            {
                                if (exportAsFooting)
                                {
                                    Toolkit.IFCFootingType footingType = FootingExporter.GetIFCFootingType(element, enumTypeValue);
                                    wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType,
                                        localPlacement, exportParts ? null : prodRep, elemTag, footingType);
                                }
                                else if (exportParts)
                                {
                                    wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType,
                                        localPlacement, null, elemTag);
                                }
                                else
                                {
                                    wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType,
                                        localPlacement, prodRep, elemTag);
                                }

                                if (exportParts)
                                    PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId);

                                localWrapper.AddElement(element, wallHnd, setter, extraParams, true);

                                if (!exportParts)
                                {
                                    OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, null,
                                        exporterIFC, localPlacement, setter, localWrapper);
                                    if (exportedBodyDirectly)
                                    {
                                        Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity;
                                        OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform,
                                            exporterIFC, localPlacement, setter, localWrapper);
                                    }
                                    else
                                    {
                                        ICollection<IFCAnyHandle> beforeOpenings = localWrapper.GetAllObjects();
                                        double scaledWidth = wallElement.Width * scale;
                                        ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper.ToNative());
                                        ICollection<IFCAnyHandle> afterOpenings = localWrapper.GetAllObjects();
                                        if (beforeOpenings.Count != afterOpenings.Count)
                                        {
                                            foreach (IFCAnyHandle before in beforeOpenings)
                                                afterOpenings.Remove(before);
                                            foreach (IFCAnyHandle potentiallyBadOpening in afterOpenings)
                                            {
                                                PotentiallyCorrectOpeningOrientationAndOpeningType(potentiallyBadOpening, localPlacement, scaledWidth);
                                            }
                                        }
                                    }
                                }

                                // export Base Quantities
                                if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities)
                                {
                                    CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth);
                                }
                            }
                            else
                            {
                                if (exportAsFooting)
                                {
                                    Toolkit.IFCFootingType footingType = FootingExporter.GetIFCFootingType(element, enumTypeValue);
                                    wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType,
                                        localPlacement, exportParts ? null : prodRep, elemTag, footingType);
                                }
                                else
                                {
                                    wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType,
                                        localPlacement, exportParts ? null : prodRep, elemTag);
                                }

                                if (exportParts)
                                    PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId);

                                localWrapper.AddElement(element, wallHnd, setter, extraParams, true);

                                if (!exportParts)
                                {
                                    // Only export one material for 2x2; for future versions, export the whole list.
                                    if (exporterIFC.ExportAs2x2 || famInstWallElem != null)
                                    {
                                        matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids, meshes, element);
                                        if (matId != ElementId.InvalidElementId)
                                            CategoryUtil.CreateMaterialAssociation(exporterIFC, wallHnd, matId);
                                    }

                                    if (exportingInplaceOpenings)
                                    {
                                        ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, 0.0, range, setter, localPlacement, localWrapper.ToNative());
                                    }

                                    if (exportedBodyDirectly)
                                    {
                                        Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity;
                                        OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform,
                                            exporterIFC, localPlacement, setter, localWrapper);
                                    }
                                }
                            }

                            ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId;

                            if ((wallElement != null || faceWall != null) && !exportParts)
                            {
                                HostObject hostObject = null;
                                if (wallElement != null)
                                    hostObject = wallElement;
                                else
                                    hostObject = faceWall;
                                if (!exporterIFC.ExportAs2x2 || exportedAsWallWithAxis)
                                    HostObjectExporter.ExportHostObjectMaterials(exporterIFC, hostObject, localWrapper.GetAnElement(),
                                        geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2, !exportedAsWallWithAxis);
                            }

                            ExportWallType(exporterIFC, localWrapper, wallHnd, element, matId, exportedAsWallWithAxis, exportAsFooting);

                            exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId);

                            tr.Commit();
                            return wallHnd;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Exports a family instance as a mapped item.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="familyInstance">The family instance to be exported.</param>
        /// <param name="exportType">The export type.</param>
        /// <param name="ifcEnumType">The string value represents the IFC type.</param>
        /// <param name="wrapper">The ProductWrapper.</param>
        /// <param name="overrideLevelId">The level id.</param>
        /// <param name="range">The range of this family instance to be exported.</param>
        public static void ExportFamilyInstanceAsMappedItem(ExporterIFC exporterIFC,
           FamilyInstance familyInstance, IFCExportType exportType, string ifcEnumType,
           ProductWrapper wrapper, ElementId overrideLevelId, IFCRange range, IFCAnyHandle parentLocalPlacement)
        {
            bool exportParts = PartExporter.CanExportParts(familyInstance);
            bool isSplit = range != null;
            if (exportParts && !PartExporter.CanExportElementInPartExport(familyInstance, isSplit ? overrideLevelId : familyInstance.Level.Id, isSplit))
                return;

            Document doc = familyInstance.Document;
            IFCFile file = exporterIFC.GetFile();

            // The "originalFamilySymbol" has the right geometry, but should be used as little as possible.
            FamilySymbol originalFamilySymbol = ExporterIFCUtils.GetOriginalSymbol(familyInstance);
            FamilySymbol familySymbol = familyInstance.Symbol;
            if (originalFamilySymbol == null || familySymbol == null)
                return;

            ProductWrapper familyProductWrapper = ProductWrapper.Create(wrapper);
            double scale = exporterIFC.LinearScale;
            Options options = GeometryUtil.GetIFCExportGeometryOptions();

            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

            HostObject hostElement = familyInstance.Host as HostObject; //hostElement could be null
            ElementId categoryId = CategoryUtil.GetSafeCategoryId(familySymbol);

            //string emptyString = "";
            string familyName = familySymbol.Name;
            string revitObjectType = familyName;

            // A Family Instance can have its own copy of geometry, or use the symbol's copy with a transform.
            // The routine below tells us whether to use the Instance's copy or the Symbol's copy.
            bool useInstanceGeometry = ExporterIFCUtils.UsesInstanceGeometry(familyInstance);
            Transform trf = familyInstance.GetTransform();

            using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData())
            {
                bool exportingDoor = (exportType == IFCExportType.ExportDoorType);
                bool exportingWindow = (exportType == IFCExportType.ExportWindowType);
                bool exportingHostParts = PartExporter.CanExportParts(hostElement);
                HostObject hostElementForDoorWindow = exportingHostParts ? null : hostElement;

                // Extra information if we are exporting a door or a window.
                IFCDoorWindowInfo doorWindowInfo = null;
                if (exportingDoor)
                    doorWindowInfo = IFCDoorWindowInfo.CreateDoorInfo(exporterIFC, familyInstance, originalFamilySymbol, hostElementForDoorWindow, overrideLevelId, trf);
                else if (exportingWindow)
                    doorWindowInfo = IFCDoorWindowInfo.CreateWindowInfo(exporterIFC, familyInstance, originalFamilySymbol, hostElementForDoorWindow, overrideLevelId, trf);

                bool ignoreDoorWindowOpening = ((exportingDoor || exportingWindow) && exportingHostParts);

                FamilyTypeInfo typeInfo = new FamilyTypeInfo();

                bool flipped = doorWindowInfo != null ? doorWindowInfo.IsSymbolFlipped : false;
                FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(originalFamilySymbol.Id, flipped);
                bool found = currentTypeInfo.IsValid();

                Family family = familySymbol.Family;

                IList<GeometryObject> geomObjects = new List<GeometryObject>();
                Transform offsetTransform = null;

                Transform doorWindowTrf = Transform.Identity;
                // We will create a new mapped type if:
                // 1.  We are exporting part of a column or in-place wall (range != null), OR
                // 2.  We are using the instance's copy of the geometry (that it, it has unique geometry), OR
                // 3.  We haven't already created the type.
                bool creatingType = ((range != null) || useInstanceGeometry || !found);
                if (creatingType)
                {
                    IFCAnyHandle bodyRepresentation = null;
                    IFCAnyHandle planRepresentation = null;

                    IFCAnyHandle dummyPlacement = null;
                    if (doorWindowInfo != null)
                    {
                        doorWindowTrf = ExporterIFCUtils.GetTransformForDoorOrWindow(familyInstance, originalFamilySymbol, doorWindowInfo);
                    }
                    else
                    {
                        dummyPlacement = IFCInstanceExporter.CreateLocalPlacement(file, null, ExporterUtil.CreateAxis2Placement3D(file));
                        extraParams.SetLocalPlacement(dummyPlacement);
                    }

                    bool needToCreate2d = ExporterCacheManager.ExportOptionsCache.ExportAnnotations;
                    GeometryElement exportGeometry =
                       useInstanceGeometry ? familyInstance.get_Geometry(options) : originalFamilySymbol.get_Geometry(options);

                    if (!exportParts)
                    {
                        using (IFCTransformSetter trfSetter = IFCTransformSetter.Create())
                        {
                            if (doorWindowInfo != null)
                            {
                                trfSetter.Initialize(exporterIFC, doorWindowTrf);
                            }

                            if (exportGeometry == null)
                                return;

                            SolidMeshGeometryInfo solidMeshCapsule = null;

                            if (range == null)
                            {
                                solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(exportGeometry);
                            }
                            else
                            {
                                solidMeshCapsule = GeometryUtil.GetSplitClippedSolidMeshGeometry(exportGeometry, range);
                            }

                            IList<Solid> solids = solidMeshCapsule.GetSolids();
                            IList<Mesh> polyMeshes = solidMeshCapsule.GetMeshes();

                            // If we are exporting parts, it is OK to have no geometry here - it will be added by the host Part.
                            bool hasSolidsOrMeshesInSymbol = (solids.Count > 0 || polyMeshes.Count > 0);

                            if (range != null && !hasSolidsOrMeshesInSymbol)
                                return; // no proper split geometry to export.

                            if (hasSolidsOrMeshesInSymbol)
                            {
                                geomObjects = FamilyExporterUtil.RemoveSolidsAndMeshesSetToDontExport(doc, exporterIFC, solids, polyMeshes);
                                if ((geomObjects.Count == 0))
                                    return; // no proper visible split geometry to export.
                            }
                            else
                                geomObjects.Add(exportGeometry);


                            bool tryToExportAsExtrusion = (!ExporterCacheManager.ExportOptionsCache.ExportAs2x2 || (exportType == IFCExportType.ExportColumnType));

                            if (exportType == IFCExportType.ExportColumnType)
                            {
                                extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ;

                                if (ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && solids.Count > 0)
                                {
                                    LocationPoint point = familyInstance.Location as LocationPoint;
                                    XYZ orig = XYZ.Zero;
                                    if (point != null)
                                        orig = point.Point;

                                    Plane plane = new Plane(XYZ.BasisX, XYZ.BasisY, orig);
                                    bool completelyClipped = false;
                                    HashSet<ElementId> materialIds = null;
                                    bodyRepresentation = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, familyInstance,
                                        categoryId, solids, plane, XYZ.BasisZ, null, out completelyClipped, out materialIds);
                                    typeInfo.MaterialIds = materialIds;
                                }
                            }
                            else
                            {
                                extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryXYZ;
                            }

                            BodyData bodyData = null;
                            if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation))
                            {
                                BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(tryToExportAsExtrusion);
                                bodyData = BodyExporter.ExportBody(exporterIFC, familyInstance, categoryId, ElementId.InvalidElementId,
                                    geomObjects, bodyExporterOptions, extraParams);
                                typeInfo.MaterialIds = bodyData.MaterialIds;
                                bodyRepresentation = bodyData.RepresentationHnd;
                                offsetTransform = bodyData.OffsetTransform;
                            }

                            // We will allow a door or window to be exported without any geometry, or an element with parts.
                            // Anything else doesn't really make sense.
                            if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation) && (doorWindowInfo == null))
                            {
                                extraParams.ClearOpenings();
                                return;
                            }
                        }

                        // By default: if exporting IFC2x3 or later, export 2D plan rep of family, if it exists, unless we are exporting Coordination View V2.
                        // This default can be overridden in the export options.
                        if (needToCreate2d)
                        {
                            XYZ curveOffset = new XYZ(0, 0, 0);
                            if (offsetTransform != null)
                                curveOffset = -offsetTransform.Origin / scale;

                            HashSet<IFCAnyHandle> curveSet = new HashSet<IFCAnyHandle>();
                            {
                                Transform planeTrf = doorWindowTrf.Inverse;
                                Plane plane = new Plane(planeTrf.get_Basis(0), planeTrf.get_Basis(1), planeTrf.Origin);
                                XYZ projDir = new XYZ(0, 0, 1);

                                IFCGeometryInfo IFCGeometryInfo = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, true);
                                ExporterIFCUtils.CollectGeometryInfo(exporterIFC, IFCGeometryInfo, exportGeometry, curveOffset, false);

                                IList<IFCAnyHandle> curves = IFCGeometryInfo.GetCurves();
                                foreach (IFCAnyHandle curve in curves)
                                    curveSet.Add(curve);

                                if (curveSet.Count > 0)
                                {
                                    IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle();
                                    IFCAnyHandle curveRepresentationItem = IFCInstanceExporter.CreateGeometricSet(file, curveSet);
                                    HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>();
                                    bodyItems.Add(curveRepresentationItem);
                                    planRepresentation = RepresentationUtil.CreateGeometricSetRep(exporterIFC, familyInstance, categoryId, "FootPrint",
                                       contextOfItems2d, bodyItems);
                                }
                            }
                        }
                    }

                    if (doorWindowInfo != null)
                        typeInfo.StyleTransform = doorWindowTrf.Inverse;
                    else
                        typeInfo.StyleTransform = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement());

                    // for many
                    HashSet<IFCAnyHandle> propertySets = null;
                    IFCAnyHandle typeStyle = CreateFamilyTypeHandle(exporterIFC, typeInfo, doorWindowInfo, bodyRepresentation, planRepresentation,
                        familyInstance, familySymbol, originalFamilySymbol, useInstanceGeometry, exportParts,
                        exportType, revitObjectType, ifcEnumType, out propertySets);

                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle))
                    {
                        wrapper.RegisterHandleWithElementType(familySymbol, typeStyle, propertySets);

                        CategoryUtil.CreateMaterialAssociations(exporterIFC, typeStyle, typeInfo.MaterialIds);

                        typeInfo.Style = typeStyle;

                        if ((exportType == IFCExportType.ExportColumnType) || (exportType == IFCExportType.ExportMemberType))
                        {
                            typeInfo.ScaledArea = extraParams.ScaledArea;
                            typeInfo.ScaledDepth = extraParams.ScaledLength;
                            typeInfo.ScaledInnerPerimeter = extraParams.ScaledInnerPerimeter;
                            typeInfo.ScaledOuterPerimeter = extraParams.ScaledOuterPerimeter;
                        }

                        ClassificationUtil.CreateClassification(exporterIFC, file, familySymbol, typeStyle);        // Create other generic classification from ClassificationCode(s)
                        ClassificationUtil.CreateUniformatClassification(exporterIFC, file, originalFamilySymbol, typeStyle);
                    }
                }

                if (found && !typeInfo.IsValid())
                    typeInfo = currentTypeInfo;

                // we'll pretend we succeeded, but we'll do nothing.
                if (!typeInfo.IsValid())
                    return;

                // add to the map, as long as we are not using range, not using instance geometry, and don't have extra openings.
                if ((range == null) && !useInstanceGeometry && (extraParams.GetOpenings().Count == 0))
                    ExporterCacheManager.TypeObjectsCache.Register(originalFamilySymbol.Id, flipped, typeInfo);

                // If we are using the instance geometry, ignore the transformation.
                if (useInstanceGeometry)
                    trf = Transform.Identity;

                if ((range != null) && exportParts)
                {
                    XYZ rangeOffset = trf.Origin;
                    rangeOffset += new XYZ(0, 0, range.Start);
                    trf.Origin = rangeOffset;
                }

                Transform originalTrf = new Transform(trf);
                XYZ scaledMapOrigin = XYZ.Zero;

                trf = trf.Multiply(typeInfo.StyleTransform);

                // create instance.  
                IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>();
                {
                    IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle();
                    IFCAnyHandle contextOfItems3d = exporterIFC.Get3DContextHandle("Body");

                    // for proxies, we store the IfcRepresentationMap directly since there is no style.
                    IFCAnyHandle style = typeInfo.Style;
                    IList<IFCAnyHandle> repMapList = !IFCAnyHandleUtil.IsNullOrHasNoValue(style) ?
                        GeometryUtil.GetRepresentationMaps(style) : null;
                    int numReps = repMapList != null ? repMapList.Count : 0;

                    IFCAnyHandle repMap2dHnd = typeInfo.Map2DHandle;
                    IFCAnyHandle repMap3dHnd = typeInfo.Map3DHandle;
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd) && (numReps > 0))
                        repMap3dHnd = repMapList[0];
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd) && (numReps > 1))
                        repMap2dHnd = repMapList[1];

                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd))
                    {
                        IList<IFCAnyHandle> representations = new List<IFCAnyHandle>();
                        representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap3dHnd, scaledMapOrigin));
                        IFCAnyHandle shapeRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, familyInstance, categoryId, contextOfItems3d,
                            representations);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep))
                            return;
                        shapeReps.Add(shapeRep);
                    }

                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd))
                    {
                        HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>();
                        representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap2dHnd, scaledMapOrigin));
                        IFCAnyHandle shapeRep = RepresentationUtil.CreatePlanMappedItemRep(exporterIFC, familyInstance, categoryId, contextOfItems2d,
                            representations);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep))
                            return;
                        shapeReps.Add(shapeRep);
                    }
                }

                IFCAnyHandle boundingBoxRep = null;
                Transform boundingBoxTrf = (offsetTransform != null) ? offsetTransform.Inverse : Transform.Identity;
                if (geomObjects.Count > 0)
                    boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomObjects, boundingBoxTrf);
                else
                {
                    boundingBoxTrf = boundingBoxTrf.Multiply(trf.Inverse);
                    boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, familyInstance.get_Geometry(options), boundingBoxTrf);
                }

                if (boundingBoxRep != null)
                    shapeReps.Add(boundingBoxRep);

                IFCAnyHandle repHnd = (shapeReps.Count > 0) ? IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps) : null;

                // We won't create the instance if: 
                // (1) we are exporting to CV2.0, (2) we have no 2D, 3D, or bounding box geometry, and (3) we aren't exporting parts.
                if (!(repHnd == null && ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && !exportParts))
                {
                    IFCAnyHandle instanceHandle = null;

                    if (overrideLevelId == ElementId.InvalidElementId)
                        overrideLevelId = ExporterUtil.GetBaseLevelIdForElement(familyInstance);
                    using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, familyInstance, trf, null, overrideLevelId))
                    {
                        string instanceGUID = GUIDUtil.CreateGUID(familyInstance);
                        string instanceName = NamingUtil.GetNameOverride(familyInstance, NamingUtil.GetIFCName(familyInstance));
                        string instanceDescription = NamingUtil.GetDescriptionOverride(familyInstance, null);
                        string instanceObjectType = NamingUtil.GetObjectTypeOverride(familyInstance, revitObjectType);
                        string instanceTag = NamingUtil.GetTagOverride(familyInstance, NamingUtil.CreateIFCElementId(familyInstance));

                        bool isChildInContainer = familyInstance.AssemblyInstanceId != ElementId.InvalidElementId;

                        IFCAnyHandle localPlacement = setter.GetPlacement();
                        IFCAnyHandle overrideLocalPlacement = null;

                        if (parentLocalPlacement != null)
                        {
                            Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(parentLocalPlacement, localPlacement);
                            Transform inverseTrf = relTrf.Inverse;

                            IFCAnyHandle relativePlacement = ExporterUtil.CreateAxis2Placement3D(file, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX);
                            IFCAnyHandle plateLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, parentLocalPlacement, relativePlacement);
                            overrideLocalPlacement = plateLocalPlacement;
                        }

                        instanceHandle = FamilyExporterUtil.ExportGenericInstance(exportType, exporterIFC, familyInstance,
                           wrapper, setter, extraParams, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType,
                           exportParts ? null : repHnd, instanceTag, overrideLocalPlacement);

                        if (exportParts)
                            PartExporter.ExportHostPart(exporterIFC, familyInstance, instanceHandle, familyProductWrapper, setter, setter.GetPlacement(), overrideLevelId);

                        if (ElementFilteringUtil.IsMEPType(exportType) || ElementFilteringUtil.ProxyForMEPType(familyInstance, exportType))
                        {
                            ExporterCacheManager.MEPCache.Register(familyInstance, instanceHandle);
                            // For ducts and pipes, check later if there is an associated duct or pipe.
                            if (exportType == IFCExportType.ExportDuctFittingType || exportType == IFCExportType.ExportPipeFittingType ||
                                exportType == IFCExportType.ExportDuctSegmentType || exportType == IFCExportType.ExportPipeSegmentType)
                                ExporterCacheManager.MEPCache.CoveredElementsCache.Add(familyInstance.Id);
                        }

                        switch (exportType)
                        {
                            case IFCExportType.ExportColumnType:
                                {
                                    IFCAnyHandle placementToUse = localPlacement;
                                    if (!useInstanceGeometry)
                                    {
                                        bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams);
                                        if (needToCreateOpenings)
                                        {
                                            Transform openingTrf = new Transform(originalTrf);
                                            Transform extraRot = new Transform(originalTrf);
                                            extraRot.Origin = XYZ.Zero;
                                            openingTrf = openingTrf.Multiply(extraRot);
                                            openingTrf = openingTrf.Multiply(typeInfo.StyleTransform);

                                            IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, openingTrf.Origin * scale,
                                               openingTrf.get_Basis(2), openingTrf.get_Basis(0));
                                            IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement);
                                            GeometryUtil.SetRelativePlacement(openingPlacement, openingRelativePlacement);
                                            placementToUse = openingPlacement;
                                        }
                                    }

                                    OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform,
                                        exporterIFC, placementToUse, setter, wrapper);

                                    //export Base Quantities.
                                    PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo);
                                    break;
                                }
                            case IFCExportType.ExportDoorType:
                            case IFCExportType.ExportWindowType:
                                {
                                    double doorHeight = doorWindowInfo.OpeningHeight;
                                    if (doorHeight < MathUtil.Eps())
                                        doorHeight = GetMinSymbolHeight(originalFamilySymbol) * scale;
                                    else
                                    {
                                        // The native OpeningHeight code is not reliable if the opening has an arc in the boundary.  Potentially fix this case.
                                        doorHeight = PotentiallyCorrectDoorHeight(doorWindowInfo.GetOpening(), doorHeight * scale);
                                    }

                                    double doorWidth = doorWindowInfo.OpeningWidth;
                                    if (doorWidth < MathUtil.Eps())
                                        doorWidth = GetMinSymbolWidth(originalFamilySymbol);

                                    double height = doorHeight; // Already scaled.
                                    double width = doorWidth * scale;

                                    IFCAnyHandle doorWindowLocalPlacement = null;
                                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(overrideLocalPlacement))
                                        doorWindowLocalPlacement = overrideLocalPlacement;
                                    else
                                {
                                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetLocalPlacement()))
                                            doorWindowInfo.SetLocalPlacement(localPlacement);

                                        IFCAnyHandle doorWindowOrigLocalPlacement = doorWindowInfo.GetLocalPlacement();
                                        Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, doorWindowOrigLocalPlacement);

                                        IFCAnyHandle doorWindowRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, relTrf.Origin, relTrf.BasisZ, relTrf.BasisX);
                                        doorWindowLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, doorWindowOrigLocalPlacement, doorWindowRelativePlacement);
                                    }
                                    if (exportType == IFCExportType.ExportDoorType)
                                        instanceHandle = IFCInstanceExporter.CreateDoor(file, instanceGUID, ownerHistory,
                                           instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement,
                                           repHnd, instanceTag, height, width);
                                    else if (exportType == IFCExportType.ExportWindowType)
                                        instanceHandle = IFCInstanceExporter.CreateWindow(file, instanceGUID, ownerHistory,
                                           instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement,
                                           repHnd, instanceTag, height, width);
                                    wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, true);

                                    exporterIFC.RegisterSpaceBoundingElementHandle(instanceHandle, familyInstance.Id, setter.LevelId);

                                    IFCAnyHandle placementToUse = doorWindowLocalPlacement;
                                    if (!useInstanceGeometry)
                                    {
                                        // correct the placement to the symbol space
                                        bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams);
                                        if (needToCreateOpenings)
                                        {
                                            Transform openingTrf = Transform.Identity;
                                            openingTrf.Origin = new XYZ(0, 0, setter.Offset);
                                            openingTrf = openingTrf.Multiply(doorWindowTrf);
                                            XYZ scaledOrigin = openingTrf.Origin * exporterIFC.LinearScale;
                                            IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, scaledOrigin, openingTrf.BasisZ, openingTrf.BasisX);
                                            IFCAnyHandle openingLocalPlacement =
                                                IFCInstanceExporter.CreateLocalPlacement(file, doorWindowLocalPlacement, openingRelativePlacement);
                                            placementToUse = openingLocalPlacement;
                                        }
                                    }

                                    OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform,
                                        exporterIFC, placementToUse, setter, wrapper);
                                    break;
                                }
                            case IFCExportType.ExportMemberType:
                                {
                                    OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform,
                                        exporterIFC, localPlacement, setter, wrapper);

                                    //export Base Quantities.
                                    PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo);
                                    break;
                                }
                            case IFCExportType.ExportPlateType:
                                {
                                    OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform,
                                        exporterIFC, localPlacement, setter, wrapper);
                                    break;
                                }
                            case IFCExportType.ExportTransportElementType:
                                {
                                    IFCAnyHandle localPlacementToUse;
                                    ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse);

                                    IFCTransportElementType operationType = FamilyExporterUtil.GetTransportElementType(familyInstance);

                                    double capacityByWeight = 0.0;
                                    ParameterUtil.GetDoubleValueFromElementOrSymbol(familyInstance, "IfcCapacityByWeight", out capacityByWeight);
                                    double capacityByNumber = 0.0;
                                    ParameterUtil.GetDoubleValueFromElementOrSymbol(familyInstance, "IfcCapacityByNumber", out capacityByNumber);

                                    instanceHandle = IFCInstanceExporter.CreateTransportElement(file, instanceGUID, ownerHistory,
                                       instanceName, instanceDescription, instanceObjectType,
                                       localPlacementToUse, repHnd, instanceTag, operationType, capacityByWeight, capacityByNumber);

                                    bool containedInSpace = (roomId != ElementId.InvalidElementId);
                                    wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, !containedInSpace);
                                    if (containedInSpace)
                                        exporterIFC.RelateSpatialElement(roomId, instanceHandle);

                                    break;
                                }
                            //case IFCExportType.ExportBuildingElementProxy:
                            //case IFCExportType.ExportBuildingElementProxyType:
                            default:
                                {
                                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle))
                                    {
                                        bool isBuildingElementProxy =
                                            ((exportType == IFCExportType.ExportBuildingElementProxy) ||
                                            (exportType == IFCExportType.ExportBuildingElementProxyType));

                                        IFCAnyHandle localPlacementToUse = null;
                                    ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse);

                                        if (!isBuildingElementProxy && FamilyExporterUtil.IsDistributionControlElementSubType(exportType))
                                        {
                                            string ifcelementType = null;
                                            ParameterUtil.GetStringValueFromElement(familyInstance.Id, "IfcElementType", out ifcelementType);

                                            instanceHandle = IFCInstanceExporter.CreateDistributionControlElement(file, instanceGUID,
                                               ownerHistory, instanceName, instanceDescription, instanceObjectType,
                                               localPlacementToUse, repHnd, instanceTag, ifcelementType);
                                        }
                                        else 
                                        {
                                        instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(file, instanceGUID,
                                           ownerHistory, instanceName, instanceDescription, instanceObjectType,
                                           localPlacementToUse, repHnd, instanceTag, null);
                                        }

                                        bool containedInSpace = (roomId != ElementId.InvalidElementId);
                                        bool associateToLevel = containedInSpace ? false : !isChildInContainer;
                                        wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, associateToLevel);
                                        if (containedInSpace)
                                            exporterIFC.RelateSpatialElement(roomId, instanceHandle);
                                    }

                                    IFCAnyHandle placementToUse = localPlacement;
                                    if (!useInstanceGeometry)
                                    {
                                        bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams);
                                        if (needToCreateOpenings)
                                        {
                                            Transform openingTrf = new Transform(originalTrf);
                                            Transform extraRot = new Transform(originalTrf);
                                            extraRot.Origin = XYZ.Zero;
                                            openingTrf = openingTrf.Multiply(extraRot);
                                            openingTrf = openingTrf.Multiply(typeInfo.StyleTransform);

                                            XYZ scaledOrigin = openingTrf.Origin * scale;
                                            IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, scaledOrigin,
                                               openingTrf.get_Basis(2), openingTrf.get_Basis(0));
                                            IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement);
                                            GeometryUtil.SetRelativePlacement(openingPlacement, openingRelativePlacement);
                                            placementToUse = openingPlacement;
                                        }
                                    }

                                    OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform,
                                        exporterIFC, placementToUse, setter, wrapper);
                                    break;
                                }
                        }

                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle))
                        {
                            ExporterCacheManager.HandleToElementCache.Register(instanceHandle, familyInstance.Id);
                            if (doorWindowInfo != null)
                            {
                                if (!ignoreDoorWindowOpening)
                                {
                                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetOpening()))
                                    {
                                        string relGUID = GUIDUtil.CreateGUID();
                                        IFCInstanceExporter.CreateRelFillsElement(file, relGUID, ownerHistory, null, null, doorWindowInfo.GetOpening(), instanceHandle);
                                    }
                                    else if (doorWindowInfo.NeedsOpening)
                                    {
                                        bool added = doorWindowInfo.SetDelayedFamilyInstance(instanceHandle, localPlacement, doorWindowInfo.AssignedLevelId);
                                        if (added)
                                            exporterIFC.RegisterDoorWindowForOpeningUpdate(doorWindowInfo);
                                        else
                                        {
                                            // we need to fill a later opening.
                                            exporterIFC.RegisterDoorWindowForUncreatedOpening(familyInstance.Id, instanceHandle);
                                        }
                                    }
                                }
                            }

                            if (!exportParts)
                                CategoryUtil.CreateMaterialAssociations(exporterIFC, instanceHandle, typeInfo.MaterialIds);

                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style))
                                ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle);
                        }
                    }
                }
            }
        }
Esempio n. 14
0
        /// <summary>
        /// Export Curtain Walls and Roofs.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="allSubElements">
        /// Collection of elements contained in the host curtain element.
        /// </param>
        /// <param name="element">
        /// The element to be exported.
        /// </param>
        /// <param name="productWrapper">
        /// The IFCProductWrapper.
        /// </param>
        public static void ExportBase(ExporterIFC exporterIFC, ICollection <ElementId> allSubElements,
                                      Element element, IFCProductWrapper wrapper)
        {
            IFCFile      file         = exporterIFC.GetFile();
            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

            IFCPlacementSetter setter = null;

            using (IFCProductWrapper curtainWallSubWrapper = IFCProductWrapper.Create(wrapper, false))
            {
                try
                {
                    IFCAnyHandle localPlacement = null;
                    bool         canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements, element.Document);
                    IFCAnyHandle rep = null;
                    if (!canExportCurtainWallAsContainer)
                    {
                        setter         = IFCPlacementSetter.Create(exporterIFC, element);
                        localPlacement = setter.GetPlacement();
                        rep            = ExportCurtainObjectCommonAsOneBRep(allSubElements, element, exporterIFC, setter, localPlacement);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(rep))
                        {
                            return;
                        }
                    }
                    else
                    {
                        ExportCurtainObjectCommonAsContainer(allSubElements, element, exporterIFC, curtainWallSubWrapper);
                        // This has to go LAST.  Why?  Because otherwise we apply the level transform twice -- once in the familyTrf, once here.
                        // This will be used just to put the CurtainWall on the right level.
                        setter         = IFCPlacementSetter.Create(exporterIFC, element);
                        localPlacement = setter.GetPlacement();
                    }

                    string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element);

                    {
                        IFCAnyHandle prodRepHnd = null;
                        IFCAnyHandle elemHnd    = null;
                        string       elemGUID   = ExporterIFCUtils.CreateGUID(element);
                        string       elemName   = NamingUtil.GetNameOverride(element, exporterIFC.GetName());
                        string       elemDesc   = NamingUtil.GetDescriptionOverride(element, null);
                        string       elemType   = NamingUtil.GetObjectTypeOverride(element, objectType);
                        string       elemId     = NamingUtil.CreateIFCElementId(element);
                        if (element is Wall || element is CurtainSystem || IsLegacyCurtainElement(element))
                        {
                            elemHnd = IFCInstanceExporter.CreateCurtainWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemId);
                        }
                        else if (element is RoofBase)
                        {
                            //need to convert the string to enum
                            string ifcEnumType = CategoryUtil.GetIFCEnumTypeName(exporterIFC, element);
                            elemHnd = IFCInstanceExporter.CreateRoof(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement,
                                                                     prodRepHnd, elemId, RoofExporter.GetIFCRoofType(ifcEnumType));
                        }
                        else
                        {
                            return;
                        }

                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd))
                        {
                            return;
                        }

                        wrapper.AddElement(elemHnd, setter, null, true);

                        ExporterIFCUtils.CreateCurtainWallPropertySet(exporterIFC, element, wrapper);
                        PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, wrapper);
                        ICollection <IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects();
                        if (relatedElementIds.Count > 0)
                        {
                            string guid = ExporterIFCUtils.CreateSubElementGUID(element, (int)IFCCurtainWallSubElements.RelAggregates);
                            HashSet <IFCAnyHandle> relatedElementIdSet = new HashSet <IFCAnyHandle>(relatedElementIds);
                            IFCInstanceExporter.CreateRelAggregates(file, guid, ownerHistory, null, null, elemHnd, relatedElementIdSet);
                        }
                        exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, element.Id, ElementId.InvalidElementId);
                    }
                }
                finally
                {
                    if (setter != null)
                    {
                        setter.Dispose();
                    }
                }
            }
        }
Esempio n. 15
0
        /// <summary>
        /// Export Curtain Walls and Roofs.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="allSubElements">
        /// Collection of elements contained in the host curtain element.
        /// </param>
        /// <param name="element">
        /// The element to be exported.
        /// </param>
        /// <param name="productWrapper">
        /// The IFCProductWrapper.
        /// </param>
        public static void ExportBase(ExporterIFC exporterIFC, ICollection<ElementId> allSubElements,
           Element element, IFCProductWrapper wrapper)
        {
            IFCFile file = exporterIFC.GetFile();
            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

            IFCPlacementSetter setter = null;

            using (IFCProductWrapper curtainWallSubWrapper = IFCProductWrapper.Create(wrapper, false))
            {
                try
                {
                    IFCAnyHandle localPlacement = null;
                    bool canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements, element.Document);
                    IFCAnyHandle rep = null;
                    if (!canExportCurtainWallAsContainer)
                    {
                        setter = IFCPlacementSetter.Create(exporterIFC, element);
                        localPlacement = setter.GetPlacement();
                        rep = ExportCurtainObjectCommonAsOneBRep(allSubElements, element, exporterIFC, setter, localPlacement);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(rep))
                            return;
                    }
                    else
                    {
                        ExportCurtainObjectCommonAsContainer(allSubElements, element, exporterIFC, curtainWallSubWrapper);
                        // This has to go LAST.  Why?  Because otherwise we apply the level transform twice -- once in the familyTrf, once here.
                        // This will be used just to put the CurtainWall on the right level.
                        setter = IFCPlacementSetter.Create(exporterIFC, element);
                        localPlacement = setter.GetPlacement();
                    }

                    string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element);

                    {
                        IFCAnyHandle prodRepHnd = null;
                        IFCAnyHandle elemHnd = null;
                        string elemGUID = ExporterIFCUtils.CreateGUID(element);
                        string elemName = NamingUtil.GetNameOverride(element, exporterIFC.GetName());
                        string elemDesc = NamingUtil.GetDescriptionOverride(element, null);
                        string elemType = NamingUtil.GetObjectTypeOverride(element, objectType);
                        string elemId = NamingUtil.CreateIFCElementId(element);
                        if (element is Wall || element is CurtainSystem || IsLegacyCurtainElement(element))
                        {
                            elemHnd = IFCInstanceExporter.CreateCurtainWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemId);
                        }
                        else if (element is RoofBase)
                        {
                            //need to convert the string to enum
                            string ifcEnumType = CategoryUtil.GetIFCEnumTypeName(exporterIFC, element);
                            elemHnd = IFCInstanceExporter.CreateRoof(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement,
                                prodRepHnd, elemId, RoofExporter.GetIFCRoofType(ifcEnumType));
                        }
                        else
                        {
                            return;
                        }

                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd))
                            return;
                        
                        wrapper.AddElement(elemHnd, setter, null, true);

                        ExporterIFCUtils.CreateCurtainWallPropertySet(exporterIFC, element, wrapper);
                        PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, wrapper);
                        ICollection<IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects();
                        if (relatedElementIds.Count > 0)
                        {
                            string guid = ExporterIFCUtils.CreateSubElementGUID(element, (int)IFCCurtainWallSubElements.RelAggregates);
                            HashSet<IFCAnyHandle> relatedElementIdSet = new HashSet<IFCAnyHandle>(relatedElementIds);
                            IFCInstanceExporter.CreateRelAggregates(file, guid, ownerHistory, null, null, elemHnd, relatedElementIdSet);
                        }
                        exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, element.Id, ElementId.InvalidElementId);
                    }
                }
                finally
                {
                    if (setter != null)
                        setter.Dispose();
                }
            }
        }
        /// <summary>
        /// Main implementation to export walls.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="element">
        /// The element.
        /// </param>
        /// <param name="geometryElement">
        /// The geometry element.
        /// </param>
        /// <param name="productWrapper">
        /// The IFCProductWrapper.
        /// </param>
        /// <param name="overrideLevelId">
        /// The level id.
        /// </param>
        /// <param name="range">
        /// The range to be exported for the element.
        /// </param>
        /// <returns>
        /// The exported wall handle.
        /// </returns>
        public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement,
           IFCProductWrapper productWrapper, ElementId overrideLevelId, UV range)
        {
            using (IFCProductWrapper localWrapper = IFCProductWrapper.Create(productWrapper))
            {
                ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                Wall wallElement = element as Wall;
                FamilyInstance famInstWallElem = element as FamilyInstance;

                if (wallElement == null && famInstWallElem == null)
                    return IFCAnyHandle.Create();

                if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range))
                    return IFCAnyHandle.Create();

                // get global values.
                Document doc = element.Document;
                double scale = exporterIFC.LinearScale;

                IFCFile file = exporterIFC.GetFile();
                IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();
                IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle();

                UV zSpan = UV.Zero;
                double depth = 0.0;
                bool validRange = (!MathUtil.IsAlmostZero(range.V - range.U));

                // get bounding box height so that we can subtract out pieces properly.
                // only for Wall, not FamilyInstance.
                if (wallElement != null && geometryElement != null)
                {
                    BoundingBoxXYZ boundingBox = element.get_BoundingBox(null);
                    zSpan = new UV(boundingBox.Min.Z, boundingBox.Max.Z);

                    // if we have a top clipping plane, modify depth accordingly.
                    double bottomHeight = validRange ? Math.Max(zSpan[0], range[0]) : zSpan[0];
                    double topHeight = validRange ? Math.Min(zSpan[1], range[1]) : zSpan[1];
                    depth = topHeight - bottomHeight;
                    if (MathUtil.IsAlmostZero(depth))
                        return IFCAnyHandle.Create();
                    depth *= scale;
                }

                IFCAnyHandle axisRep = IFCAnyHandle.Create();
                IFCAnyHandle bodyRep = IFCAnyHandle.Create();

                bool exportingAxis = false;
                Curve curve = null;

                bool exportedAsWallWithAxis = false;
                bool exportedBodyDirectly = false;
                bool exportingInplaceOpenings = false;

                Curve centerCurve = GetWallAxis(wallElement);

                XYZ localXDir = new XYZ(1, 0, 0);
                XYZ localYDir = new XYZ(0, 1, 0);
                XYZ localZDir = new XYZ(0, 0, 1);
                XYZ localOrig = new XYZ(0, 0, 0);
                double eps = MathUtil.Eps();

                if (centerCurve != null)
                {
                    Curve baseCurve = GetWallAxisAtBaseHeight(wallElement);
                    curve = GetWallTrimmedCurve(wallElement, baseCurve);

                    UV curveBounds;
                    XYZ oldOrig;
                    GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig);

                    localOrig = oldOrig;
                    if (baseCurve != null)
                    {
                        if (!validRange || (MathUtil.IsAlmostEqual(range[0], zSpan[0])))
                        {
                            XYZ newOrig = baseCurve.Evaluate(curveBounds.U, false);
                            if (validRange && (zSpan[0] < newOrig[2] - eps))
                                localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan[0]);
                            else
                                localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]);
                        }
                        else
                        {
                            localOrig = new XYZ(localOrig.X, localOrig.Y, range[0]);
                        }
                    }

                    double dist = localOrig[2] - oldOrig[2];
                    if (!MathUtil.IsAlmostZero(dist))
                    {
                        XYZ moveVec = new XYZ(0, 0, dist);
                        curve = GeometryUtil.MoveCurve(curve, moveVec);
                    }
                    localYDir = localZDir.CrossProduct(localXDir);

                    // ensure that X and Z axes are orthogonal.
                    double xzDot = localZDir.DotProduct(localXDir);
                    if (!MathUtil.IsAlmostZero(xzDot))
                        localXDir = localYDir.CrossProduct(localZDir);
                }

                Transform orientationTrf = Transform.Identity;
                orientationTrf.BasisX = localXDir;
                orientationTrf.BasisY = localYDir;
                orientationTrf.BasisZ = localZDir;
                orientationTrf.Origin = localOrig;

                using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId))
                {
                    IFCAnyHandle localPlacement = setter.GetPlacement();

                    Plane plane = new Plane(localXDir, localYDir, localOrig);  // project curve to XY plane.
                    XYZ projDir = new XYZ(0, 0, 1);

                    // two representations: axis, body.         
                    {
                        if ((centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve)))
                        {
                            exportingAxis = true;

                            IFCLabel identifierOpt = IFCLabel.Create("Axis");	// IFC2x2 convention
                            IFCLabel representationTypeOpt = IFCLabel.Create("Curve2D");  // IFC2x2 convention

                            IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false);
                            ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true);
                            IList<IFCAnyHandle> axisItems = info.GetCurves();

                            if (axisItems.Count == 0)
                            {
                                exportingAxis = false;
                            }
                            else
                            {
                                HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>();
                                foreach (IFCAnyHandle axisItem in axisItems)
                                    axisItemSet.Add(axisItem);

                                axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, catId, contextOfItems,
                                   identifierOpt, representationTypeOpt, axisItemSet);
                            }
                        }
                    }

                    IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>();

                    do
                    {
                        if (wallElement == null || !exportingAxis || curve == null)
                            break;

                        bool hasExtrusion = HasElevationProfile(wallElement);
                        if (hasExtrusion)
                        {
                            IList<CurveLoop> loops = GetElevationProfile(wallElement);
                            if (loops.Count == 0)
                                hasExtrusion = false;
                            else
                            {
                                IList<IList<CurveLoop>> sortedLoops = ExporterIFCUtils.SortCurveLoops(loops);
                                if (sortedLoops.Count == 0)
                                    break;

                                // Current limitation: can't handle wall split into multiple disjointed pieces.
                                int numSortedLoops = sortedLoops.Count;
                                if (numSortedLoops > 1)
                                    break;

                                bool ignoreExtrusion = true;
                                bool cantHandle = false;
                                bool hasGeometry = false;
                                for (int ii = 0; (ii < numSortedLoops) && !cantHandle; ii++)
                                {
                                    int sortedLoopSize = sortedLoops[ii].Count;
                                    if (sortedLoopSize == 0)
                                        continue;
                                    if (!ExporterIFCUtils.IsCurveLoopConvexWithOpenings(sortedLoops[ii][0], range, wallElement, out ignoreExtrusion))
                                    {
                                        if (ignoreExtrusion)
                                        {
                                            // we need more information.  Is there something to export?  If so, we'll
                                            // ignore the extrusion.  Otherwise, we will fail.

                                            IFCSolidMeshGeometryInfo solidMeshInfo = ExporterIFCUtils.GetClippedSolidMeshGeometry(exporterIFC, range, geometryElement);
                                            if (solidMeshInfo.GetSolids().Count == 0 && solidMeshInfo.GetMeshes().Count == 0)
                                                continue;
                                            hasExtrusion = false;
                                        }
                                        else
                                        {
                                            cantHandle = true;
                                        }
                                        hasGeometry = true;
                                    }
                                    else
                                    {
                                        hasGeometry = true;
                                    }
                                }

                                if (!hasGeometry)
                                    return IFCAnyHandle.Create();
                                if (cantHandle)
                                    break;
                            }
                        }

                        if (!CanExportWallGeometryAsExtrusion(element, range))
                            break;

                        // extrusion direction.
                        XYZ extrusionDir = GetWallHeightDirection(wallElement);

                        // create extrusion boundary.
                        IList<CurveLoop> boundaryLoops = new List<CurveLoop>();

                        bool alwaysThickenCurve = IsWallBaseRectangular(wallElement, curve);

                        if (!alwaysThickenCurve)
                        {
                            boundaryLoops = GetLoopsFromTopBottomFace(wallElement, exporterIFC);
                            if (boundaryLoops.Count == 0)
                                continue;
                        }
                        else
                        {
                            CurveLoop newLoop = CurveLoop.CreateViaThicken(curve, wallElement.Width, new XYZ(0, 0, 1));
                            if (newLoop == null)
                                break;

                            if (!GeometryUtil.IsIFCLoopCCW(newLoop, new XYZ(0, 0, 1)))
                                newLoop = GeometryUtil.ReverseOrientation(newLoop);
                            boundaryLoops.Add(newLoop);
                        }

                        // origin gets scaled later.
                        XYZ setterOffset = new XYZ(0, 0, setter.Offset + (localOrig[2] - setter.BaseOffset));

                        IFCAnyHandle baseBodyItemHnd = file.CreateExtrudedSolidFromCurveLoop(exporterIFC, catId,
                           boundaryLoops, plane, extrusionDir, depth);
                        if (!baseBodyItemHnd.HasValue)
                            break;

                        IFCAnyHandle bodyItemHnd = AddClippingsToBaseExtrusion(exporterIFC, wallElement,
                           setterOffset, range, zSpan, baseBodyItemHnd, out cutPairOpenings);
                        if (!bodyItemHnd.HasValue)
                            break;

                        HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>();
                        bodyItems.Add(bodyItemHnd);

                        if (baseBodyItemHnd.Id == bodyItemHnd.Id)
                        {
                            bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, catId, contextOfItems, bodyItems, IFCAnyHandle.Create());
                        }
                        else
                        {
                            bodyRep = RepresentationUtil.CreateClippingRep(exporterIFC, catId, contextOfItems, bodyItems);
                        }

                        if (bodyRep.HasValue)
                            exportedAsWallWithAxis = true;
                    } while (false);

                    IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData();
                    ElementId matId = ElementId.InvalidElementId;

                    if (!exportedAsWallWithAxis)
                    {
                        IFCSolidMeshGeometryInfo solidMeshInfo;

                        if (wallElement != null)
                        {
                            if (validRange)
                            {
                                solidMeshInfo = ExporterIFCUtils.GetClippedSolidMeshGeometry(exporterIFC, range, geometryElement);
                                if (solidMeshInfo.GetSolids().Count == 0 && solidMeshInfo.GetMeshes().Count == 0)
                                    return IFCAnyHandle.Create();
                            }
                            else
                            {
                                solidMeshInfo = ExporterIFCUtils.GetSplitSolidMeshGeometry(exporterIFC, geometryElement);
                            }
                        }
                        else
                        {
                            GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem);
                            if (geomElemToUse != null)
                            {
                                exportingInplaceOpenings = true;
                            }
                            else
                            {
                                exportingInplaceOpenings = false;
                                geomElemToUse = geometryElement;
                            }
                            Transform trf = Transform.Identity;
                            if (geomElemToUse != geometryElement)
                                trf = famInstWallElem.GetTransform();
                            solidMeshInfo = ExporterIFCUtils.GetSolidMeshGeometry(exporterIFC, geomElemToUse, trf);
                        }

                        IList<Solid> solids = solidMeshInfo.GetSolids();
                        IList<Mesh> meshes = solidMeshInfo.GetMeshes();

                        extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ;   // only allow vertical extrusions!
                        extraParams.AreInnerRegionsOpenings = true;

                        if ((solids.Count > 0) || (meshes.Count > 0))
                        {
                            matId = BodyExporter.GetBestMaterialIdForGeometry(solids, meshes);
                            bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, catId, solids, meshes, true, extraParams);
                        }
                        else
                        {
                            IList<GeometryObject> geomElemList = new List<GeometryObject>();
                            geomElemList.Add(geometryElement);
                            bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, catId, geomElemList, true, extraParams);
                        }

                        if (!bodyRep.HasValue)
                            return IFCAnyHandle.Create();

                        // We will be able to export as a IfcWallStandardCase as long as we have an axis curve.
                        XYZ extrDirUsed = XYZ.Zero;
                        if (extraParams.HasCustomAxis)
                        {
                            extrDirUsed = extraParams.CustomAxis;
                            if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0))
                            {
                                if ((solids.Count == 1) && (meshes.Count == 0))
                                    exportedAsWallWithAxis = exportingAxis;
                                exportedBodyDirectly = true;
                            }
                        }
                    }

                    IFCAnyHandle prodRep = IFCAnyHandle.Create();
                    IList<IFCAnyHandle> representations = new List<IFCAnyHandle>();
                    if (exportingAxis)
                        representations.Add(axisRep);

                    representations.Add(bodyRep);
                    prodRep = file.CreateProductDefinitionShape(IFCLabel.Create(), IFCLabel.Create(), representations);

                    IFCLabel objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element);
                    IFCAnyHandle wallHnd = IFCAnyHandle.Create();

                    IFCLabel elemGUID = (validRange) ? IFCLabel.CreateGUID() : IFCLabel.CreateGUID(element);
                    IFCLabel elemName = NamingUtil.GetNameOverride(element, NamingUtil.CreateIFCName(exporterIFC, -1));
                    IFCLabel elemDesc = NamingUtil.GetDescriptionOverride(element, IFCLabel.Create());
                    IFCLabel elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType);
                    IFCLabel elemId = NamingUtil.CreateIFCElementId(element);

                    if (exportedAsWallWithAxis)
                    {
                        wallHnd = file.CreateWallStandardCase(elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement,
                           elemId, prodRep);
                        localWrapper.AddElement(wallHnd, setter, extraParams, true);

                        OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, exporterIFC, localPlacement, setter, localWrapper);
                        if (exportedBodyDirectly)
                        {
                            OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper);
                        }
                        else
                        {
                            double scaledWidth = wallElement.Width * scale;
                            ExporterIFCUtils.AddOpeningsToWall(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper);
                        }

                        // export Base Quantities
                        if (exporterIFC.ExportBaseQuantities)
                        {
                            CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth);
                        }
                    }
                    else
                    {
                        wallHnd = file.CreateWall(elemGUID, ownerHistory, elemName, elemDesc, elemObjectType,
                           localPlacement, elemId, prodRep);
                        localWrapper.AddElement(wallHnd, setter, extraParams, true);

                        // Only export one material for 2x2; for future versions, export the whole list.
                        if (exporterIFC.ExportAs2x2 && (matId != ElementId.InvalidElementId))
                        {
                            CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, wallHnd, matId);
                        }

                        if (exportingInplaceOpenings)
                        {
                            double scaledWidth = wallElement.Width * scale;
                            ExporterIFCUtils.AddOpeningsToWall(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper);
                        }

                        if (exportedBodyDirectly)
                            OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper);
                    }

                    ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, element, localWrapper);

                    ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId;

                    if (wallElement != null)
                        ExporterIFCUtils.ExportHostObject(exporterIFC, wallElement, geometryElement, localWrapper);

                    exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId);
                    return wallHnd;
                }
            }
        }