Esempio n. 1
0
        static IFCAnyHandle CreateLocalPlacementForConnector(ExporterIFC exporterIFC, Connector connector, IFCAnyHandle elementHandle,
                                                             IFCFlowDirection flowDir)
        {
            try
            {
                IFCFile file = exporterIFC.GetFile();

                IFCAnyHandle elementPlacement = IFCAnyHandleUtil.GetObjectPlacement(elementHandle);
                Transform    origTrf          = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, elementPlacement);

                Transform connectorCoordinateSystem = connector.CoordinateSystem;
                if (flowDir == IFCFlowDirection.Sink)
                {
                    // Reverse the direction of the connector.
                    connectorCoordinateSystem.BasisX = -connectorCoordinateSystem.BasisX;
                    connectorCoordinateSystem.BasisZ = -connectorCoordinateSystem.BasisZ;
                }

                Transform relTransform = origTrf.Inverse.Multiply(connectorCoordinateSystem);
                XYZ       scaledOrigin = UnitUtil.ScaleLength(relTransform.Origin);

                IFCAnyHandle relLocalPlacement = ExporterUtil.CreateAxis2Placement3D(file,
                                                                                     scaledOrigin, relTransform.BasisZ, relTransform.BasisX);

                return(IFCInstanceExporter.CreateLocalPlacement(file, elementPlacement, relLocalPlacement));
            }
            catch
            {
            }
            return(null);
        }
        /// <summary>
        /// Update the local placements of the members of an assembly relative to the assembly.
        /// </summary>
        /// <param name="exporterIFC">The ExporerIFC.</param>
        /// <param name="assemblyPlacement">The assembly local placement handle.</param>
        /// <param name="elementPlacements">The member local placement handles.</param>
        public static void SetLocalPlacementsRelativeToAssembly(ExporterIFC exporterIFC, IFCAnyHandle assemblyPlacement, ICollection <IFCAnyHandle> elementPlacements)
        {
            foreach (IFCAnyHandle elementHandle in elementPlacements)
            {
                IFCAnyHandle elementPlacement = IFCAnyHandleUtil.GetObjectPlacement(elementHandle);

                Transform origTrf = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, assemblyPlacement);
                if (!origTrf.IsIdentity)
                {
                    Transform relTrf     = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(assemblyPlacement, elementPlacement);
                    Transform inverseTrf = relTrf.Inverse;

                    IFCFile      file = exporterIFC.GetFile();
                    IFCAnyHandle relLocalPlacement = ExporterUtil.CreateAxis2Placement3D(file, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX);

                    // NOTE: caution that old IFCAXIS2PLACEMENT3D may be unused as the new one replace it.
                    // But we cannot delete it safely yet because we don't know if any handle is referencing it.
                    GeometryUtil.SetRelativePlacement(elementPlacement, relLocalPlacement);
                }
                GeometryUtil.SetPlacementRelTo(elementPlacement, assemblyPlacement);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Exports a CeilingAndFloor element to IFC.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="floor">The floor element.</param>
        /// <param name="geometryElement">The geometry element.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        public static void ExportCeilingAndFloorElement(ExporterIFC exporterIFC, CeilingAndFloor floorElement, GeometryElement geometryElement,
                                                        ProductWrapper productWrapper)
        {
            if (geometryElement == null)
            {
                return;
            }

            // export parts or not
            bool exportParts = PartExporter.CanExportParts(floorElement);

            if (exportParts && !PartExporter.CanExportElementInPartExport(floorElement, floorElement.LevelId, false))
            {
                return;
            }

            IFCFile file = exporterIFC.GetFile();

            string               ifcEnumType;
            IFCExportInfoPair    exportType   = ExporterUtil.GetExportType(exporterIFC, floorElement, out ifcEnumType);
            IFCAnyHandle         type         = null;
            MaterialLayerSetInfo layersetInfo = null;

            if (!ElementFilteringUtil.IsElementVisible(floorElement))
            {
                return;
            }

            // Check the intended IFC entity or type name is in the exclude list specified in the UI
            Common.Enums.IFCEntityType elementClassTypeEnum;
            if (Enum.TryParse <Common.Enums.IFCEntityType>(exportType.ExportInstance.ToString(), out elementClassTypeEnum) ||
                Enum.TryParse <Common.Enums.IFCEntityType>(exportType.ExportType.ToString(), out elementClassTypeEnum))
            {
                if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum))
                {
                    return;
                }
            }

            Document doc = floorElement.Document;

            using (SubTransaction tempPartTransaction = new SubTransaction(doc))
            {
                // For IFC4RV export, Floor will be split into its parts(temporarily) in order to export the floor by its parts
                bool exportByComponents = ExporterUtil.ShouldExportByComponents(floorElement, exportParts);

                using (IFCTransaction tr = new IFCTransaction(file))
                {
                    bool canExportAsContainerOrWithExtrusionAnalyzer = (!exportParts && (floorElement is Floor));

                    if (canExportAsContainerOrWithExtrusionAnalyzer)
                    {
                        // Try to export the Floor slab as a container.  If that succeeds, we are done.
                        // If we do export the floor as a container, it will take care of the local placement and transform there, so we need to leave
                        // this out of the IFCTransformSetter and PlacementSetter scopes below, or else we'll get double transforms.
                        IFCAnyHandle floorHnd = RoofExporter.ExportRoofOrFloorAsContainer(exporterIFC, floorElement, geometryElement, productWrapper);
                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(floorHnd))
                        {
                            tr.Commit();
                            return;
                        }
                    }

                    IList <IFCAnyHandle> slabHnds        = new List <IFCAnyHandle>();
                    IList <IFCAnyHandle> brepSlabHnds    = new List <IFCAnyHandle>();
                    IList <IFCAnyHandle> nonBrepSlabHnds = new List <IFCAnyHandle>();

                    IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle;

                    using (IFCTransformSetter transformSetter = IFCTransformSetter.Create())
                    {
                        // Check for containment override
                        IFCAnyHandle overrideContainerHnd = null;
                        ElementId    overrideContainerId  = ParameterUtil.OverrideContainmentParameter(exporterIFC, floorElement, out overrideContainerHnd);

                        using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, floorElement, null, null, overrideContainerId, overrideContainerHnd))
                        {
                            IFCAnyHandle localPlacement = placementSetter.LocalPlacement;

                            // The routine ExportExtrudedSlabOpenings is called if exportedAsInternalExtrusion is true, and it requires having a valid level association.
                            // Disable calling ExportSlabAsExtrusion if we can't handle potential openings.
                            bool canExportAsInternalExtrusion = placementSetter.LevelInfo != null;
                            bool exportedAsInternalExtrusion  = false;

                            ElementId catId = CategoryUtil.GetSafeCategoryId(floorElement);

                            IList <IFCAnyHandle>             prodReps        = new List <IFCAnyHandle>();
                            IList <ShapeRepresentationType>  repTypes        = new List <ShapeRepresentationType>();
                            IList <IList <CurveLoop> >       extrusionLoops  = new List <IList <CurveLoop> >();
                            IList <IFCExtrusionCreationData> loopExtraParams = new List <IFCExtrusionCreationData>();
                            Plane floorPlane = GeometryUtil.CreateDefaultPlane();

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

                            if (canExportAsContainerOrWithExtrusionAnalyzer)
                            {
                                Floor floor = floorElement as Floor;

                                // Next, try to use the ExtrusionAnalyzer for the limited cases it handles - 1 solid, no openings, end clippings only.
                                // Also limited to cases with line and arc boundaries.
                                //
                                SolidMeshGeometryInfo  solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement);
                                IList <Solid>          solids        = solidMeshInfo.GetSolids();
                                IList <Mesh>           meshes        = solidMeshInfo.GetMeshes();
                                IList <GeometryObject> gObjs         = FamilyExporterUtil.RemoveInvisibleSolidsAndMeshes(floorElement.Document, exporterIFC, ref solids, ref meshes);

                                if (solids.Count == 1 && meshes.Count == 0)
                                {
                                    bool completelyClipped;
                                    // floorExtrusionDirection is set to (0, 0, -1) because extrusionAnalyzerFloorPlane is computed from the top face of the floor
                                    XYZ floorExtrusionDirection = new XYZ(0, 0, -1);
                                    XYZ modelOrigin             = XYZ.Zero;

                                    XYZ floorOrigin = floor.GetVerticalProjectionPoint(modelOrigin, FloorFace.Top);
                                    if (floorOrigin == null)
                                    {
                                        // GetVerticalProjectionPoint may return null if FloorFace.Top is an edited face that doesn't
                                        // go through the Revit model origin.  We'll try the midpoint of the bounding box instead.
                                        BoundingBoxXYZ boundingBox = floorElement.get_BoundingBox(null);
                                        modelOrigin = (boundingBox.Min + boundingBox.Max) / 2.0;
                                        floorOrigin = floor.GetVerticalProjectionPoint(modelOrigin, FloorFace.Top);
                                    }

                                    if (floorOrigin != null)
                                    {
                                        XYZ   floorDir = floor.GetNormalAtVerticalProjectionPoint(floorOrigin, FloorFace.Top);
                                        Plane extrusionAnalyzerFloorBasePlane = GeometryUtil.CreatePlaneByNormalAtOrigin(floorDir);

                                        GenerateAdditionalInfo additionalInfo = GenerateAdditionalInfo.GenerateBody;
                                        additionalInfo |= ExporterCacheManager.ExportOptionsCache.ExportAs4 ?
                                                          GenerateAdditionalInfo.GenerateFootprint : GenerateAdditionalInfo.None;

                                        // Skip generate body item for IFC4RV. It will be handled later in PartExporter.ExportHostPartAsShapeAspects()
                                        if (exportByComponents)
                                        {
                                            additionalInfo &= ~GenerateAdditionalInfo.GenerateBody;
                                        }

                                        HandleAndData floorAndProperties =
                                            ExtrusionExporter.CreateExtrusionWithClippingAndProperties(exporterIFC, floorElement,
                                                                                                       catId, solids[0], extrusionAnalyzerFloorBasePlane, floorOrigin, floorExtrusionDirection, null, out completelyClipped,
                                                                                                       addInfo: additionalInfo);
                                        if (completelyClipped)
                                        {
                                            return;
                                        }

                                        IList <IFCAnyHandle> representations = new List <IFCAnyHandle>();
                                        if (floorAndProperties.Handle != null)
                                        {
                                            representations.Add(floorAndProperties.Handle);
                                            repTypes.Add(ShapeRepresentationType.SweptSolid);
                                        }

                                        // Footprint representation will only be exported in export to IFC4
                                        if (((additionalInfo & GenerateAdditionalInfo.GenerateFootprint) != 0) && (floorAndProperties.FootprintInfo != null))
                                        {
                                            IFCAnyHandle footprintShapeRep = floorAndProperties.FootprintInfo.CreateFootprintShapeRepresentation(exporterIFC);
                                            representations.Add(footprintShapeRep);
                                        }

                                        if (exportByComponents)
                                        {
                                            IFCAnyHandle prodRep = RepresentationUtil.CreateProductDefinitionShapeWithoutBodyRep(exporterIFC, floorElement, catId, geometryElement, representations);
                                            prodReps.Add(prodRep);
                                        }
                                        else if (representations.Count > 0 && floorAndProperties.Handle != null) // Only when at least the body rep exists will come here
                                        {
                                            IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations);
                                            prodReps.Add(prodRep);
                                        }

                                        if (floorAndProperties.Data != null)
                                        {
                                            loopExtraParams.Add(floorAndProperties.Data);
                                        }
                                    }
                                }
                            }

                            // Use internal routine as backup that handles openings.
                            if (prodReps.Count == 0 && canExportAsInternalExtrusion && !exportByComponents)
                            {
                                exportedAsInternalExtrusion = ExporterIFCUtils.ExportSlabAsExtrusion(exporterIFC, floorElement,
                                                                                                     geometryElement, transformSetter, localPlacement, out localPlacements, out prodReps,
                                                                                                     out extrusionLoops, out loopExtraParams, floorPlane);
                                PotentiallyFixPresentationLayerAssignment(floorElement, prodReps);
                                for (int ii = 0; ii < prodReps.Count; ii++)
                                {
                                    // all are extrusions
                                    repTypes.Add(ShapeRepresentationType.SweptSolid);

                                    // Footprint representation will only be exported in export to IFC4
                                    if (ExporterCacheManager.ExportOptionsCache.ExportAs4)
                                    {
                                        if (extrusionLoops.Count > ii)
                                        {
                                            if (extrusionLoops[ii].Count > 0)
                                            {
                                                // Get the extrusion footprint using the first Curveloop. Transform needs to be obtained from the returned local placement
                                                Transform    lcs = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, localPlacements[ii]);
                                                IFCAnyHandle footprintGeomRepItem = GeometryUtil.CreateIFCCurveFromCurveLoop(exporterIFC, extrusionLoops[ii][0], lcs, floorPlane.Normal);

                                                IFCAnyHandle        contextOfItemsFootprint = exporterIFC.Get3DContextHandle("FootPrint");
                                                ISet <IFCAnyHandle> repItem = new HashSet <IFCAnyHandle>();
                                                repItem.Add(footprintGeomRepItem);
                                                IFCAnyHandle         footprintShapeRepresentation = RepresentationUtil.CreateBaseShapeRepresentation(exporterIFC, contextOfItemsFootprint, "FootPrint", "Curve2D", repItem);
                                                IList <IFCAnyHandle> reps = new List <IFCAnyHandle>();
                                                reps.Add(footprintShapeRepresentation);
                                                IFCAnyHandleUtil.AddRepresentations(prodReps[ii], reps);
                                            }
                                        }
                                    }
                                }
                            }

                            IFCAnyHandle prodDefHnd;
                            if (prodReps.Count == 0)
                            {
                                if (exportByComponents)
                                {
                                    prodDefHnd = RepresentationUtil.CreateProductDefinitionShapeWithoutBodyRep(exporterIFC, floorElement, catId, geometryElement, null);
                                    prodReps.Add(prodDefHnd);
                                }
                                else
                                {
                                    using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData())
                                    {
                                        // Brep representation using tesellation after ExportSlabAsExtrusion does not return prodReps
                                        BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.Medium);
                                        BodyData            bodyData;
                                        prodDefHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC,
                                                                                                                floorElement, catId, geometryElement, bodyExporterOptions, null, ecData, out bodyData);
                                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodDefHnd))
                                        {
                                            ecData.ClearOpenings();
                                            return;
                                        }

                                        prodReps.Add(prodDefHnd);
                                        repTypes.Add(bodyData.ShapeRepresentationType);
                                    }
                                }
                            }

                            // Create the slab from either the extrusion or the BRep information.
                            string ifcGUID = GUIDUtil.CreateGUID(floorElement);

                            int numReps = exportParts ? 1 : prodReps.Count;

                            // Deal with a couple of cases that have non-standard defaults.
                            switch (exportType.ExportInstance)
                            {
                            case IFCEntityType.IfcCovering:
                                exportType.ValidatedPredefinedType = IFCValidateEntry.GetValidIFCType <IFCCoveringType>(floorElement, ifcEnumType, "FLOORING");
                                break;

                            case IFCEntityType.IfcSlab:
                                bool            isBaseSlab      = false;
                                AnalyticalModel analyticalModel = floorElement.GetAnalyticalModel();
                                if (analyticalModel != null)
                                {
                                    AnalyzeAs slabFoundationType = analyticalModel.GetAnalyzeAs();
                                    isBaseSlab = (slabFoundationType == AnalyzeAs.SlabOnGrade) || (slabFoundationType == AnalyzeAs.Mat);
                                }
                                exportType.ValidatedPredefinedType = IFCValidateEntry.GetValidIFCType <IFCSlabType>(floorElement, ifcEnumType, isBaseSlab ? "BASESLAB" : "FLOOR");
                                break;
                            }

                            for (int ii = 0; ii < numReps; ii++)
                            {
                                string ifcName = NamingUtil.GetNameOverride(floorElement, NamingUtil.GetIFCNamePlusIndex(floorElement, ii == 0 ? -1 : ii + 1));

                                string       currentGUID       = (ii == 0) ? ifcGUID : GUIDUtil.CreateGUID();
                                IFCAnyHandle localPlacementHnd = exportedAsInternalExtrusion ? localPlacements[ii] : localPlacement;

                                IFCAnyHandle slabHnd = null;
                                slabHnd = IFCInstanceExporter.CreateGenericIFCEntity(exportType, exporterIFC, floorElement, currentGUID, ownerHistory,
                                                                                     localPlacementHnd, exportParts ? null : prodReps[ii]);
                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(slabHnd))
                                {
                                    return;
                                }

                                if (!string.IsNullOrEmpty(ifcName))
                                {
                                    IFCAnyHandleUtil.OverrideNameAttribute(slabHnd, ifcName);
                                }

                                // Pre IFC4 Slab does not have PredefinedType
                                if (!string.IsNullOrEmpty(exportType.ValidatedPredefinedType) && !ExporterCacheManager.ExportOptionsCache.ExportAsOlderThanIFC4)
                                {
                                    IFCAnyHandleUtil.SetAttribute(slabHnd, "PredefinedType", exportType.ValidatedPredefinedType, true);
                                }
                                if (exportParts && !ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView)
                                {
                                    PartExporter.ExportHostPart(exporterIFC, floorElement, slabHnd, productWrapper, placementSetter, localPlacementHnd, null);
                                }
                                else if (exportByComponents)
                                {
                                    IFCExtrusionCreationData partECData            = new IFCExtrusionCreationData();
                                    IFCAnyHandle             hostShapeRepFromParts = PartExporter.ExportHostPartAsShapeAspects(exporterIFC, floorElement, prodReps[ii],
                                                                                                                               productWrapper, placementSetter, localPlacement, ElementId.InvalidElementId, out layersetInfo, partECData);
                                    loopExtraParams.Add(partECData);
                                }

                                slabHnds.Add(slabHnd);

                                // For IFC4RV, export of the geometry is already handled in PartExporter.ExportHostPartAsShapeAspects()
                                if (!exportParts && !exportByComponents)
                                {
                                    if (repTypes[ii] == ShapeRepresentationType.Brep || repTypes[ii] == ShapeRepresentationType.Tessellation)
                                    {
                                        brepSlabHnds.Add(slabHnd);
                                    }
                                    else
                                    {
                                        nonBrepSlabHnds.Add(slabHnd);
                                    }
                                }
                            }

                            for (int ii = 0; ii < numReps; ii++)
                            {
                                IFCExtrusionCreationData loopExtraParam = ii < loopExtraParams.Count ? loopExtraParams[ii] : null;
                                productWrapper.AddElement(floorElement, slabHnds[ii], placementSetter, loopExtraParam, true, exportType);

                                type = ExporterUtil.CreateGenericTypeFromElement(floorElement, exportType, file, ownerHistory, exportType.ValidatedPredefinedType, productWrapper);
                                ExporterCacheManager.TypeRelationsCache.Add(type, slabHnds[ii]);

                                ExporterUtil.AddIntoComplexPropertyCache(slabHnds[ii], layersetInfo);
                            }

                            // This call to the native function appears to create Brep opening also when appropriate. But the creation of the IFC instances is not
                            //   controllable from the managed code. Therefore in some cases BRep geometry for Opening will still be exported even in the Reference View
                            if (exportedAsInternalExtrusion)
                            {
                                ISet <IFCAnyHandle> oldCreatedObjects = productWrapper.GetAllObjects();
                                ExporterIFCUtils.ExportExtrudedSlabOpenings(exporterIFC, floorElement, placementSetter.LevelInfo,
                                                                            localPlacements[0], slabHnds, extrusionLoops, floorPlane, productWrapper.ToNative());
                                ISet <IFCAnyHandle> newCreatedObjects = productWrapper.GetAllObjects();
                                newCreatedObjects.ExceptWith(oldCreatedObjects);
                                PotentiallyFixPresentationLayerAssignment(floorElement, newCreatedObjects);
                            }
                        }

                        if (!exportParts)
                        {
                            if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView)
                            {
                                HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, productWrapper.GetAnElement(),
                                                                             geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, false, type);
                            }
                            else
                            {
                                if (nonBrepSlabHnds.Count > 0)
                                {
                                    HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, nonBrepSlabHnds,
                                                                                 geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, false, type);
                                }

                                if (brepSlabHnds.Count > 0)
                                {
                                    HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, brepSlabHnds,
                                                                                 geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, true, type);
                                }
                            }
                        }
                    }

                    tr.Commit();
                    return;
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Exports a CeilingAndFloor element to IFC.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="floor">The floor element.</param>
        /// <param name="geometryElement">The geometry element.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        public static void ExportCeilingAndFloorElement(ExporterIFC exporterIFC, CeilingAndFloor floorElement, GeometryElement geometryElement,
                                                        ProductWrapper productWrapper)
        {
            if (geometryElement == null)
            {
                return;
            }

            // export parts or not
            bool exportParts = PartExporter.CanExportParts(floorElement);

            if (exportParts && !PartExporter.CanExportElementInPartExport(floorElement, floorElement.LevelId, false))
            {
                return;
            }

            IFCFile file = exporterIFC.GetFile();

            string        ifcEnumType;
            IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, floorElement, out ifcEnumType);

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                bool canExportAsContainerOrWithExtrusionAnalyzer = (!exportParts && (floorElement is Floor));

                if (canExportAsContainerOrWithExtrusionAnalyzer)
                {
                    // Try to export the Floor slab as a container.  If that succeeds, we are done.
                    // If we do export the floor as a container, it will take care of the local placement and transform there, so we need to leave
                    // this out of the IFCTransformSetter and PlacementSetter scopes below, or else we'll get double transforms.
                    IFCAnyHandle floorHnd = RoofExporter.ExportRoofOrFloorAsContainer(exporterIFC, ifcEnumType, floorElement, geometryElement, productWrapper);
                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(floorHnd))
                    {
                        tr.Commit();
                        return;
                    }
                }

                IList <IFCAnyHandle> slabHnds        = new List <IFCAnyHandle>();
                IList <IFCAnyHandle> brepSlabHnds    = new List <IFCAnyHandle>();
                IList <IFCAnyHandle> nonBrepSlabHnds = new List <IFCAnyHandle>();

                using (IFCTransformSetter transformSetter = IFCTransformSetter.Create())
                {
                    using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, floorElement))
                    {
                        IFCAnyHandle localPlacement = placementSetter.LocalPlacement;
                        IFCAnyHandle ownerHistory   = ExporterCacheManager.OwnerHistoryHandle;

                        // The routine ExportExtrudedSlabOpenings is called if exportedAsInternalExtrusion is true, and it requires having a valid level association.
                        // Disable calling ExportSlabAsExtrusion if we can't handle potential openings.
                        bool canExportAsInternalExtrusion = placementSetter.LevelInfo != null;
                        bool exportedAsInternalExtrusion  = false;

                        ElementId catId = CategoryUtil.GetSafeCategoryId(floorElement);

                        IList <IFCAnyHandle>             prodReps        = new List <IFCAnyHandle>();
                        IList <ShapeRepresentationType>  repTypes        = new List <ShapeRepresentationType>();
                        IList <IList <CurveLoop> >       extrusionLoops  = new List <IList <CurveLoop> >();
                        IList <IFCExtrusionCreationData> loopExtraParams = new List <IFCExtrusionCreationData>();
                        Plane floorPlane = GeometryUtil.CreateDefaultPlane();

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

                        if (canExportAsContainerOrWithExtrusionAnalyzer)
                        {
                            Floor floor = floorElement as Floor;

                            // Next, try to use the ExtrusionAnalyzer for the limited cases it handles - 1 solid, no openings, end clippings only.
                            // Also limited to cases with line and arc boundaries.
                            //
                            SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement);
                            IList <Solid>         solids        = solidMeshInfo.GetSolids();
                            IList <Mesh>          meshes        = solidMeshInfo.GetMeshes();

                            if (solids.Count == 1 && meshes.Count == 0)
                            {
                                bool completelyClipped;
                                // floorExtrusionDirection is set to (0, 0, -1) because extrusionAnalyzerFloorPlane is computed from the top face of the floor
                                XYZ floorExtrusionDirection = new XYZ(0, 0, -1);
                                XYZ modelOrigin             = XYZ.Zero;

                                XYZ floorOrigin = floor.GetVerticalProjectionPoint(modelOrigin, FloorFace.Top);
                                if (floorOrigin == null)
                                {
                                    // GetVerticalProjectionPoint may return null if FloorFace.Top is an edited face that doesn't
                                    // go through the Revit model origin.  We'll try the midpoint of the bounding box instead.
                                    BoundingBoxXYZ boundingBox = floorElement.get_BoundingBox(null);
                                    modelOrigin = (boundingBox.Min + boundingBox.Max) / 2.0;
                                    floorOrigin = floor.GetVerticalProjectionPoint(modelOrigin, FloorFace.Top);
                                }

                                if (floorOrigin != null)
                                {
                                    XYZ   floorDir = floor.GetNormalAtVerticalProjectionPoint(floorOrigin, FloorFace.Top);
                                    Plane extrusionAnalyzerFloorPlane = new Plane(floorDir, floorOrigin);

                                    GenerateAdditionalInfo additionalInfo     = ExporterCacheManager.ExportOptionsCache.ExportAs4 ? GenerateAdditionalInfo.GenerateFootprint : GenerateAdditionalInfo.None;
                                    HandleAndData          floorAndProperties =
                                        ExtrusionExporter.CreateExtrusionWithClippingAndProperties(exporterIFC, floorElement,
                                                                                                   catId, solids[0], extrusionAnalyzerFloorPlane, floorExtrusionDirection, null, out completelyClipped,
                                                                                                   addInfo: additionalInfo);
                                    if (completelyClipped)
                                    {
                                        return;
                                    }
                                    if (floorAndProperties.Handle != null)
                                    {
                                        IList <IFCAnyHandle> representations = new List <IFCAnyHandle>();
                                        representations.Add(floorAndProperties.Handle);

                                        // Footprint representation will only be exported in export to IFC4
                                        if (((additionalInfo & GenerateAdditionalInfo.GenerateFootprint) != 0) && (floorAndProperties.FootprintRepHandle != null))
                                        {
                                            representations.Add(floorAndProperties.FootprintRepHandle);
                                        }

                                        IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations);
                                        prodReps.Add(prodRep);
                                        repTypes.Add(ShapeRepresentationType.SweptSolid);

                                        if (floorAndProperties.Data != null)
                                        {
                                            loopExtraParams.Add(floorAndProperties.Data);
                                        }
                                    }
                                }
                            }
                        }

                        // Use internal routine as backup that handles openings.
                        if (prodReps.Count == 0 && canExportAsInternalExtrusion)
                        {
                            //IList<IFCAnyHandle> prodRepsTmp = new List<IFCAnyHandle>();
                            exportedAsInternalExtrusion = ExporterIFCUtils.ExportSlabAsExtrusion(exporterIFC, floorElement,
                                                                                                 geometryElement, transformSetter, localPlacement, out localPlacements, out prodReps,
                                                                                                 out extrusionLoops, out loopExtraParams, floorPlane);
                            for (int ii = 0; ii < prodReps.Count; ii++)
                            {
                                // all are extrusions
                                repTypes.Add(ShapeRepresentationType.SweptSolid);

                                // Footprint representation will only be exported in export to IFC4
                                if (ExporterCacheManager.ExportOptionsCache.ExportAs4)
                                {
                                    // Get back the representations, we need to add the Footprint to it
                                    //IList<IFCAnyHandle> representations = IFCAnyHandleUtil.GetRepresentations(prodRepsTmp[ii]);

                                    if (extrusionLoops.Count > ii)
                                    {
                                        if (extrusionLoops[ii].Count > 0)
                                        {
                                            // Get the extrusion footprint using the first Curveloop. Transform needs to be obtained from the returned local placement
                                            Transform    lcs   = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, localPlacements[ii]);
                                            Plane        plane = new Plane(lcs.BasisX, lcs.BasisY, lcs.Origin);
                                            IFCAnyHandle footprintGeomRepItem = GeometryUtil.CreateIFCCurveFromCurveLoop(exporterIFC, extrusionLoops[ii][0], plane, floorPlane.Normal);

                                            IFCAnyHandle        contextOfItemsFootprint = exporterIFC.Get3DContextHandle("FootPrint");
                                            ISet <IFCAnyHandle> repItem = new HashSet <IFCAnyHandle>();
                                            repItem.Add(footprintGeomRepItem);
                                            IFCAnyHandle footprintShapeRepresentation = RepresentationUtil.CreateBaseShapeRepresentation(exporterIFC, contextOfItemsFootprint, "FootPrint", "Curve2D", repItem);
                                            //representations.Add(footprintShapeRepresentation);
                                            IList <IFCAnyHandle> reps = new List <IFCAnyHandle>();
                                            reps.Add(footprintShapeRepresentation);
                                            IFCAnyHandleUtil.AddRepresentations(prodReps[ii], reps);
                                        }
                                    }
                                    //IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations);
                                    //prodReps.Add(prodRep);
                                }
                                else
                                {
                                    //prodReps.Add(prodRepsTmp[ii]);
                                }

                                // We do not need the prodRepsTmp anymore, delete the handle:
                                //prodRepsTmp[ii].Delete();
                            }
                        }

                        if (prodReps.Count == 0)
                        {
                            using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData())
                            {
                                // Brep representation using tesellation after ExportSlabAsExtrusion does not return prodReps
                                BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.Medium);
                                BodyData            bodyData;
                                IFCAnyHandle        prodDefHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC,
                                                                                                                            floorElement, catId, geometryElement, bodyExporterOptions, null, ecData, out bodyData);
                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodDefHnd))
                                {
                                    ecData.ClearOpenings();
                                    return;
                                }

                                prodReps.Add(prodDefHnd);
                                repTypes.Add(bodyData.ShapeRepresentationType);
                            }
                        }

                        // Create the slab from either the extrusion or the BRep information.
                        string ifcGUID = GUIDUtil.CreateGUID(floorElement);

                        int numReps = exportParts ? 1 : prodReps.Count;

                        string entityType = null;

                        switch (exportType)
                        {
                        case IFCExportType.IfcFooting:
                            if (ExporterCacheManager.ExportOptionsCache.ExportAs4)
                            {
                                entityType = IFCValidateEntry.GetValidIFCType <Revit.IFC.Export.Toolkit.IFC4.IFCFootingType>(floorElement, ifcEnumType, null);
                            }
                            else
                            {
                                entityType = IFCValidateEntry.GetValidIFCType <IFCFootingType>(floorElement, ifcEnumType, null);
                            }
                            break;

                        case IFCExportType.IfcCovering:
                            entityType = IFCValidateEntry.GetValidIFCType <IFCCoveringType>(floorElement, ifcEnumType, "FLOORING");
                            break;

                        case IFCExportType.IfcRamp:
                            if (ExporterCacheManager.ExportOptionsCache.ExportAs4)
                            {
                                entityType = IFCValidateEntry.GetValidIFCType <Revit.IFC.Export.Toolkit.IFC4.IFCRampType>(floorElement, ifcEnumType, null);
                            }
                            else
                            {
                                entityType = IFCValidateEntry.GetValidIFCType <IFCRampType>(floorElement, ifcEnumType, null);
                            }
                            break;

                        default:
                            bool            isBaseSlab      = false;
                            AnalyticalModel analyticalModel = floorElement.GetAnalyticalModel();
                            if (analyticalModel != null)
                            {
                                AnalyzeAs slabFoundationType = analyticalModel.GetAnalyzeAs();
                                isBaseSlab = (slabFoundationType == AnalyzeAs.SlabOnGrade) || (slabFoundationType == AnalyzeAs.Mat);
                            }
                            entityType = IFCValidateEntry.GetValidIFCType <IFCSlabType>(floorElement, ifcEnumType, isBaseSlab ? "BASESLAB" : "FLOOR");
                            break;
                        }

                        for (int ii = 0; ii < numReps; ii++)
                        {
                            string ifcName        = NamingUtil.GetNameOverride(floorElement, NamingUtil.GetIFCNamePlusIndex(floorElement, ii == 0 ? -1 : ii + 1));
                            string ifcDescription = NamingUtil.GetDescriptionOverride(floorElement, null);
                            string ifcObjectType  = NamingUtil.GetObjectTypeOverride(floorElement, exporterIFC.GetFamilyName());
                            string ifcTag         = NamingUtil.GetTagOverride(floorElement, NamingUtil.CreateIFCElementId(floorElement));

                            string       currentGUID       = (ii == 0) ? ifcGUID : GUIDUtil.CreateGUID();
                            IFCAnyHandle localPlacementHnd = exportedAsInternalExtrusion ? localPlacements[ii] : localPlacement;

                            IFCAnyHandle slabHnd = null;

                            // TODO: replace with CreateGenericBuildingElement.
                            switch (exportType)
                            {
                            case IFCExportType.IfcFooting:
                                slabHnd = IFCInstanceExporter.CreateFooting(file, currentGUID, ownerHistory, ifcName,
                                                                            ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii],
                                                                            ifcTag, entityType);
                                break;

                            case IFCExportType.IfcCovering:
                                slabHnd = IFCInstanceExporter.CreateCovering(file, currentGUID, ownerHistory, ifcName,
                                                                             ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii],
                                                                             ifcTag, entityType);
                                break;

                            case IFCExportType.IfcRamp:
                                slabHnd = IFCInstanceExporter.CreateRamp(file, currentGUID, ownerHistory, ifcName,
                                                                         ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii],
                                                                         ifcTag, entityType);
                                break;

                            default:
                                //if ((canExportAsInternalExtrusion || exportedAsInternalExtrusion) && ExporterCacheManager.ExportOptionsCache.ExportAs4)
                                //{
                                //    slabHnd = IFCInstanceExporter.CreateSlabStandardCase(file, currentGUID, ownerHistory, ifcName,
                                //        ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii],
                                //        ifcTag, entityType);
                                //}
                                //else
                                slabHnd = IFCInstanceExporter.CreateSlab(file, currentGUID, ownerHistory, ifcName,
                                                                         ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii],
                                                                         ifcTag, entityType);
                                break;
                            }

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

                            if (exportParts)
                            {
                                PartExporter.ExportHostPart(exporterIFC, floorElement, slabHnd, productWrapper, placementSetter, localPlacementHnd, null);
                            }

                            slabHnds.Add(slabHnd);

                            if (!exportParts)
                            {
                                if (repTypes[ii] == ShapeRepresentationType.Brep)
                                {
                                    brepSlabHnds.Add(slabHnd);
                                }
                                else
                                {
                                    nonBrepSlabHnds.Add(slabHnd);
                                }
                            }
                        }

                        for (int ii = 0; ii < numReps; ii++)
                        {
                            IFCExtrusionCreationData loopExtraParam = ii < loopExtraParams.Count ? loopExtraParams[ii] : null;
                            productWrapper.AddElement(floorElement, slabHnds[ii], placementSetter, loopExtraParam, true);
                        }

                        // This call to the native function appears to create Brep opening also when appropriate. But the creation of the IFC instances is not
                        //   controllable from the managed code. Therefore in some cases BRep geometry for Opening will still be exported even in the Reference View
                        if (exportedAsInternalExtrusion)
                        {
                            ExporterIFCUtils.ExportExtrudedSlabOpenings(exporterIFC, floorElement, placementSetter.LevelInfo,
                                                                        localPlacements[0], slabHnds, extrusionLoops, floorPlane, productWrapper.ToNative());
                        }
                        //// For now we have to be content without IfcOpeningStandardCase from the openings created by this native call because it is too much to
                        ////    "reverse engineer" the IFChandle
                        //foreach (IFCAnyHandle slabHandle in slabHnds)
                        //{
                        //    updateOpeningProfileRep(exporterIFC, slabHandle);
                        //}
                    }

                    if (!exportParts)
                    {
                        if (nonBrepSlabHnds.Count > 0)
                        {
                            HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, nonBrepSlabHnds,
                                                                         geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, false);
                        }
                        if (brepSlabHnds.Count > 0)
                        {
                            HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, brepSlabHnds,
                                                                         geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, true);
                        }
                    }
                }
                tr.Commit();

                return;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Exports a ramp to IfcRamp, without decomposing into separate runs and landings.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="ifcEnumType">The ramp type.</param>
        /// <param name="ramp">The ramp element.</param>
        /// <param name="geometryElement">The geometry element.</param>
        /// <param name="numFlights">The number of flights for a multistory ramp.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        public static void ExportRamp(ExporterIFC exporterIFC, string ifcEnumType, Element ramp, GeometryElement geometryElement,
                                      int numFlights, ProductWrapper productWrapper)
        {
            if (ramp == null || geometryElement == null)
            {
                return;
            }

            // Check the intended IFC entity or type name is in the exclude list specified in the UI
            Common.Enums.IFCEntityType elementClassTypeEnum = Common.Enums.IFCEntityType.IfcRamp;
            if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum))
            {
                return;
            }

            // TESTING
            foreach (GeometryObject geomObj in geometryElement)
            {
                Visibility visibility = geomObj.Visibility;
            }

            IFCFile   file       = exporterIFC.GetFile();
            ElementId categoryId = CategoryUtil.GetSafeCategoryId(ramp);

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, ramp))
                {
                    IFCAnyHandle contextOfItemsFootPrint = exporterIFC.Get3DContextHandle("FootPrint");
                    IFCAnyHandle contextOfItemsAxis      = exporterIFC.Get3DContextHandle("Axis");

                    Transform    trf          = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, placementSetter.LocalPlacement);
                    IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle;

                    IList <(Solid body, Face largestTopFace)> rampFlights = null;
                    IList <Solid> landings = null;
                    if (IdentifyRampFlightAndLanding(geometryElement, out rampFlights, out landings))
                    {
                        string       rampGUID           = GUIDUtil.CreateGUID(ramp);
                        IFCAnyHandle rampLocalPlacement = placementSetter.LocalPlacement;
                        string       predefType         = "NOTDEFINED"; //Temporary
                        IFCAnyHandle rampContainerHnd   = IFCInstanceExporter.CreateRamp(exporterIFC, ramp, rampGUID, ownerHistory, rampLocalPlacement, null, predefType);
                        // Create appropriate type
                        IFCExportInfoPair exportType = new IFCExportInfoPair();
                        exportType.SetValueWithPair(IFCEntityType.IfcRamp);
                        IFCAnyHandle rampTypeHnd = ExporterUtil.CreateGenericTypeFromElement(ramp, exportType, exporterIFC.GetFile(), ownerHistory, predefType, productWrapper);
                        ExporterCacheManager.TypeRelationsCache.Add(rampTypeHnd, rampContainerHnd);
                        productWrapper.AddElement(ramp, rampContainerHnd, placementSetter.LevelInfo, null, true);

                        //Breakdown the Ramp into its components: RampFlights and Landings
                        int rampFlightIndex = 0;
                        int landingIndex    = 0;
                        HashSet <IFCAnyHandle> rampComponents = new HashSet <IFCAnyHandle>();
                        foreach ((Solid body, Face topFace)rampFlight in rampFlights)
                        {
                            using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData())
                            {
                                ecData.AllowVerticalOffsetOfBReps = false;
                                ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, placementSetter.LocalPlacement, null));
                                ecData.ReuseLocalPlacement = true;
                                BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow);
                                BodyData            bodyData            = BodyExporter.ExportBody(exporterIFC, ramp, categoryId, ElementId.InvalidElementId, rampFlight.body, bodyExporterOptions, ecData);

                                IFCAnyHandle bodyRep = bodyData.RepresentationHnd;
                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep))
                                {
                                    ecData.ClearOpenings();
                                    continue;
                                }
                                IList <IFCAnyHandle> reps = new List <IFCAnyHandle>();
                                reps.Add(bodyRep);

                                //if (!ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2)
                                //{
                                //   CreateWalkingLineAndFootprint(exporterIFC, run, bodyData, categoryId, trf, ref reps);
                                //}

                                Transform boundingBoxTrf         = (bodyData.OffsetTransform == null) ? Transform.Identity : bodyData.OffsetTransform.Inverse;
                                IList <GeometryObject> solidList = new List <GeometryObject>();
                                solidList.Add(rampFlight.body);
                                IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solidList, boundingBoxTrf);
                                if (boundingBoxRep != null)
                                {
                                    reps.Add(boundingBoxRep);
                                }

                                IFCAnyHandle representation = IFCInstanceExporter.CreateProductDefinitionShape(exporterIFC.GetFile(), null, null, reps);

                                rampFlightIndex++;
                                string flightGUID     = GUIDUtil.CreateSubElementGUID(ramp, rampFlightIndex);
                                string origFlightName = IFCAnyHandleUtil.GetStringAttribute(rampContainerHnd, "Name") + " " + rampFlightIndex;
                                string flightName     = NamingUtil.GetOverrideStringValue(ramp, "IfcRampFlight.Name (" + rampFlightIndex + ")", origFlightName);

                                IFCAnyHandle flightLocalPlacement = ecData.GetLocalPlacement();
                                string       flightPredefType     = NamingUtil.GetOverrideStringValue(ramp, "IfcRampFlight.PredefinedType (" + rampFlightIndex + ")", null);

                                IFCAnyHandle rampFlightHnd = IFCInstanceExporter.CreateRampFlight(exporterIFC, null, flightGUID, ownerHistory, flightLocalPlacement,
                                                                                                  representation, flightPredefType);
                                IFCAnyHandleUtil.OverrideNameAttribute(rampFlightHnd, flightName);
                                rampComponents.Add(rampFlightHnd);

                                // Create type
                                IFCExportInfoPair flightEportType = new IFCExportInfoPair();
                                flightEportType.SetValueWithPair(IFCEntityType.IfcRampFlight);
                                IFCAnyHandle flightTypeHnd = IFCInstanceExporter.CreateGenericIFCType(flightEportType, null, exporterIFC.GetFile(), null, null, flightPredefType);
                                IFCAnyHandleUtil.OverrideNameAttribute(flightTypeHnd, flightName);
                                ExporterCacheManager.TypeRelationsCache.Add(flightTypeHnd, rampFlightHnd);

                                CategoryUtil.CreateMaterialAssociation(exporterIFC, rampFlightHnd, bodyData.MaterialIds);

                                IFCAnyHandle psetRampFlightCommonHnd = CreatePSetRampFlightCommon(exporterIFC, file, ramp, rampFlightIndex, rampFlight.topFace);

                                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(psetRampFlightCommonHnd))
                                {
                                    HashSet <IFCAnyHandle> relatedObjects = new HashSet <IFCAnyHandle>()
                                    {
                                        rampFlightHnd
                                    };
                                    ExporterUtil.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, relatedObjects, psetRampFlightCommonHnd);
                                }
                            }
                        }
                        foreach (Solid landing in landings)
                        {
                            using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData())
                            {
                                ecData.AllowVerticalOffsetOfBReps = false;
                                ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, placementSetter.LocalPlacement, null));
                                ecData.ReuseLocalPlacement = true;
                                BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow);
                                BodyData            bodyData            = BodyExporter.ExportBody(exporterIFC, ramp, categoryId, ElementId.InvalidElementId, landing, bodyExporterOptions, ecData);

                                IFCAnyHandle bodyRep = bodyData.RepresentationHnd;
                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep))
                                {
                                    ecData.ClearOpenings();
                                    continue;
                                }
                                IList <IFCAnyHandle> reps = new List <IFCAnyHandle>();
                                reps.Add(bodyRep);

                                //if (!ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2)
                                //{
                                //   CreateWalkingLineAndFootprint(exporterIFC, run, bodyData, categoryId, trf, ref reps);
                                //}

                                Transform boundingBoxTrf         = (bodyData.OffsetTransform == null) ? Transform.Identity : bodyData.OffsetTransform.Inverse;
                                IList <GeometryObject> solidList = new List <GeometryObject>();
                                solidList.Add(landing);
                                IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solidList, boundingBoxTrf);
                                if (boundingBoxRep != null)
                                {
                                    reps.Add(boundingBoxRep);
                                }

                                IFCAnyHandle representation = IFCInstanceExporter.CreateProductDefinitionShape(exporterIFC.GetFile(), null, null, reps);

                                landingIndex++;
                                string landingGUID     = GUIDUtil.CreateSubElementGUID(ramp, landingIndex);
                                string origLandingName = IFCAnyHandleUtil.GetStringAttribute(rampContainerHnd, "Name") + " " + landingIndex;
                                string landingName     = NamingUtil.GetOverrideStringValue(ramp, "IfcRampLanding.Name (" + landingIndex + ")", origLandingName);

                                IFCAnyHandle landingLocalPlacement = ecData.GetLocalPlacement();
                                string       landingPredefType     = "LANDING";

                                IFCAnyHandle rampLandingHnd = IFCInstanceExporter.CreateSlab(exporterIFC, ramp, landingGUID, ownerHistory, landingLocalPlacement,
                                                                                             representation, landingPredefType);
                                IFCAnyHandleUtil.OverrideNameAttribute(rampLandingHnd, landingName);
                                rampComponents.Add(rampLandingHnd);

                                // Create type
                                IFCExportInfoPair landingEportType = new IFCExportInfoPair();
                                landingEportType.SetValueWithPair(IFCEntityType.IfcSlab);
                                IFCAnyHandle landingTypeHnd = IFCInstanceExporter.CreateGenericIFCType(landingEportType, null, exporterIFC.GetFile(), null, null, landingPredefType);
                                IFCAnyHandleUtil.OverrideNameAttribute(landingTypeHnd, landingName);
                                ExporterCacheManager.TypeRelationsCache.Add(landingTypeHnd, rampLandingHnd);

                                CategoryUtil.CreateMaterialAssociation(exporterIFC, rampLandingHnd, bodyData.MaterialIds);

                                IFCAnyHandle psetSlabCommonHnd = CreatePSetRampLandingCommon(exporterIFC, file, ramp, landingIndex);

                                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(psetSlabCommonHnd))
                                {
                                    HashSet <IFCAnyHandle> relatedObjects = new HashSet <IFCAnyHandle>()
                                    {
                                        rampLandingHnd
                                    };
                                    ExporterUtil.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, relatedObjects, psetSlabCommonHnd);
                                }
                            }
                        }

                        if (rampComponents.Count > 0)
                        {
                            IFCInstanceExporter.CreateRelAggregates(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, rampContainerHnd, rampComponents);
                        }
                    }
                    else
                    {
                        using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData())
                        {
                            ecData.SetLocalPlacement(placementSetter.LocalPlacement);
                            ecData.ReuseLocalPlacement = false;

                            GeometryElement rampGeom = GeometryUtil.GetOneLevelGeometryElement(geometryElement, numFlights);

                            BodyData bodyData;

                            BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow);
                            IFCAnyHandle        representation      = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC,
                                                                                                                                 ramp, categoryId, rampGeom, bodyExporterOptions, null, ecData, out bodyData);

                            if (IFCAnyHandleUtil.IsNullOrHasNoValue(representation))
                            {
                                ecData.ClearOpenings();
                                return;
                            }

                            string       containedRampGuid           = GUIDUtil.CreateSubElementGUID(ramp, (int)IFCRampSubElements.ContainedRamp);
                            IFCAnyHandle containedRampLocalPlacement = ExporterUtil.CreateLocalPlacement(file, ecData.GetLocalPlacement(), null);
                            string       rampType = GetIFCRampType(ifcEnumType);

                            List <IFCAnyHandle> components = new List <IFCAnyHandle>();
                            IList <IFCExtrusionCreationData> componentExtrusionData = new List <IFCExtrusionCreationData>();
                            IFCAnyHandle containedRampHnd = IFCInstanceExporter.CreateRamp(exporterIFC, ramp, containedRampGuid, ownerHistory,
                                                                                           containedRampLocalPlacement, representation, rampType);
                            components.Add(containedRampHnd);
                            componentExtrusionData.Add(ecData);
                            //productWrapper.AddElement(containedRampHnd, placementSetter.LevelInfo, ecData, false);
                            CategoryUtil.CreateMaterialAssociation(exporterIFC, containedRampHnd, bodyData.MaterialIds);

                            string       guid           = GUIDUtil.CreateGUID(ramp);
                            IFCAnyHandle localPlacement = ecData.GetLocalPlacement();

                            IFCAnyHandle rampHnd = IFCInstanceExporter.CreateRamp(exporterIFC, ramp, guid, ownerHistory,
                                                                                  localPlacement, null, rampType);

                            productWrapper.AddElement(ramp, rampHnd, placementSetter.LevelInfo, ecData, true);

                            StairRampContainerInfo stairRampInfo = new StairRampContainerInfo(rampHnd, components, localPlacement);
                            ExporterCacheManager.StairRampContainerInfoCache.AddStairRampContainerInfo(ramp.Id, stairRampInfo);

                            ExportMultistoryRamp(exporterIFC, ramp, numFlights, rampHnd, components, componentExtrusionData, placementSetter,
                                                 productWrapper);
                        }
                    }
                }
                tr.Commit();
            }
        }
        private static bool ExportGenericElementAsMappedItem(ExporterIFC exporterIFC,
                                                             Element element, GeometryElement geomElem, IFCExportInfoPair exportType,
                                                             ProductWrapper wrapper)
        {
            GeometryInstance geometryInstance = GetTheGeometryInstance(geomElem);

            if (geometryInstance == null)
            {
                return(false);
            }

            GeometryElement exportGeometry = geometryInstance.GetSymbolGeometry();

            if (exportGeometry == null)
            {
                return(false);
            }

            ElementId   symbolId    = geometryInstance.GetSymbolGeometryId()?.SymbolId ?? ElementId.InvalidElementId;
            ElementType elementType = element.Document.GetElement(symbolId) as ElementType;

            if (elementType == null)
            {
                return(false);
            }

            Transform originalTrf = geometryInstance.Transform;

            // Can't handle mirrored transforms yet.
            if (originalTrf.HasReflection)
            {
                return(false);
            }

            ElementId categoryId = CategoryUtil.GetSafeCategoryId(element);

            IFCFile file = exporterIFC.GetFile();

            IList <Transform>        repMapTrfList = new List <Transform>();
            BodyData                 bodyData      = null;
            FamilyTypeInfo           typeInfo      = new FamilyTypeInfo();
            IFCExtrusionCreationData extraParams   = typeInfo.extraParams;

            Transform offsetTransform = Transform.Identity;

            // We will create a new mapped type if we haven't already created the type.
            FamilyTypeInfo currentTypeInfo = ExporterCacheManager.FamilySymbolToTypeInfoCache.Find(symbolId, false, exportType);
            bool           found           = currentTypeInfo.IsValid();

            if (!found)
            {
                IList <IFCAnyHandle> representations3D = new List <IFCAnyHandle>();

                IFCAnyHandle dummyPlacement = ExporterUtil.CreateLocalPlacement(file, null, null);
                extraParams.SetLocalPlacement(dummyPlacement);

                using (TransformSetter trfSetter = TransformSetter.Create())
                {
                    BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(false, ExportOptionsCache.ExportTessellationLevel.ExtraLow);

                    bodyData = BodyExporter.ExportBody(exporterIFC, element, categoryId,
                                                       ExporterUtil.GetSingleMaterial(element), exportGeometry,
                                                       bodyExporterOptions, extraParams);
                    typeInfo.MaterialIdList = bodyData.MaterialIds;
                    offsetTransform         = bodyData.OffsetTransform;

                    // This code does not handle openings yet.
                    // The intention for this is FabricationParts and DirectShapes which do not
                    // currently have opening.
                    // If they can have openings in the future, we can add this.
                    IFCAnyHandle bodyRepHnd = bodyData.RepresentationHnd;
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd) || extraParams.GetOpenings().Count > 0)
                    {
                        return(false);
                    }

                    representations3D.Add(bodyRepHnd);
                    repMapTrfList.Add(null);
                }

                typeInfo.StyleTransform = ExporterIFCUtils.GetUnscaledTransform(exporterIFC,
                                                                                extraParams.GetLocalPlacement());

                IFCAnyHandle typeStyle = FamilyInstanceExporter.CreateTypeEntityHandle(exporterIFC,
                                                                                       ref typeInfo, null, representations3D, repMapTrfList, null,
                                                                                       element, elementType, elementType, false, false,
                                                                                       exportType, out HashSet <IFCAnyHandle> propertySets);

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

                    typeInfo.Style = typeStyle;

                    CategoryUtil.TryToCreateMaterialAssocation(exporterIFC, bodyData, elementType,
                                                               element, exportGeometry, typeStyle, typeInfo);

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

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

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

            extraParams = typeInfo.extraParams;

            // We expect no openings, so always add to map.
            ExporterCacheManager.FamilySymbolToTypeInfoCache.Register(symbolId, false, exportType, typeInfo);

            XYZ       scaledMapOrigin = XYZ.Zero;
            Transform scaledTrf       = originalTrf.Multiply(typeInfo.StyleTransform);

            // create instance.
            IList <IFCAnyHandle> shapeReps = FamilyInstanceExporter.CreateShapeRepresentations(exporterIFC,
                                                                                               file, element, categoryId, typeInfo, scaledMapOrigin);

            if (shapeReps == null)
            {
                return(false);
            }

            Transform boundingBoxTrf = (offsetTransform != null) ? offsetTransform.Inverse : Transform.Identity;

            boundingBoxTrf = boundingBoxTrf.Multiply(scaledTrf.Inverse);
            IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomElem, boundingBoxTrf);

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

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

            using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, scaledTrf, null))
            {
                IFCAnyHandle instanceHandle            = null;
                IFCAnyHandle localPlacement            = setter.LocalPlacement;
                bool         materialAlreadyAssociated = false;

                // We won't create the instance if:
                // (1) we are exporting to CV2.0/RV, (2) we have no 2D, 3D, or bounding box geometry, and (3) we aren't exporting parts.
                if (!(repHnd == null &&
                      (ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2 ||
                       ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView)))
                {
                    string instanceGUID = GUIDUtil.CreateGUID(element);

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

                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle))
                    {
                        bool isBuildingElementProxy =
                            ((exportType.ExportInstance == IFCEntityType.IfcBuildingElementProxy) ||
                             (exportType.ExportType == IFCEntityType.IfcBuildingElementProxyType));

                        ElementId roomId = setter.UpdateRoomRelativeCoordinates(element,
                                                                                out IFCAnyHandle localPlacementToUse);
                        bool         containedInSpace = (roomId != ElementId.InvalidElementId) && (exportType.ExportInstance != IFCEntityType.IfcSystemFurnitureElement);
                        IFCAnyHandle ownerHistory     = ExporterCacheManager.OwnerHistoryHandle;

                        if (!isBuildingElementProxy)
                        {
                            instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportType, exporterIFC, element, instanceGUID,
                                                                                        ownerHistory, localPlacementToUse, repHnd);
                        }
                        else
                        {
                            instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(exporterIFC, element, instanceGUID,
                                                                                            ownerHistory, localPlacementToUse, repHnd, exportType.ValidatedPredefinedType);
                        }

                        bool associateToLevel = !containedInSpace && !isChildInContainer;
                        wrapper.AddElement(element, instanceHandle, setter, extraParams, associateToLevel, exportType);
                        if (containedInSpace)
                        {
                            ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle);
                        }
                    }

                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle))
                    {
                        if (ElementFilteringUtil.IsMEPType(exportType) || ElementFilteringUtil.ProxyForMEPType(element, exportType))
                        {
                            ExporterCacheManager.MEPCache.Register(element, instanceHandle);
                        }

                        ExporterCacheManager.HandleToElementCache.Register(instanceHandle, element.Id);

                        if (!materialAlreadyAssociated)
                        {
                            // Create material association for the instance only if the the istance geometry is different from the type
                            // or the type does not have any material association
                            IFCAnyHandle constituentSetHnd = ExporterCacheManager.MaterialSetCache.FindConstituentSetHnd(symbolId);
                            if (IFCAnyHandleUtil.IsNullOrHasNoValue(constituentSetHnd) &&
                                bodyData != null && bodyData.RepresentationItemInfo != null && bodyData.RepresentationItemInfo.Count > 0)
                            {
                                CategoryUtil.CreateMaterialAssociationWithShapeAspect(exporterIFC, element, instanceHandle, bodyData.RepresentationItemInfo);
                            }
                            else
                            {
                                // Create material association in case if bodyData is null
                                CategoryUtil.CreateMaterialAssociation(exporterIFC, instanceHandle, typeInfo.MaterialIdList);
                            }
                        }

                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style))
                        {
                            ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle);
                        }
                    }
                }
            }
            return(true);
        }