コード例 #1
0
ファイル: BeamExporter.cs プロジェクト: tornadory/revit-ifc
        /// <summary>
        /// Exports a beam to IFC beam if it has an axis representation and only one Solid as its geometry, ideally as an extrusion, potentially with clippings and openings.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="element">The element to be exported.</param>
        /// <param name="geometryElement">The geometry element.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        /// <param name="dontExport">An output value that says that the element shouldn't be exported at all.</param>
        /// <returns>The created handle.</returns>
        /// <remarks>In the original implementation, the ExportBeam function would export each beam as its own individual geometry (that is, not use representation maps).
        /// For non-standard beams, this could result in massive IFC files.  Now, we use the ExportBeamAsStandardElement function and limit its scope, and instead
        /// resort to the standard FamilyInstanceExporter.ExportFamilyInstanceAsMappedItem for more complicated objects categorized as beams.  This has the following pros and cons:
        /// Pro: possiblity for massively reduced file sizes for files containing repeated complex beam families
        /// Con: some beams that may have had an "Axis" representation before will no longer have them, although this possibility is minimized.
        /// Con: some beams that have 1 Solid and an axis, but that Solid will be heavily faceted, won't be helped by this improvement.
        /// It is intended that we phase out this routine entirely and instead teach ExportFamilyInstanceAsMappedItem how to sometimes export the Axis representation for beams.</remarks>
        public static IFCAnyHandle ExportBeamAsStandardElement(ExporterIFC exporterIFC,
                                                               Element element, GeometryElement geometryElement, ProductWrapper productWrapper, out bool dontExport)
        {
            dontExport = true;
            IList <GeometryObject> geomObjects = BeamGeometryToExport(exporterIFC, element, geometryElement, out dontExport);

            if (dontExport)
            {
                return(null);
            }

            IFCAnyHandle       beam = null;
            IFCFile            file = exporterIFC.GetFile();
            MaterialAndProfile materialAndProfile = null;
            IFCAnyHandle       materialProfileSet = null;

            using (IFCTransaction transaction = new IFCTransaction(file))
            {
                BeamAxisInfo axisInfo      = GetBeamAxisTransform(element);
                bool         canExportAxis = (axisInfo != null);

                Curve     curve         = canExportAxis ? axisInfo.Axis : null;
                XYZ       beamDirection = canExportAxis ? axisInfo.AxisDirection : null;
                Transform orientTrf     = canExportAxis ? axisInfo.LCSAsTransform : null;

                using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, orientTrf))
                {
                    IFCAnyHandle localPlacement = setter.LocalPlacement;
                    using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData())
                    {
                        extrusionCreationData.SetLocalPlacement(localPlacement);
                        if (canExportAxis && (orientTrf.BasisX != null))
                        {
                            extrusionCreationData.CustomAxis            = beamDirection;
                            extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom;
                        }
                        else
                        {
                            extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryXY;
                        }

                        ElementId catId = CategoryUtil.GetSafeCategoryId(element);

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

                        // The list of materials in the solids or meshes.
                        ICollection <ElementId> materialIds = null;

                        // If the beam is a FamilyInstance, and it uses transformed FamilySymbol geometry only, then
                        // let's only try to CreateBeamGeometryAsExtrusion unsuccesfully once.  Otherwise, we can spend a lot of time trying
                        // unsuccessfully to do so.
                        bool tryToCreateBeamGeometryAsExtrusion = true;

                        bool      useFamilySymbolGeometry = (element is FamilyInstance) ? !ExporterIFCUtils.UsesInstanceGeometry(element as FamilyInstance) : false;
                        ElementId beamTypeId = element.GetTypeId();
                        if (useFamilySymbolGeometry)
                        {
                            tryToCreateBeamGeometryAsExtrusion = !ExporterCacheManager.CanExportBeamGeometryAsExtrusionCache.ContainsKey(beamTypeId) ||
                                                                 ExporterCacheManager.CanExportBeamGeometryAsExtrusionCache[beamTypeId];
                        }

                        // The representation handle generated from one of the methods below.
                        BeamBodyAsExtrusionInfo extrusionInfo = null;
                        if (tryToCreateBeamGeometryAsExtrusion)
                        {
                            extrusionInfo = CreateBeamGeometryAsExtrusion(exporterIFC, element, catId, geomObjects, axisInfo);
                            if (useFamilySymbolGeometry)
                            {
                                ExporterCacheManager.CanExportBeamGeometryAsExtrusionCache[beamTypeId] = (extrusionInfo != null);
                            }
                        }

                        if (extrusionInfo != null && extrusionInfo.DontExport)
                        {
                            dontExport = true;
                            return(null);
                        }

                        IFCAnyHandle repHnd = (extrusionInfo != null) ? extrusionInfo.RepresentationHandle : null;

                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd))
                        {
                            materialIds = extrusionInfo.Materials;
                            extrusionCreationData.Slope = extrusionInfo.Slope;
                        }
                        else
                        {
                            // Here is where we limit the scope of how complex a case we will still try to export as a standard element.
                            // This is explicitly added so that many curved beams that can be represented by a reasonable facetation because of the
                            // SweptSolidExporter can still have an Axis representation.
                            BodyData bodyData = null;

                            BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow);
                            bodyExporterOptions.CollectMaterialAndProfile = true;

                            if (geomObjects != null && geomObjects.Count == 1 && geomObjects[0] is Solid)
                            {
                                bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId,
                                                                   geomObjects[0], bodyExporterOptions, extrusionCreationData);

                                repHnd      = bodyData.RepresentationHnd;
                                materialIds = bodyData.MaterialIds;
                                if (!bodyData.OffsetTransform.IsIdentity)
                                {
                                    offsetTransform = bodyData.OffsetTransform;
                                }
                                materialAndProfile = bodyData.materialAndProfile;
                            }
                        }

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

                        IList <IFCAnyHandle> representations = new List <IFCAnyHandle>();
                        IFCAnyHandle         axisRep         = CreateBeamAxis(exporterIFC, element, catId, axisInfo, offsetTransform);
                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(axisRep))
                        {
                            representations.Add(axisRep);
                        }
                        representations.Add(repHnd);

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

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

                        string instanceGUID   = GUIDUtil.CreateGUID(element);
                        string preDefinedType = "BEAM"; // Default predefined type for Beam
                        //preDefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, preDefinedType);

                        beam = IFCInstanceExporter.CreateBeam(exporterIFC, element, instanceGUID, ExporterCacheManager.OwnerHistoryHandle, extrusionCreationData.GetLocalPlacement(), prodRep, preDefinedType);

                        IFCAnyHandle mpSetUsage;
                        if (materialProfileSet != null)
                        {
                            mpSetUsage = IFCInstanceExporter.CreateMaterialProfileSetUsage(file, materialProfileSet, null, null);
                        }

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

                        ExportBeamType(exporterIFC, productWrapper, beam, element, preDefinedType);

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

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

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

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

                transaction.Commit();
                return(beam);
            }
        }