/// <summary> /// Exports a generic family instance as IFC instance. /// </summary> /// <param name="type">The export type.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="familyInstance">The element.</param> /// <param name="wrapper">The ProductWrapper.</param> /// <param name="setter">The PlacementSetter.</param> /// <param name="extraParams">The extrusion creation data.</param> /// <param name="instanceGUID">The guid.</param> /// <param name="ownerHistory">The owner history handle.</param> /// <param name="instanceName">The name.</param> /// <param name="instanceDescription">The description.</param> /// <param name="instanceObjectType">The object type.</param> /// <param name="productRepresentation">The representation handle.</param> /// <param name="instanceTag">The tag for the entity, usually based on the element id.</param> /// <param name="ifcEnumType">The predefined type/shape type, if any, for the object.</param> /// <param name="overrideLocalPlacement">The local placement to use instead of the one in the placement setter, if appropriate.</param> /// <returns>The handle.</returns> public static IFCAnyHandle ExportGenericInstance(IFCExportInfoPair type, ExporterIFC exporterIFC, Element familyInstance, ProductWrapper wrapper, PlacementSetter setter, IFCExtrusionCreationData extraParams, string instanceGUID, IFCAnyHandle ownerHistory, IFCAnyHandle productRepresentation, string ifcEnumType, IFCAnyHandle overrideLocalPlacement) { IFCFile file = exporterIFC.GetFile(); Document doc = familyInstance.Document; bool isRoomRelated = IsRoomRelated(type); bool isChildInContainer = familyInstance.AssemblyInstanceId != ElementId.InvalidElementId; IFCAnyHandle localPlacementToUse = setter.LocalPlacement; ElementId roomId = ElementId.InvalidElementId; if (isRoomRelated) { roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); } //should remove the create method where there is no use of this handle for API methods //some places uses the return value of ExportGenericInstance as input parameter for API methods IFCAnyHandle instanceHandle = null; switch (type.ExportInstance) { case IFCEntityType.IfcBeam: { string preDefinedType = string.IsNullOrWhiteSpace(type.ValidatedPredefinedType) ? "BEAM" : type.ValidatedPredefinedType; instanceHandle = IFCInstanceExporter.CreateBeam(exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation, preDefinedType); break; } case IFCEntityType.IfcColumn: { string preDefinedType = string.IsNullOrWhiteSpace(type.ValidatedPredefinedType) ? "COLUMN" : type.ValidatedPredefinedType; instanceHandle = IFCInstanceExporter.CreateColumn(exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation, preDefinedType); break; } case IFCEntityType.IfcCurtainWall: { instanceHandle = IFCInstanceExporter.CreateCurtainWall(exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation, type.ValidatedPredefinedType); break; } case IFCEntityType.IfcMember: { string preDefinedType = string.IsNullOrWhiteSpace(type.ValidatedPredefinedType) ? "BRACE" : type.ValidatedPredefinedType; instanceHandle = IFCInstanceExporter.CreateMember(exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation, preDefinedType); // Register the members's IFC handle for later use by truss export. ExporterCacheManager.ElementToHandleCache.Register(familyInstance.Id, instanceHandle); break; } case IFCEntityType.IfcPlate: { IFCAnyHandle localPlacement = localPlacementToUse; if (overrideLocalPlacement != null) { isChildInContainer = true; localPlacement = overrideLocalPlacement; } string preDefinedType = string.IsNullOrWhiteSpace(type.ValidatedPredefinedType) ? "NOTDEFINED" : type.ValidatedPredefinedType; instanceHandle = IFCInstanceExporter.CreatePlate(exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacement, productRepresentation, preDefinedType); break; } case IFCEntityType.IfcMechanicalFastener: { double?nominalDiameter = null; double?nominalLength = null; double nominalDiameterVal, nominalLengthVal; if (ParameterUtil.GetDoubleValueFromElementOrSymbol(familyInstance, "NominalDiameter", out nominalDiameterVal) != null) { nominalDiameter = UnitUtil.ScaleLength(nominalDiameterVal); } if (ParameterUtil.GetDoubleValueFromElementOrSymbol(familyInstance, "NominalLength", out nominalLengthVal) != null) { nominalLength = UnitUtil.ScaleLength(nominalLengthVal); } string preDefinedType = string.IsNullOrWhiteSpace(type.ValidatedPredefinedType) ? "NOTDEFINED" : type.ValidatedPredefinedType; instanceHandle = IFCInstanceExporter.CreateMechanicalFastener(exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation, nominalDiameter, nominalLength, preDefinedType); break; } case IFCEntityType.IfcRailing: { //string strEnumType; //IFCExportInfoPair exportAs = ExporterUtil.GetExportType(exporterIFC, familyInstance, out strEnumType); //if (ExporterCacheManager.ExportOptionsCache.ExportAs4) //{ // instanceHandle = IFCInstanceExporter.CreateRailing(exporterIFC, familyInstance, instanceGUID, ownerHistory, // localPlacementToUse, productRepresentation, GetPreDefinedType<Toolkit.IFC4.IFCRailingType>(familyInstance, strEnumType).ToString()); //} //else //{ // instanceHandle = IFCInstanceExporter.CreateRailing(exporterIFC, familyInstance, instanceGUID, ownerHistory, // localPlacementToUse, productRepresentation, GetPreDefinedType<Toolkit.IFCRailingType>(familyInstance, strEnumType).ToString()); //} string preDefinedType = string.IsNullOrWhiteSpace(type.ValidatedPredefinedType) ? "NOTDEFINED" : type.ValidatedPredefinedType; instanceHandle = IFCInstanceExporter.CreateRailing(exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation, preDefinedType); break; } case IFCEntityType.IfcSpace: { IFCInternalOrExternal internalOrExternal = CategoryUtil.IsElementExternal(familyInstance) ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal; instanceHandle = IFCInstanceExporter.CreateSpace(exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation, IFCElementComposition.Element, internalOrExternal); break; } default: { // !!! These entities are deprecated in IFC4 and will be made abstract in the next version. // It is still kept as it is because if we generate an IfcBuildingElementProxy, teh connectivity will be lost if (ExporterCacheManager.ExportOptionsCache.ExportAs4 && (type.ExportInstance == IFCEntityType.IfcDistributionElement || type.ExportInstance == IFCEntityType.IfcEnergyConversionDevice || type.ExportInstance == IFCEntityType.IfcFlowController || type.ExportInstance == IFCEntityType.IfcFlowFitting || type.ExportInstance == IFCEntityType.IfcFlowMovingDevice || type.ExportInstance == IFCEntityType.IfcFlowSegment || type.ExportInstance == IFCEntityType.IfcFlowStorageDevice || type.ExportInstance == IFCEntityType.IfcFlowTerminal || type.ExportInstance == IFCEntityType.IfcFlowTreatmentDevice)) { instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(type, exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation); } else { if (type.ExportInstance != IFCEntityType.UnKnown) { instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(type, exporterIFC, familyInstance, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation); } } break; } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { bool containedInSpace = (roomId != ElementId.InvalidElementId); bool associateToLevel = containedInSpace ? false : !isChildInContainer; wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, associateToLevel); if (containedInSpace) { ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); } } return(instanceHandle); }
/// <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(); 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; // The representation handle generated from one of the methods below. BeamBodyAsExtrusionInfo extrusionInfo = CreateBeamGeometryAsExtrusion(exporterIFC, element, catId, geomObjects, axisInfo); 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); 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; offsetTransform = bodyData.OffsetTransform; } } 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 instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); string preDefinedType = "BEAM"; // Default predefined type for Beam preDefinedType = IFCValidateEntry.GetValidIFCType(element, preDefinedType); beam = IFCInstanceExporter.CreateBeam(file, instanceGUID, ExporterCacheManager.OwnerHistoryHandle, instanceName, instanceDescription, instanceObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, instanceTag, preDefinedType); productWrapper.AddElement(element, beam, setter, extrusionCreationData, true); OpeningUtil.CreateOpeningsIfNecessary(beam, element, extrusionCreationData, offsetTransform, exporterIFC, extrusionCreationData.GetLocalPlacement(), setter, productWrapper); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); typeInfo.ScaledDepth = extrusionCreationData.ScaledLength; typeInfo.ScaledArea = extrusionCreationData.ScaledArea; typeInfo.ScaledInnerPerimeter = extrusionCreationData.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extrusionCreationData.ScaledOuterPerimeter; PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, beam, element, typeInfo, null); if (materialIds.Count != 0) { CategoryUtil.CreateMaterialAssociations(exporterIFC, beam, materialIds); } // Register the beam's IFC handle for later use by truss and beam system export. ExporterCacheManager.ElementToHandleCache.Register(element.Id, beam); } } transaction.Commit(); return(beam); } }
/// <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, IFCExportInfoPair exportType, 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; // Check for containment override IFCAnyHandle overrideContainerHnd = null; ElementId overrideContainerId = ParameterUtil.OverrideContainmentParameter(exporterIFC, element, out overrideContainerHnd); using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, orientTrf, overrideContainerId, overrideContainerHnd)) { 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; bool useFamilySymbolGeometry = (element is FamilyInstance) ? !GeometryUtil.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); if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { bodyExporterOptions.CollectMaterialAndProfile = false; } else { 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); beam = IFCInstanceExporter.CreateBeam(exporterIFC, element, instanceGUID, ExporterCacheManager.OwnerHistoryHandle, extrusionCreationData.GetLocalPlacement(), prodRep, exportType.ValidatedPredefinedType); IFCAnyHandle mpSetUsage; if (materialProfileSet != null) { mpSetUsage = IFCInstanceExporter.CreateMaterialProfileSetUsage(file, materialProfileSet, null, null); } productWrapper.AddElement(element, beam, setter, extrusionCreationData, true, exportType); ExportBeamType(exporterIFC, productWrapper, beam, element, exportType.ValidatedPredefinedType); 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, exportType); } } transaction.Commit(); return(beam); } }
/// <summary> /// Exports a beam to IFC beam. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element to be exported. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportBeam(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { if (geometryElement == null) { return; } IFCFile file = exporterIFC.GetFile(); double scale = exporterIFC.LinearScale; using (IFCTransaction transaction = new IFCTransaction(file)) { LocationCurve locCurve = element.Location as LocationCurve; Transform orientTrf = Transform.Identity; bool canExportAxis = (locCurve != null); IFCAnyHandle axisRep = null; XYZ beamDirection = null; XYZ projDir = null; Curve curve = null; Plane plane = null; if (canExportAxis) { curve = locCurve.Curve; if (curve is Line) { Line line = curve as Line; XYZ planeY, planeOrig; planeOrig = line.get_EndPoint(0); beamDirection = line.Direction; if (Math.Abs(beamDirection.Z) < 0.707) // approx 1.0/sqrt(2.0) { planeY = XYZ.BasisZ.CrossProduct(beamDirection); } else { planeY = XYZ.BasisX.CrossProduct(beamDirection); } planeY = planeY.Normalize(); projDir = beamDirection.CrossProduct(planeY); plane = new Plane(beamDirection, planeY, planeOrig); orientTrf.BasisX = beamDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = planeOrig; } else if (curve is Arc) { XYZ yDir, center; Arc arc = curve as Arc; beamDirection = arc.XDirection; yDir = arc.YDirection; projDir = arc.Normal; center = arc.Center; plane = new Plane(beamDirection, yDir, center); orientTrf.BasisX = beamDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center; } else { canExportAxis = false; } } using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, canExportAxis ? orientTrf : null, ExporterUtil.GetBaseLevelIdForElement(element))) { IFCAnyHandle localPlacement = setter.GetPlacement(); SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { extrusionCreationData.SetLocalPlacement(localPlacement); if (canExportAxis && (orientTrf.BasisX != null)) { extrusionCreationData.CustomAxis = beamDirection; extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom; } else { extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryXY; } IList <Solid> solids = solidMeshInfo.GetSolids(); IList <Mesh> meshes = solidMeshInfo.GetMeshes(); ElementId catId = CategoryUtil.GetSafeCategoryId(element); // The representation handle generated from one of the methods below. IFCAnyHandle repHnd = null; // The list of materials in the solids or meshes. ICollection <ElementId> materialIds = new HashSet <ElementId>(); // There may be an offset to make the local coordinate system // be near the origin. This offset will be used to move the axis to the new LCS. Transform offsetTransform = null; // If we have a beam with a Linear location line that only has one solid geometry, // we will try to use the ExtrusionAnalyzer to generate an extrusion with 0 or more clippings. // This code is currently limited in that it will not process beams with openings, so we // use other methods below if this one fails. if (solids.Count == 1 && meshes.Count == 0 && (canExportAxis && (curve is Line))) { bool completelyClipped; beamDirection = orientTrf.BasisX; Plane beamExtrusionPlane = new Plane(orientTrf.BasisY, orientTrf.BasisZ, orientTrf.Origin); repHnd = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, element, catId, solids[0], beamExtrusionPlane, beamDirection, null, out completelyClipped); if (completelyClipped) { return; } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { // This is used by the BeamSlopeCalculator. This should probably be generated automatically by // CreateExtrusionWithClipping. IFCExtrusionBasis bestAxis = (Math.Abs(beamDirection[0]) > Math.Abs(beamDirection[1])) ? IFCExtrusionBasis.BasisX : IFCExtrusionBasis.BasisY; extrusionCreationData.Slope = GeometryUtil.GetSimpleExtrusionSlope(beamDirection, bestAxis); ElementId materialId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids[0], exporterIFC, element); if (materialId != ElementId.InvalidElementId) { materialIds.Add(materialId); } } } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if (solids.Count > 0 || meshes.Count > 0) { bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, solids, meshes, bodyExporterOptions, extrusionCreationData); } else { IList <GeometryObject> geomlist = new List <GeometryObject>(); geomlist.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, geomlist, bodyExporterOptions, extrusionCreationData); } repHnd = bodyData.RepresentationHnd; materialIds = bodyData.MaterialIds; offsetTransform = bodyData.OffsetTransform; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { extrusionCreationData.ClearOpenings(); return; } IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); if (canExportAxis) { XYZ curveOffset = new XYZ(0, 0, 0); if (offsetTransform != null) { curveOffset = -offsetTransform.Origin / scale; } else { // Note that we do not have to have any scaling adjustment here, since the curve origin is in the // same internal coordinate system as the curve. curveOffset = -plane.Origin; } Plane offsetPlane = new Plane(plane.XVec, plane.YVec, XYZ.Zero); IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetPlane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true); IList <IFCAnyHandle> axis_items = info.GetCurves(); if (axis_items.Count > 0) { string identifierOpt = "Axis"; // this is by IFC2x2 convention, not temporary string representationTypeOpt = "Curve2D"; // this is by IFC2x2 convention, not temporary axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); representations.Add(axisRep); } } representations.Add(repHnd); Transform boundingBoxTrf = (offsetTransform == null) ? Transform.Identity : offsetTransform.Inverse; IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, boundingBoxTrf); if (boundingBoxRep != null) { representations.Add(boundingBoxRep); } IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); string instanceGUID = GUIDUtil.CreateGUID(element); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); IFCAnyHandle beam = IFCInstanceExporter.CreateBeam(file, instanceGUID, exporterIFC.GetOwnerHistoryHandle(), instanceName, instanceDescription, instanceObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, instanceTag); productWrapper.AddElement(element, beam, setter, extrusionCreationData, true); OpeningUtil.CreateOpeningsIfNecessary(beam, element, extrusionCreationData, offsetTransform, exporterIFC, extrusionCreationData.GetLocalPlacement(), setter, productWrapper); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); typeInfo.ScaledDepth = extrusionCreationData.ScaledLength; typeInfo.ScaledArea = extrusionCreationData.ScaledArea; typeInfo.ScaledInnerPerimeter = extrusionCreationData.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extrusionCreationData.ScaledOuterPerimeter; PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, beam, element, typeInfo); if (materialIds.Count != 0) { CategoryUtil.CreateMaterialAssociations(exporterIFC, beam, materialIds); } // Register the beam's IFC handle for later use by truss and beam system export. ExporterCacheManager.ElementToHandleCache.Register(element.Id, beam); } } transaction.Commit(); } }
/// <summary> /// Exports a generic family instance as IFC instance. /// </summary> /// <param name="type">The export type.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="familyInstance">The element.</param> /// <param name="wrapper">The ProductWrapper.</param> /// <param name="setter">The PlacementSetter.</param> /// <param name="extraParams">The extrusion creation data.</param> /// <param name="instanceGUID">The guid.</param> /// <param name="ownerHistory">The owner history handle.</param> /// <param name="instanceName">The name.</param> /// <param name="instanceDescription">The description.</param> /// <param name="instanceObjectType">The object type.</param> /// <param name="productRepresentation">The representation handle.</param> /// <param name="instanceTag">The tag for the entity, usually based on the element id.</param> /// <param name="ifcEnumType">The predefined type/shape type, if any, for the object.</param> /// <param name="overrideLocalPlacement">The local placement to use instead of the one in the placement setter, if appropriate.</param> /// <returns>The handle.</returns> public static IFCAnyHandle ExportGenericInstance(IFCExportType type, ExporterIFC exporterIFC, Element familyInstance, ProductWrapper wrapper, PlacementSetter setter, IFCExtrusionCreationData extraParams, string instanceGUID, IFCAnyHandle ownerHistory, string instanceName, string instanceDescription, string instanceObjectType, IFCAnyHandle productRepresentation, string instanceTag, string ifcEnumType, IFCAnyHandle overrideLocalPlacement) { IFCFile file = exporterIFC.GetFile(); Document doc = familyInstance.Document; bool isRoomRelated = IsRoomRelated(type); bool isChildInContainer = familyInstance.AssemblyInstanceId != ElementId.InvalidElementId; IFCAnyHandle localPlacementToUse = setter.LocalPlacement; ElementId roomId = ElementId.InvalidElementId; if (isRoomRelated) { roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); } //should remove the create method where there is no use of this handle for API methods //some places uses the return value of ExportGenericInstance as input parameter for API methods IFCAnyHandle instanceHandle = null; switch (type) { case IFCExportType.IfcBeam: case IFCExportType.IfcBeamType: { string preDefinedType = string.IsNullOrWhiteSpace(ifcEnumType) ? "BEAM" : ifcEnumType; instanceHandle = IFCInstanceExporter.CreateBeam(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag, preDefinedType); break; } case IFCExportType.IfcColumn: case IFCExportType.IfcColumnType: { string preDefinedType = string.IsNullOrWhiteSpace(ifcEnumType) ? "COLUMN" : ifcEnumType; instanceHandle = IFCInstanceExporter.CreateColumn(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag, preDefinedType); break; } case IFCExportType.IfcCurtainWall: case IFCExportType.IfcCurtainWallType: { instanceHandle = IFCInstanceExporter.CreateCurtainWall(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); break; } case IFCExportType.IfcMember: case IFCExportType.IfcMemberType: { string preDefinedType = string.IsNullOrWhiteSpace(ifcEnumType) ? "BRACE" : ifcEnumType; instanceHandle = IFCInstanceExporter.CreateMember(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag, preDefinedType); // Register the members's IFC handle for later use by truss export. ExporterCacheManager.ElementToHandleCache.Register(familyInstance.Id, instanceHandle); break; } case IFCExportType.IfcPlate: case IFCExportType.IfcPlateType: { IFCAnyHandle localPlacement = localPlacementToUse; if (overrideLocalPlacement != null) { isChildInContainer = true; localPlacement = overrideLocalPlacement; } string preDefinedType = string.IsNullOrWhiteSpace(ifcEnumType) ? "NOTDEFINED" : ifcEnumType; instanceHandle = IFCInstanceExporter.CreatePlate(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacement, productRepresentation, instanceTag, preDefinedType); break; } case IFCExportType.IfcDiscreteAccessoryType: { instanceHandle = IFCInstanceExporter.CreateDiscreteAccessory(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); break; } case IFCExportType.IfcDistributionControlElement: { instanceHandle = IFCInstanceExporter.CreateDistributionControlElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag, null); break; } case IFCExportType.IfcDistributionFlowElement: { instanceHandle = IFCInstanceExporter.CreateDistributionFlowElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); break; } case IFCExportType.IfcDistributionChamberElement: case IFCExportType.IfcDistributionChamberElementType: { instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(Common.Enums.IFCEntityType.IfcDistributionChamberElement, file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); break; } case IFCExportType.IfcFastenerType: { instanceHandle = IFCInstanceExporter.CreateFastener(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); break; } case IFCExportType.IfcMechanicalFastenerType: { double?nominalDiameter = null; double?nominalLength = null; double nominalDiameterVal, nominalLengthVal; if (ParameterUtil.GetDoubleValueFromElementOrSymbol(familyInstance, "NominalDiameter", out nominalDiameterVal) != null) { nominalDiameter = UnitUtil.ScaleLength(nominalDiameterVal); } if (ParameterUtil.GetDoubleValueFromElementOrSymbol(familyInstance, "NominalLength", out nominalLengthVal) != null) { nominalLength = UnitUtil.ScaleLength(nominalLengthVal); } string preDefinedType = string.IsNullOrWhiteSpace(ifcEnumType) ? "NOTDEFINED" : ifcEnumType; instanceHandle = IFCInstanceExporter.CreateMechanicalFastener(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag, nominalDiameter, nominalLength, preDefinedType); break; } case IFCExportType.IfcRailingType: { string strEnumType; IFCExportType exportAs = ExporterUtil.GetExportType(exporterIFC, familyInstance, out strEnumType); if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { instanceHandle = IFCInstanceExporter.CreateRailing(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag, GetPreDefinedType <Toolkit.IFC4.IFCRailingType>(familyInstance, strEnumType).ToString()); } else { instanceHandle = IFCInstanceExporter.CreateRailing(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag, GetPreDefinedType <Toolkit.IFCRailingType>(familyInstance, strEnumType).ToString()); } break; } case IFCExportType.IfcSpace: { string instanceLongName = NamingUtil.GetLongNameOverride(familyInstance, NamingUtil.GetLongNameOverride(familyInstance, instanceName)); IFCInternalOrExternal internalOrExternal = CategoryUtil.IsElementExternal(familyInstance) ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal; instanceHandle = IFCInstanceExporter.CreateSpace(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceLongName, IFCElementComposition.Element, internalOrExternal, null); break; } default: { if (ExporterCacheManager.ExportOptionsCache.ExportAs4 && (type == IFCExportType.IfcDistributionElement || type == IFCExportType.IfcEnergyConversionDevice || type == IFCExportType.IfcFlowController || type == IFCExportType.IfcFlowFitting || type == IFCExportType.IfcFlowMovingDevice || type == IFCExportType.IfcFlowSegment || type == IFCExportType.IfcFlowStorageDevice || type == IFCExportType.IfcFlowTerminal || type == IFCExportType.IfcFlowTreatmentDevice)) { // for IFC4, there are several entities that are valid in IFC2x3 but now have been made abstract or deprecated, so cannot be created. Create proxy instead. //instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(file, instanceGUID, ownerHistory, // instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag, // Toolkit.IFC4.IFCBuildingElementProxyType.USERDEFINED.ToString()); Common.Enums.IFCEntityType exportEntity = Common.Enums.IFCEntityType.UnKnown; if (Enum.TryParse(type.ToString(), out exportEntity)) { instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportEntity, file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } } else if ((type == IFCExportType.IfcPile) || (type == IFCExportType.IfcFurnishingElement) || IsFurnishingElementSubType(type) || (type == IFCExportType.IfcEnergyConversionDevice) || IsEnergyConversionDeviceSubType(type) || (type == IFCExportType.IfcFlowFitting) || IsFlowFittingSubType(type) || (type == IFCExportType.IfcFlowMovingDevice) || IsFlowMovingDeviceSubType(type) || (type == IFCExportType.IfcFlowSegment) || IsFlowSegmentSubType(type) || (type == IFCExportType.IfcFlowStorageDevice) || IsFlowStorageDeviceSubType(type) || (type == IFCExportType.IfcFlowTerminal) || IsFlowTerminalSubType(type) || (type == IFCExportType.IfcFlowTreatmentDevice) || IsFlowTreatmentDeviceSubType(type) || (type == IFCExportType.IfcFlowController) || IsFlowControllerSubType(type) || (type == IFCExportType.IfcDistributionFlowElement) || IsDistributionFlowElementSubType(type) || (type == IFCExportType.IfcDistributionControlElement) || IsDistributionControlElementSubType(type) || (type == IFCExportType.IfcBuildingElementProxy) || (type == IFCExportType.IfcBuildingElementProxyType)) { string exportEntityStr = type.ToString(); Common.Enums.IFCEntityType exportEntity = Common.Enums.IFCEntityType.UnKnown; if (String.Compare(exportEntityStr.Substring(exportEntityStr.Length - 4), "Type", true) == 0) { exportEntityStr = exportEntityStr.Substring(0, (exportEntityStr.Length - 4)); } if (!Enum.TryParse(exportEntityStr, out exportEntity)) { // This is a special case. IFC2x3 has IfcFlowElement for the instance, and both IfcElectricHeaterType and IfcSpaceHeaterType. // IFC4 has IfcSpaceHeater and IfcSpaceHeaterType. // Since IfcElectricHeater doesn't exist in IFC4, TryParse will fail. For the instance only, we will map it to IfcSpaceHeater, // which will in turn be redirected to IfcFlowElement for IFC2x3, if necessary. if (type == IFCExportType.IfcElectricHeaterType) { exportEntity = Common.Enums.IFCEntityType.IfcSpaceHeater; } else { exportEntity = Common.Enums.IFCEntityType.UnKnown; } } if (exportEntity != Common.Enums.IFCEntityType.UnKnown) { instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportEntity, file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } } break; } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { bool containedInSpace = (roomId != ElementId.InvalidElementId); bool associateToLevel = containedInSpace ? false : !isChildInContainer; wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, associateToLevel); if (containedInSpace) { ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); } } return(instanceHandle); }