/// <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);
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Exports a MEP family instance.
        /// </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>
        public static void Export(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCProductWrapper productWrapper)
        {
            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                string        ifcEnumType;
                IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType);

                using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element))
                {
                    IFCAnyHandle localPlacementToUse = setter.GetPlacement();
                    using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData())
                    {
                        ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                        BodyExporterOptions bodyExporterOptions   = new BodyExporterOptions(true);
                        IFCAnyHandle        productRepresentation = RepresentationUtil.CreateBRepProductDefinitionShape(element.Document.Application,
                                                                                                                        exporterIFC, element, catId, geometryElement, bodyExporterOptions, null, extraParams);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(productRepresentation))
                        {
                            extraParams.ClearOpenings();
                            return;
                        }

                        IFCAnyHandle   ownerHistory    = exporterIFC.GetOwnerHistoryHandle();
                        ElementId      typeId          = element.GetTypeId();
                        ElementType    type            = element.Document.GetElement(typeId) as ElementType;
                        FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(typeId, false);

                        bool found = currentTypeInfo.IsValid();
                        if (!found)
                        {
                            string typeGUID            = ExporterIFCUtils.CreateGUID(type);
                            string origTypeName        = exporterIFC.GetName();
                            string typeName            = NamingUtil.GetNameOverride(type, origTypeName);
                            string typeObjectType      = NamingUtil.CreateIFCObjectName(exporterIFC, type);
                            string applicableOccurance = NamingUtil.GetObjectTypeOverride(type, typeObjectType);
                            string typeDescription     = NamingUtil.GetDescriptionOverride(type, null);
                            string typeElemId          = NamingUtil.CreateIFCElementId(type);

                            HashSet <IFCAnyHandle> propertySetsOpt = new HashSet <IFCAnyHandle>();
                            IList <IFCAnyHandle>   repMapListOpt   = new List <IFCAnyHandle>();

                            IFCAnyHandle styleHandle = FamilyExporterUtil.ExportGenericType(file, exportType, ifcEnumType, typeGUID, ownerHistory, typeName,
                                                                                            typeDescription, applicableOccurance, propertySetsOpt, repMapListOpt, typeElemId, typeName, element, type);
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle))
                            {
                                currentTypeInfo.Style = styleHandle;
                                ExporterCacheManager.TypeObjectsCache.Register(typeId, false, currentTypeInfo);
                            }
                        }
                        string instanceGUID        = ExporterIFCUtils.CreateGUID(element);
                        string origInstanceName    = exporterIFC.GetName();
                        string instanceName        = NamingUtil.GetNameOverride(element, origInstanceName);
                        string objectType          = NamingUtil.CreateIFCObjectName(exporterIFC, element);
                        string instanceObjectType  = NamingUtil.GetObjectTypeOverride(element, objectType);
                        string instanceDescription = NamingUtil.GetDescriptionOverride(element, null);
                        string instanceElemId      = NamingUtil.CreateIFCElementId(element);

                        bool roomRelated = !FamilyExporterUtil.IsDistributionFlowElementSubType(exportType);

                        ElementId roomId = ElementId.InvalidElementId;
                        if (roomRelated)
                        {
                            roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse);
                        }

                        IFCAnyHandle instanceHandle = null;
                        if (FamilyExporterUtil.IsFurnishingElementSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFurnishingElement(file, instanceGUID, ownerHistory,
                                                                                         instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }
                        else if (FamilyExporterUtil.IsDistributionFlowElementSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateDistributionFlowElement(file, instanceGUID, ownerHistory,
                                                                                               instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }
                        else if (FamilyExporterUtil.IsEnergyConversionDeviceSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateEnergyConversionDevice(file, instanceGUID, ownerHistory,
                                                                                              instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }
                        else if (FamilyExporterUtil.IsFlowFittingSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowFitting(file, instanceGUID, ownerHistory,
                                                                                   instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }
                        else if (FamilyExporterUtil.IsFlowMovingDeviceSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowMovingDevice(file, instanceGUID, ownerHistory,
                                                                                        instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }
                        else if (FamilyExporterUtil.IsFlowSegmentSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowSegment(file, instanceGUID, ownerHistory,
                                                                                   instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }
                        else if (FamilyExporterUtil.IsFlowStorageDeviceSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowStorageDevice(file, instanceGUID, ownerHistory,
                                                                                         instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }
                        else if (FamilyExporterUtil.IsFlowTerminalSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowTerminal(file, instanceGUID, ownerHistory,
                                                                                    instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }
                        else if (FamilyExporterUtil.IsFlowTreatmentDeviceSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowTreatmentDevice(file, instanceGUID, ownerHistory,
                                                                                           instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }
                        else if (FamilyExporterUtil.IsFlowControllerSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowController(file, instanceGUID, ownerHistory,
                                                                                      instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceElemId);
                        }

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

                        if (roomId != ElementId.InvalidElementId)
                        {
                            exporterIFC.RelateSpatialElement(roomId, instanceHandle);
                            productWrapper.AddElement(instanceHandle, setter, extraParams, false);
                        }
                        else
                        {
                            productWrapper.AddElement(instanceHandle, setter, extraParams, LevelUtil.AssociateElementToLevel(element));
                        }

                        OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, element, extraParams, exporterIFC, localPlacementToUse, setter, productWrapper);

                        if (currentTypeInfo.IsValid())
                        {
                            ExporterCacheManager.TypeRelationsCache.Add(currentTypeInfo.Style, instanceHandle);
                        }

                        PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, productWrapper);

                        ExporterCacheManager.MEPCache.Register(element, instanceHandle);

                        tr.Commit();
                    }
                }
            }
        }
Example #3
0
        /// <summary>
        /// Exports a beam to IFC beam.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="element">
        /// The element to be exported.
        /// </param>
        /// <param name="geometryElement">
        /// The geometry element.
        /// </param>
        /// <param name="productWrapper">
        /// The ProductWrapper.
        /// </param>
        public static void ExportBeam(ExporterIFC exporterIFC,
           Element element, GeometryElement geometryElement, ProductWrapper productWrapper)
        {
            if (geometryElement == null)
                return;

            IFCFile file = exporterIFC.GetFile();
            double scale = exporterIFC.LinearScale;

            using (IFCTransaction transaction = new IFCTransaction(file))
            {
                LocationCurve locCurve = element.Location as LocationCurve;
                Transform orientTrf = Transform.Identity;

                bool canExportAxis = (locCurve != null);
                IFCAnyHandle axisRep = null;

                XYZ beamDirection = null;
                XYZ projDir = null;
                Curve curve = null;

                Plane plane = null;
                if (canExportAxis)
                {
                    curve = locCurve.Curve;
                    if (curve is Line)
                    {
                        Line line = curve as Line;
                        XYZ planeY, planeOrig;
                        planeOrig = line.get_EndPoint(0);
                        beamDirection = line.Direction;
                        if (Math.Abs(beamDirection.Z) < 0.707)  // approx 1.0/sqrt(2.0)
                        {
                            planeY = XYZ.BasisZ.CrossProduct(beamDirection);
                        }
                        else
                        {
                            planeY = XYZ.BasisX.CrossProduct(beamDirection);
                        }
                        planeY = planeY.Normalize();
                        projDir = beamDirection.CrossProduct(planeY);
                        plane = new Plane(beamDirection, planeY, planeOrig);
                        orientTrf.BasisX = beamDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = planeOrig;
                    }
                    else if (curve is Arc)
                    {
                        XYZ yDir, center;
                        Arc arc = curve as Arc;
                        beamDirection = arc.XDirection; yDir = arc.YDirection; projDir = arc.Normal; center = arc.Center;
                        plane = new Plane(beamDirection, yDir, center);
                        orientTrf.BasisX = beamDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center;
                    }
                    else
                        canExportAxis = false;
                }

                using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, canExportAxis ? orientTrf : null, ExporterUtil.GetBaseLevelIdForElement(element)))
                {
                    IFCAnyHandle localPlacement = setter.GetPlacement();
                    SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement);

                    using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData())
                    {
                        extrusionCreationData.SetLocalPlacement(localPlacement);
                        if (canExportAxis && (orientTrf.BasisX != null))
                        {
                            extrusionCreationData.CustomAxis = beamDirection;
                            extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom;
                        }
                        else
                            extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryXY;

                        IList<Solid> solids = solidMeshInfo.GetSolids();
                        IList<Mesh> meshes = solidMeshInfo.GetMeshes();
                        
                        ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                        // The representation handle generated from one of the methods below.
                        IFCAnyHandle repHnd = null;

                        // The list of materials in the solids or meshes.
                        ICollection<ElementId> materialIds = new HashSet<ElementId>();

                        // There may be an offset to make the local coordinate system
                        // be near the origin.  This offset will be used to move the axis to the new LCS.
                        Transform offsetTransform = null;
                        
                        // If we have a beam with a Linear location line that only has one solid geometry,
                        // we will try to use the ExtrusionAnalyzer to generate an extrusion with 0 or more clippings.
                        // This code is currently limited in that it will not process beams with openings, so we
                        // use other methods below if this one fails.
                        if (solids.Count == 1 && meshes.Count == 0 && (canExportAxis && (curve is Line)))
                        {
                            bool completelyClipped;
                            beamDirection = orientTrf.BasisX;
                            Plane beamExtrusionPlane = new Plane(orientTrf.BasisY, orientTrf.BasisZ, orientTrf.Origin);
                            repHnd = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, element,
                                catId, solids[0], beamExtrusionPlane, beamDirection, null, out completelyClipped);
                            if (completelyClipped)
                                return;

                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd))
                            {
                                // This is used by the BeamSlopeCalculator.  This should probably be generated automatically by
                                // CreateExtrusionWithClipping.
                                IFCExtrusionBasis bestAxis = (Math.Abs(beamDirection[0]) > Math.Abs(beamDirection[1])) ?
                                    IFCExtrusionBasis.BasisX : IFCExtrusionBasis.BasisY;
                                extrusionCreationData.Slope = GeometryUtil.GetSimpleExtrusionSlope(beamDirection, bestAxis);
                                ElementId materialId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids[0], exporterIFC, element);
                                if (materialId != ElementId.InvalidElementId)
                                    materialIds.Add(materialId);
                            }
                        }

                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd))
                        {
                            BodyData bodyData = null;

                            BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true);
                            if (solids.Count > 0 || meshes.Count > 0)
                            {
                                bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId,
                                    solids, meshes, bodyExporterOptions, extrusionCreationData);
                            }
                            else
                            {
                                IList<GeometryObject> geomlist = new List<GeometryObject>();
                                geomlist.Add(geometryElement);
                                bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, 
                                    geomlist, bodyExporterOptions, extrusionCreationData);
                            }
                            repHnd = bodyData.RepresentationHnd;
                            materialIds = bodyData.MaterialIds;
                            offsetTransform = bodyData.OffsetTransform;
                        }

                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd))
                        {
                            extrusionCreationData.ClearOpenings();
                            return;
                        }

                        IList<IFCAnyHandle> representations = new List<IFCAnyHandle>();

                        if (canExportAxis)
                        {
                            XYZ curveOffset = new XYZ(0, 0, 0);
                            if (offsetTransform != null)
                            {
                                curveOffset = -offsetTransform.Origin / scale;
                            }
                            else
                            {
                                // Note that we do not have to have any scaling adjustment here, since the curve origin is in the 
                                // same internal coordinate system as the curve.
                                curveOffset = -plane.Origin;
                            }

                            Plane offsetPlane = new Plane(plane.XVec, plane.YVec, XYZ.Zero);
                            IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetPlane, projDir, false);
                            ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true);
                            
                            IList<IFCAnyHandle> axis_items = info.GetCurves();

                            if (axis_items.Count > 0)
                            {
                                string identifierOpt = "Axis";	// this is by IFC2x2 convention, not temporary
                                string representationTypeOpt = "Curve2D";  // this is by IFC2x2 convention, not temporary
                                axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt),
                                   identifierOpt, representationTypeOpt, axis_items);
                                representations.Add(axisRep);
                            }
                        }
                        representations.Add(repHnd);

                        Transform boundingBoxTrf = (offsetTransform == null) ? Transform.Identity : offsetTransform.Inverse;
                        IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, boundingBoxTrf);
                        if (boundingBoxRep != null)
                            representations.Add(boundingBoxRep);

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

                        string instanceGUID = GUIDUtil.CreateGUID(element);
                        string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                        string instanceDescription = NamingUtil.GetDescriptionOverride(element, null);
                        string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element));
                        string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element));

                        IFCAnyHandle beam = IFCInstanceExporter.CreateBeam(file, instanceGUID, exporterIFC.GetOwnerHistoryHandle(),
                            instanceName, instanceDescription, instanceObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, instanceTag);

                        productWrapper.AddElement(element, beam, setter, extrusionCreationData, true);

                        OpeningUtil.CreateOpeningsIfNecessary(beam, element, extrusionCreationData, offsetTransform, exporterIFC, 
                            extrusionCreationData.GetLocalPlacement(), setter, productWrapper);

                        FamilyTypeInfo typeInfo = new FamilyTypeInfo();
                        typeInfo.ScaledDepth = extrusionCreationData.ScaledLength;
                        typeInfo.ScaledArea = extrusionCreationData.ScaledArea;
                        typeInfo.ScaledInnerPerimeter = extrusionCreationData.ScaledInnerPerimeter;
                        typeInfo.ScaledOuterPerimeter = extrusionCreationData.ScaledOuterPerimeter;
                        PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, beam, element, typeInfo);

                        if (materialIds.Count != 0)
                        {
                            CategoryUtil.CreateMaterialAssociations(exporterIFC, beam, materialIds);
                        }

                        // Register the beam's IFC handle for later use by truss and beam system export.
                        ExporterCacheManager.ElementToHandleCache.Register(element.Id, beam);
                    }
                }

                transaction.Commit();
            }
        }
Example #4
0
        /// <summary>
        /// Exports a beam to IFC beam.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="element">
        /// The element to be exported.
        /// </param>
        /// <param name="geometryElement">
        /// The geometry element.
        /// </param>
        /// <param name="productWrapper">
        /// The ProductWrapper.
        /// </param>
        public static void ExportBeam(ExporterIFC exporterIFC,
                                      Element element, GeometryElement geometryElement, ProductWrapper productWrapper)
        {
            if (geometryElement == null)
            {
                return;
            }

            IFCFile file  = exporterIFC.GetFile();
            double  scale = exporterIFC.LinearScale;

            using (IFCTransaction transaction = new IFCTransaction(file))
            {
                LocationCurve locCurve  = element.Location as LocationCurve;
                Transform     orientTrf = Transform.Identity;

                bool         canExportAxis = (locCurve != null);
                IFCAnyHandle axisRep       = null;

                XYZ   beamDirection = null;
                XYZ   projDir       = null;
                Curve curve         = null;

                Plane plane = null;
                if (canExportAxis)
                {
                    curve = locCurve.Curve;
                    if (curve is Line)
                    {
                        Line line = curve as Line;
                        XYZ  planeY, planeOrig;
                        planeOrig     = line.get_EndPoint(0);
                        beamDirection = line.Direction;
                        if (Math.Abs(beamDirection.Z) < 0.707)  // approx 1.0/sqrt(2.0)
                        {
                            planeY = XYZ.BasisZ.CrossProduct(beamDirection);
                        }
                        else
                        {
                            planeY = XYZ.BasisX.CrossProduct(beamDirection);
                        }
                        planeY           = planeY.Normalize();
                        projDir          = beamDirection.CrossProduct(planeY);
                        plane            = new Plane(beamDirection, planeY, planeOrig);
                        orientTrf.BasisX = beamDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = planeOrig;
                    }
                    else if (curve is Arc)
                    {
                        XYZ yDir, center;
                        Arc arc = curve as Arc;
                        beamDirection    = arc.XDirection; yDir = arc.YDirection; projDir = arc.Normal; center = arc.Center;
                        plane            = new Plane(beamDirection, yDir, center);
                        orientTrf.BasisX = beamDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center;
                    }
                    else
                    {
                        canExportAxis = false;
                    }
                }

                using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, canExportAxis ? orientTrf : null, ExporterUtil.GetBaseLevelIdForElement(element)))
                {
                    IFCAnyHandle          localPlacement = setter.GetPlacement();
                    SolidMeshGeometryInfo solidMeshInfo  = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement);

                    using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData())
                    {
                        extrusionCreationData.SetLocalPlacement(localPlacement);
                        if (canExportAxis && (orientTrf.BasisX != null))
                        {
                            extrusionCreationData.CustomAxis            = beamDirection;
                            extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom;
                        }
                        else
                        {
                            extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryXY;
                        }

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

                        ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                        // The representation handle generated from one of the methods below.
                        IFCAnyHandle repHnd = null;

                        // The list of materials in the solids or meshes.
                        ICollection <ElementId> materialIds = new HashSet <ElementId>();

                        // There may be an offset to make the local coordinate system
                        // be near the origin.  This offset will be used to move the axis to the new LCS.
                        Transform offsetTransform = null;

                        // If we have a beam with a Linear location line that only has one solid geometry,
                        // we will try to use the ExtrusionAnalyzer to generate an extrusion with 0 or more clippings.
                        // This code is currently limited in that it will not process beams with openings, so we
                        // use other methods below if this one fails.
                        if (solids.Count == 1 && meshes.Count == 0 && (canExportAxis && (curve is Line)))
                        {
                            bool completelyClipped;
                            beamDirection = orientTrf.BasisX;
                            Plane beamExtrusionPlane = new Plane(orientTrf.BasisY, orientTrf.BasisZ, orientTrf.Origin);
                            repHnd = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, element,
                                                                                   catId, solids[0], beamExtrusionPlane, beamDirection, null, out completelyClipped);
                            if (completelyClipped)
                            {
                                return;
                            }

                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd))
                            {
                                // This is used by the BeamSlopeCalculator.  This should probably be generated automatically by
                                // CreateExtrusionWithClipping.
                                IFCExtrusionBasis bestAxis = (Math.Abs(beamDirection[0]) > Math.Abs(beamDirection[1])) ?
                                                             IFCExtrusionBasis.BasisX : IFCExtrusionBasis.BasisY;
                                extrusionCreationData.Slope = GeometryUtil.GetSimpleExtrusionSlope(beamDirection, bestAxis);
                                ElementId materialId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids[0], exporterIFC, element);
                                if (materialId != ElementId.InvalidElementId)
                                {
                                    materialIds.Add(materialId);
                                }
                            }
                        }

                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd))
                        {
                            BodyData bodyData = null;

                            BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true);
                            if (solids.Count > 0 || meshes.Count > 0)
                            {
                                bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId,
                                                                   solids, meshes, bodyExporterOptions, extrusionCreationData);
                            }
                            else
                            {
                                IList <GeometryObject> geomlist = new List <GeometryObject>();
                                geomlist.Add(geometryElement);
                                bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId,
                                                                   geomlist, bodyExporterOptions, extrusionCreationData);
                            }
                            repHnd          = bodyData.RepresentationHnd;
                            materialIds     = bodyData.MaterialIds;
                            offsetTransform = bodyData.OffsetTransform;
                        }

                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd))
                        {
                            extrusionCreationData.ClearOpenings();
                            return;
                        }

                        IList <IFCAnyHandle> representations = new List <IFCAnyHandle>();

                        if (canExportAxis)
                        {
                            XYZ curveOffset = new XYZ(0, 0, 0);
                            if (offsetTransform != null)
                            {
                                curveOffset = -offsetTransform.Origin / scale;
                            }
                            else
                            {
                                // Note that we do not have to have any scaling adjustment here, since the curve origin is in the
                                // same internal coordinate system as the curve.
                                curveOffset = -plane.Origin;
                            }

                            Plane           offsetPlane = new Plane(plane.XVec, plane.YVec, XYZ.Zero);
                            IFCGeometryInfo info        = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetPlane, projDir, false);
                            ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true);

                            IList <IFCAnyHandle> axis_items = info.GetCurves();

                            if (axis_items.Count > 0)
                            {
                                string identifierOpt         = "Axis";    // this is by IFC2x2 convention, not temporary
                                string representationTypeOpt = "Curve2D"; // this is by IFC2x2 convention, not temporary
                                axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt),
                                                                                       identifierOpt, representationTypeOpt, axis_items);
                                representations.Add(axisRep);
                            }
                        }
                        representations.Add(repHnd);

                        Transform    boundingBoxTrf = (offsetTransform == null) ? Transform.Identity : offsetTransform.Inverse;
                        IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, boundingBoxTrf);
                        if (boundingBoxRep != null)
                        {
                            representations.Add(boundingBoxRep);
                        }

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

                        string instanceGUID        = GUIDUtil.CreateGUID(element);
                        string instanceName        = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                        string instanceDescription = NamingUtil.GetDescriptionOverride(element, null);
                        string instanceObjectType  = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element));
                        string instanceTag         = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element));

                        IFCAnyHandle beam = IFCInstanceExporter.CreateBeam(file, instanceGUID, exporterIFC.GetOwnerHistoryHandle(),
                                                                           instanceName, instanceDescription, instanceObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, instanceTag);

                        productWrapper.AddElement(element, beam, setter, extrusionCreationData, true);

                        OpeningUtil.CreateOpeningsIfNecessary(beam, element, extrusionCreationData, offsetTransform, exporterIFC,
                                                              extrusionCreationData.GetLocalPlacement(), setter, productWrapper);

                        FamilyTypeInfo typeInfo = new FamilyTypeInfo();
                        typeInfo.ScaledDepth          = extrusionCreationData.ScaledLength;
                        typeInfo.ScaledArea           = extrusionCreationData.ScaledArea;
                        typeInfo.ScaledInnerPerimeter = extrusionCreationData.ScaledInnerPerimeter;
                        typeInfo.ScaledOuterPerimeter = extrusionCreationData.ScaledOuterPerimeter;
                        PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, beam, element, typeInfo);

                        if (materialIds.Count != 0)
                        {
                            CategoryUtil.CreateMaterialAssociations(exporterIFC, beam, materialIds);
                        }

                        // Register the beam's IFC handle for later use by truss and beam system export.
                        ExporterCacheManager.ElementToHandleCache.Register(element.Id, beam);
                    }
                }

                transaction.Commit();
            }
        }
        /// <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);
                        }
                    }
                }
            }
        }
        private static IFCAnyHandle CreateFamilyTypeHandle(ExporterIFC exporterIFC, FamilyTypeInfo typeInfo, IFCDoorWindowInfo doorWindowInfo, 
            IFCAnyHandle bodyRepresentation, IFCAnyHandle planRepresentation,
            Element familyInstance, ElementType familySymbol, ElementType originalFamilySymbol, 
            bool useInstanceGeometry, bool exportParts,
            IFCExportType exportType, string revitObjectType, string ifcEnumType, 
            out HashSet<IFCAnyHandle> propertySets)
        {
            // for many
            propertySets = new HashSet<IFCAnyHandle>();

            IFCFile file = exporterIFC.GetFile();

            IFCAnyHandle repMap2dHnd = null;
            IFCAnyHandle repMap3dHnd = null;

            IList<IFCAnyHandle> repMapList = new List<IFCAnyHandle>();
            {
                IFCAnyHandle origin = null;
                if (bodyRepresentation != null)
                {
                    if (origin == null)
                        origin = ExporterUtil.CreateAxis2Placement3D(file);
                    repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRepresentation);
                    repMapList.Add(repMap3dHnd);
                }

                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(planRepresentation))
                {
                    if (origin == null)
                        origin = ExporterUtil.CreateAxis2Placement3D(file);
                    repMap2dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, planRepresentation);
                    repMapList.Add(repMap2dHnd);
                }
            }

            // We won't allow creating a type if we aren't creating an instance.
            // We won't create the instance if: we are exporting to CV2.0, we have no 2D, 3D, or bounding box geometry, and we aren't exporting parts.
            bool willCreateInstance = !(repMapList.Count == 0 && ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 &&
                !ExporterCacheManager.ExportOptionsCache.ExportBoundingBox && !exportParts);
            if (!willCreateInstance)
                return null;

            IFCAnyHandle typeStyle = null;

            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

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

            string guid = useInstanceGeometry ?
                GUIDUtil.CreateSubElementGUID(familyInstance, (int)IFCFamilyInstanceSubElements.InstanceAsType) :
                GUIDUtil.CreateGUID(originalFamilySymbol);
            string symId = NamingUtil.CreateIFCElementId(originalFamilySymbol);

            string gentypeName = NamingUtil.GetNameOverride(familySymbol, revitObjectType);
            string gentypeDescription = NamingUtil.GetDescriptionOverride(familySymbol, null);
            string gentypeApplicableOccurrence = NamingUtil.GetOverrideStringValue(familySymbol, "IfcApplicableOccurrence", null);
            string gentypeTag = NamingUtil.GetTagOverride(familySymbol, symId);
            string gentypeElementType = NamingUtil.GetOverrideStringValue(familySymbol, "IfcElementType", revitObjectType);

            // This covers many generic types.  If we can't find it in the list here, do custom exports.
            typeStyle = FamilyExporterUtil.ExportGenericType(exporterIFC, exportType, ifcEnumType, guid,
               gentypeName, gentypeDescription, gentypeApplicableOccurrence, propertySets, repMapList, gentypeTag, gentypeElementType,
               familyInstance, familySymbol);

            // Cover special cases not covered above.
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle))
            {
                string symbolTag = NamingUtil.GetTagOverride(familySymbol, NamingUtil.CreateIFCElementId(familySymbol));
                switch (exportType)
                {
                    case IFCExportType.ExportColumnType:
                        {
                            string columnType = "Column";
                            typeStyle = IFCInstanceExporter.CreateColumnType(file, guid, ownerHistory, gentypeName,
                                gentypeDescription, gentypeApplicableOccurrence, propertySets, repMapList, symbolTag,
                                gentypeElementType, GetColumnType(familyInstance, columnType));
                            break;
                        }
                    case IFCExportType.ExportDoorType:
                        {
                            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.CreateSubElementGUID(originalFamilySymbol, (int)IFCDoorSubElements.DoorStyle);
                                typeStyle = IFCInstanceExporter.CreateDoorStyle(file, doorStyleGUID, ownerHistory, gentypeName,
                                   gentypeDescription, gentypeApplicableOccurrence, propertySets, repMapList, symbolTag,
                                DoorWindowUtil.GetDoorStyleOperation(doorWindowInfo.DoorOperationType),
                                DoorWindowUtil.GetDoorStyleConstruction(familyInstance),
                                   paramTakesPrecedence, sizeable);
                            break;
                        }
                    case IFCExportType.ExportSpace:
                        {
                            typeStyle = IFCInstanceExporter.CreateSpaceType(file, guid, ownerHistory, gentypeName,
                               gentypeDescription, gentypeApplicableOccurrence, propertySets, repMapList, symbolTag,
                               gentypeElementType);

                            break;
                        }
                    case IFCExportType.ExportSystemFurnitureElementType:
                        {
                            typeStyle = IFCInstanceExporter.CreateSystemFurnitureElementType(file, guid, ownerHistory, gentypeName,
                               gentypeDescription, gentypeApplicableOccurrence, propertySets, repMapList, symbolTag,
                               gentypeElementType);

                            break;
                        }
                    case IFCExportType.ExportWindowType:
                        {
                            Toolkit.IFCWindowStyleOperation operationType = DoorWindowUtil.GetIFCWindowStyleOperation(originalFamilySymbol);
                            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.CreateSubElementGUID(originalFamilySymbol, (int)IFCWindowSubElements.WindowStyle);

                                typeStyle = IFCInstanceExporter.CreateWindowStyle(file, windowStyleGUID, ownerHistory, gentypeName,
                                   gentypeDescription, gentypeApplicableOccurrence, propertySets, repMapList, symbolTag,
                                   constructionType, operationType, paramTakesPrecedence, sizeable);
                            break;
                        }
                    case IFCExportType.ExportBuildingElementProxy:
                    case IFCExportType.ExportBuildingElementProxyType:
                        {
                            typeStyle = IFCInstanceExporter.CreateBuildingElementProxyType(file, guid, ownerHistory, gentypeName,
                                gentypeDescription, gentypeApplicableOccurrence, propertySets, repMapList, symbolTag,
                                gentypeElementType, FamilyExporterUtil.GetBuildingElementProxyType(familyInstance, ifcEnumType));
                            break;
                        }
                }

                if (IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle))
                {
                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd))
                        typeInfo.Map2DHandle = repMap2dHnd;
                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd))
                        typeInfo.Map3DHandle = repMap3dHnd;
                }
            }

            return typeStyle;
        }
        /// <summary>
        /// Exports a MEP family instance.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="element">The element.</param>
        /// <param name="geometryElement">The geometry element.</param>
        /// <param name="exportType">The export type of the element.
        /// <param name="ifcEnumType">The sub-type of the element.</param></param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        /// <returns>True if an entity was created, false otherwise.</returns>
        public static bool Export(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement,
                                  IFCExportType exportType, string ifcEnumType, ProductWrapper productWrapper)
        {
            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, null, ExporterUtil.GetBaseLevelIdForElement(element)))
                {
                    IFCAnyHandle localPlacementToUse = setter.GetPlacement();
                    using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData())
                    {
                        extraParams.SetLocalPlacement(localPlacementToUse);

                        ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                        BodyExporterOptions bodyExporterOptions   = new BodyExporterOptions(true);
                        BodyData            bodyData              = null;
                        IFCAnyHandle        productRepresentation = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC,
                                                                                                                               element, catId, geometryElement, bodyExporterOptions, null, extraParams, out bodyData);
                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(productRepresentation))
                        {
                            extraParams.ClearOpenings();
                            return(false);
                        }

                        IFCAnyHandle   ownerHistory    = exporterIFC.GetOwnerHistoryHandle();
                        ElementId      typeId          = element.GetTypeId();
                        ElementType    type            = element.Document.GetElement(typeId) as ElementType;
                        FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(typeId, false);

                        bool found = currentTypeInfo.IsValid();
                        if (!found)
                        {
                            string typeGUID            = GUIDUtil.CreateGUID(type);
                            string typeName            = NamingUtil.GetNameOverride(type, NamingUtil.GetIFCName(type));
                            string typeObjectType      = NamingUtil.GetObjectTypeOverride(type, NamingUtil.CreateIFCObjectName(exporterIFC, type));
                            string applicableOccurence = NamingUtil.GetOverrideStringValue(type, "IfcApplicableOccurrence", typeObjectType);
                            string typeDescription     = NamingUtil.GetDescriptionOverride(type, null);
                            string typeTag             = NamingUtil.GetTagOverride(type, NamingUtil.CreateIFCElementId(type));
                            string typeElementType     = NamingUtil.GetOverrideStringValue(type, "IfcElementType", typeName);

                            IList <IFCAnyHandle> repMapListOpt = new List <IFCAnyHandle>();

                            IFCAnyHandle styleHandle = FamilyExporterUtil.ExportGenericType(exporterIFC, exportType, ifcEnumType, typeGUID, typeName,
                                                                                            typeDescription, applicableOccurence, null, repMapListOpt, typeTag, typeElementType, element, type);
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle))
                            {
                                productWrapper.RegisterHandleWithElementType(type, styleHandle, null);

                                currentTypeInfo.Style = styleHandle;
                                ExporterCacheManager.TypeObjectsCache.Register(typeId, false, currentTypeInfo);
                            }
                        }
                        string instanceGUID        = GUIDUtil.CreateGUID(element);
                        string instanceName        = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                        string instanceObjectType  = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element));
                        string instanceDescription = NamingUtil.GetDescriptionOverride(element, null);
                        string instanceTag         = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element));

                        bool roomRelated = !FamilyExporterUtil.IsDistributionFlowElementSubType(exportType);

                        ElementId roomId = ElementId.InvalidElementId;
                        if (roomRelated)
                        {
                            roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse);
                        }

                        IFCAnyHandle instanceHandle = null;
                        if (FamilyExporterUtil.IsFurnishingElementSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFurnishingElement(file, instanceGUID, ownerHistory,
                                                                                         instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }
                        else if (FamilyExporterUtil.IsDistributionFlowElementSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateDistributionFlowElement(file, instanceGUID, ownerHistory,
                                                                                               instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }
                        else if (FamilyExporterUtil.IsEnergyConversionDeviceSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateEnergyConversionDevice(file, instanceGUID, ownerHistory,
                                                                                              instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }
                        else if (FamilyExporterUtil.IsFlowFittingSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowFitting(file, instanceGUID, ownerHistory,
                                                                                   instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }
                        else if (FamilyExporterUtil.IsFlowMovingDeviceSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowMovingDevice(file, instanceGUID, ownerHistory,
                                                                                        instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }
                        else if (FamilyExporterUtil.IsFlowSegmentSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowSegment(file, instanceGUID, ownerHistory,
                                                                                   instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }
                        else if (FamilyExporterUtil.IsFlowStorageDeviceSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowStorageDevice(file, instanceGUID, ownerHistory,
                                                                                         instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }
                        else if (FamilyExporterUtil.IsFlowTerminalSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowTerminal(file, instanceGUID, ownerHistory,
                                                                                    instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }
                        else if (FamilyExporterUtil.IsFlowTreatmentDeviceSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowTreatmentDevice(file, instanceGUID, ownerHistory,
                                                                                           instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }
                        else if (FamilyExporterUtil.IsFlowControllerSubType(exportType))
                        {
                            instanceHandle = IFCInstanceExporter.CreateFlowController(file, instanceGUID, ownerHistory,
                                                                                      instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag);
                        }

                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle))
                        {
                            return(false);
                        }

                        bool relatedToSpace = (roomId != ElementId.InvalidElementId);
                        productWrapper.AddElement(element, instanceHandle, setter, extraParams, !relatedToSpace);
                        if (relatedToSpace)
                        {
                            exporterIFC.RelateSpatialElement(roomId, instanceHandle);
                        }

                        OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, element, extraParams, null,
                                                              exporterIFC, localPlacementToUse, setter, productWrapper);

                        if (currentTypeInfo.IsValid())
                        {
                            ExporterCacheManager.TypeRelationsCache.Add(currentTypeInfo.Style, instanceHandle);
                        }

                        if (bodyData != null && bodyData.MaterialIds.Count != 0)
                        {
                            CategoryUtil.CreateMaterialAssociations(exporterIFC, instanceHandle, bodyData.MaterialIds);
                        }

                        ExporterCacheManager.MEPCache.Register(element, instanceHandle);

                        tr.Commit();
                    }
                }
            }
            return(true);
        }