/// <summary> /// Get information about the structural member axis, if possible. /// Here we will do the following: /// - Calculate the Axis LCS by using the Axis curve itself with the StartPoint of the curve to be the origin and the tangent of the curve at origin as the direction /// - The curve is then transformed to its LCS /// </summary> /// <param name="element">The structural member element.</param> /// <returns>The StructuralMemberAxisInfo structure, or null if the structural member has no axis, or it is not a Line or Arc.</returns> public static StructuralMemberAxisInfo GetStructuralMemberAxisTransform(Element element) { StructuralMemberAxisInfo axisInfo = null; Transform orientTrf = Transform.Identity; XYZ structMemberDirection = null; XYZ projDir = null; Curve curve = null; LocationCurve locCurve = element.Location as LocationCurve; bool canExportAxis = (locCurve != null); if (canExportAxis) { // Here we are defining the Axis Curve LCS by using the start point (for line) as the origin. // For the Arc, the center is the origin // The Structural member direction is the X-Axis curve = locCurve.Curve; if (curve is Line) { Line line = curve as Line; XYZ planeY; XYZ LCSorigin = line.GetEndPoint(0); structMemberDirection = line.Direction.Normalize(); if (Math.Abs(structMemberDirection.Z) < 0.707) // approx 1.0/sqrt(2.0) { planeY = XYZ.BasisZ.CrossProduct(structMemberDirection).Normalize(); } else { planeY = XYZ.BasisX.CrossProduct(structMemberDirection).Normalize(); } projDir = structMemberDirection.CrossProduct(planeY); orientTrf.BasisX = structMemberDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = LCSorigin; } else if (curve is Arc) { XYZ yDir; Arc arc = curve as Arc; structMemberDirection = arc.XDirection.Normalize(); yDir = arc.YDirection.Normalize(); projDir = arc.Normal; XYZ center = arc.Center; if (!MathUtil.IsAlmostZero(structMemberDirection.DotProduct(yDir))) { // ensure that beamDirection and yDir are orthogonal yDir = projDir.CrossProduct(structMemberDirection); yDir = yDir.Normalize(); } orientTrf.BasisX = structMemberDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center; } else { canExportAxis = false; } } if (canExportAxis) { axisInfo = new StructuralMemberAxisInfo(); axisInfo.Axis = curve.CreateTransformed(orientTrf.Inverse); // transform the curve into its LCS axisInfo.AxisDirection = orientTrf.BasisX; // We define here the Axis Curve to be following the X-axis axisInfo.AxisNormal = orientTrf.BasisZ; axisInfo.LCSAsTransform = orientTrf; } return(axisInfo); }
/// <summary> /// Exports an element to IfcPile. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="ifcEnumType">The string value represents the IFC type.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportPile(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, string ifcEnumType, ProductWrapper productWrapper) { // NOTE: We expect to incorporate this code into the generic FamilyInstanceExporter at some point. // export parts or not bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, element.LevelId, false)) { return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { // Check for containment override IFCAnyHandle overrideContainerHnd = null; ElementId overrideContainerId = ParameterUtil.OverrideContainmentParameter(exporterIFC, element, out overrideContainerHnd); using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, null, overrideContainerId, overrideContainerHnd)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(setter.LocalPlacement); IFCAnyHandle prodRep = null; ElementId matId = ElementId.InvalidElementId; if (!exportParts) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); StructuralMemberAxisInfo axisInfo = StructuralMemberExporter.GetStructuralMemberAxisTransform(element); if (axisInfo != null) { ecData.CustomAxis = axisInfo.AxisDirection; ecData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom; } else { ecData.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; } prodRep = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, catId, geometryElement, bodyExporterOptions, null, ecData, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodRep)) { ecData.ClearOpenings(); return; } } string instanceGUID = GUIDUtil.CreateGUID(element); IFCExportInfoPair exportInfo = new IFCExportInfoPair(Common.Enums.IFCEntityType.IfcPile, ifcEnumType); IFCAnyHandle pile = IFCInstanceExporter.CreatePile(exporterIFC, element, instanceGUID, ExporterCacheManager.OwnerHistoryHandle, ecData.GetLocalPlacement(), prodRep, ifcEnumType, null); // TODO: to allow shared geometry for Piles. For now, Pile export will not use shared geometry if (exportInfo.ExportType != Common.Enums.IFCEntityType.UnKnown) { IFCAnyHandle type = ExporterUtil.CreateGenericTypeFromElement(element, exportInfo, file, ExporterCacheManager.OwnerHistoryHandle, exportInfo.ValidatedPredefinedType, productWrapper); ExporterCacheManager.TypeRelationsCache.Add(type, pile); } if (exportParts) { PartExporter.ExportHostPart(exporterIFC, element, pile, productWrapper, setter, setter.LocalPlacement, null); } else { if (matId != ElementId.InvalidElementId) { CategoryUtil.CreateMaterialAssociation(exporterIFC, pile, matId); } } productWrapper.AddElement(element, pile, setter, ecData, true, exportInfo); OpeningUtil.CreateOpeningsIfNecessary(pile, element, ecData, null, exporterIFC, ecData.GetLocalPlacement(), setter, productWrapper); } } tr.Commit(); } }
/// <summary> /// Create the handle corresponding to the "Axis" IfcRepresentation for a structural member objects, if possible. /// </summary> /// <param name="exporterIFC">The ExporterIFC class.</param> /// <param name="element">The structural member element.</param> /// <param name="catId">The structural member category id.</param> /// <param name="axisInfo">The optional structural member axis information.</param> /// <param name="offsetTransform">The optional offset transform applied to the "Body" representation.</param> /// <returns>The handle, or null if not created.</returns> public static IFCAnyHandle CreateStructuralMemberAxis(ExporterIFC exporterIFC, Element element, ElementId catId, StructuralMemberAxisInfo axisInfo, Transform newTransformLCS) { if (axisInfo == null) { return(null); } // This Axis should have been transformed into its ECS position previously (in GetStructuralMemberAxisTransform()) Curve curve = axisInfo.Axis; Transform offset = Transform.Identity; if (newTransformLCS != null) { // We need to flip the Left-handed transform to the right-hand one as IFC only support right-handed coordinate system if (newTransformLCS.Determinant < 0) { XYZ orig = newTransformLCS.Origin; newTransformLCS.Origin = XYZ.Zero; offset = FlipYTrf().Multiply(newTransformLCS); offset.Origin = orig; } else { offset = newTransformLCS; } } // Calculate the transformation matrix to tranform the original Axis Curve at its ECS into the new ECS assigned in the offset curve = curve.CreateTransformed(offset.Inverse.Multiply(axisInfo.LCSAsTransform)); IDictionary <IFCFuzzyXYZ, IFCAnyHandle> cachePoints = new Dictionary <IFCFuzzyXYZ, IFCAnyHandle>(); IFCAnyHandle ifcCurveHnd = GeometryUtil.CreateIFCCurveFromRevitCurve(exporterIFC.GetFile(), exporterIFC, curve, true, cachePoints); IList <IFCAnyHandle> axis_items = new List <IFCAnyHandle>(); if (!(IFCAnyHandleUtil.IsNullOrHasNoValue(ifcCurveHnd))) { axis_items.Add(ifcCurveHnd); } if (axis_items.Count > 0) { string identifierOpt = "Axis"; // This is by IFC2x2+ convention. string representationTypeOpt = "Curve3D"; // This is by IFC2x2+ convention. IFCAnyHandle axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); return(axisRep); } return(null); }
/// <summary> /// Exports an element to IfcPile. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="ifcEnumType">The string value represents the IFC type.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportPile(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, string ifcEnumType, ProductWrapper productWrapper) { // export parts or not bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, element.LevelId, false)) { return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(setter.LocalPlacement); IFCAnyHandle prodRep = null; ElementId matId = ElementId.InvalidElementId; if (!exportParts) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); StructuralMemberAxisInfo axisInfo = StructuralMemberExporter.GetStructuralMemberAxisTransform(element); if (axisInfo != null) { ecData.CustomAxis = axisInfo.AxisDirection; ecData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom; } else { ecData.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; } prodRep = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, catId, geometryElement, bodyExporterOptions, null, ecData, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodRep)) { ecData.ClearOpenings(); return; } } string instanceGUID = GUIDUtil.CreateGUID(element); //string pileType = IFCValidateEntry.GetValidIFCPredefinedType(element, ifcEnumType); IFCAnyHandle pile = IFCInstanceExporter.CreatePile(exporterIFC, element, instanceGUID, ExporterCacheManager.OwnerHistoryHandle, ecData.GetLocalPlacement(), prodRep, ifcEnumType, null); if (exportParts) { PartExporter.ExportHostPart(exporterIFC, element, pile, productWrapper, setter, setter.LocalPlacement, null); } else { if (matId != ElementId.InvalidElementId) { CategoryUtil.CreateMaterialAssociation(exporterIFC, pile, matId); } } productWrapper.AddElement(element, pile, setter, ecData, true); OpeningUtil.CreateOpeningsIfNecessary(pile, element, ecData, null, exporterIFC, ecData.GetLocalPlacement(), setter, productWrapper); } } tr.Commit(); } }