/// <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();
                    IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData();

                    ElementId catId = CategoryUtil.GetSafeCategoryId(element);


                    IFCSolidMeshGeometryInfo solidMeshInfo = ExporterIFCUtils.GetSolidMeshGeometry(exporterIFC, geometryElement, Transform.Identity);
                    IList<Solid> solids = solidMeshInfo.GetSolids();
                    IList<Mesh> polyMeshes = solidMeshInfo.GetMeshes();

                    bool tryToExportAsExtrusion = true;
                    if (solids.Count != 1 || polyMeshes.Count != 0)
                        tryToExportAsExtrusion = false;

                    IFCAnyHandle shapeRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, catId, solids, polyMeshes, tryToExportAsExtrusion, extraParams);
                    if (!shapeRep.HasValue)
                        return;

                    IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>();
                    shapeReps.Add(shapeRep);
                    IFCAnyHandle productRepresentation = file.CreateProductDefinitionShape(IFCLabel.Create(), IFCLabel.Create(), shapeReps);

                    IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();
                    ElementId typeId = element.GetTypeId();
                    ElementType type = element.Document.get_Element(typeId) as ElementType;
                    IFCTypeInfo currentTypeInfo = exporterIFC.FindType(typeId, false);

                    bool found = currentTypeInfo.IsValid();
                    if (!found)
                    {
                        IFCLabel typeGUID = IFCLabel.CreateGUID(type);
                        IFCLabel origTypeName = NamingUtil.CreateIFCName(exporterIFC, -1);
                        IFCLabel typeName = NamingUtil.GetNameOverride(type, origTypeName);
                        IFCLabel typeObjectType = NamingUtil.CreateIFCObjectName(exporterIFC, type);
                        IFCLabel applicableOccurance = NamingUtil.GetObjectTypeOverride(type, typeObjectType);
                        IFCLabel typeDescription = NamingUtil.GetDescriptionOverride(type, IFCLabel.Create());
                        IFCLabel 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 (styleHandle.HasValue)
                        {
                            currentTypeInfo.SetStyle(styleHandle);
                            exporterIFC.AddType(typeId, false, currentTypeInfo);
                        }
                    }
                    IFCLabel instanceGUID = IFCLabel.CreateGUID(element);
                    IFCLabel origInstanceName = NamingUtil.CreateIFCName(exporterIFC, -1);
                    IFCLabel instanceName = NamingUtil.GetNameOverride(element, origInstanceName);
                    IFCLabel objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element);
                    IFCLabel instanceObjectType = NamingUtil.GetObjectTypeOverride(element, objectType);
                    IFCLabel instanceDescription = NamingUtil.GetDescriptionOverride(element, IFCLabel.Create());
                    IFCLabel instanceElemId = NamingUtil.CreateIFCElementId(element);

                    bool roomRelated = !FamilyExporterUtil.IsDistributionFlowElementSubType(exportType);

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

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

                    if (!instanceHandle.HasValue)
                        return;

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

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

                    if (currentTypeInfo.IsValid())
                        exporterIFC.AddTypeRelation(currentTypeInfo.GetStyle(), instanceHandle);

                    ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, element, productWrapper);

                    tr.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 IFCProductWrapper.
        /// </param>
        /// <param name="overrideLevelId">
        /// The level id.
        /// </param>
        /// <param name="range">
        /// The range of this family instance to be exported.
        /// </param>
        public static void ExportFamilyInstanceAsMappedItem(ExporterIFC exporterIFC,
           FamilyInstance familyInstance, IFCExportType exportType, string ifcEnumType,
           IFCProductWrapper wrapper, ElementId overrideLevelId, UV range)
        {
            Document doc = familyInstance.Document;
            IFCFile file = exporterIFC.GetFile();

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

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

            IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle();

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

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

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

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

            Transform trf = familyInstance.GetTransform();

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

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

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

            Family family = familySymbol.Family;

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

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

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

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

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

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

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

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

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

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

                        if (needToCreate3d)
                        {
                            IFCSolidMeshGeometryInfo solidMeshInfo;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                typeInfo.SetStyle(typeStyle);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    if (typeInfo.GetStyle().HasValue)
                        exporterIFC.AddTypeRelation(typeInfo.GetStyle(), instanceHandle);
                }
            }
        }