/// <summary> /// Gets aggregate attribute values from a handle. /// </summary> /// <typeparam name="T">The return type.</typeparam> /// <param name="handle">The handle.</param> /// <param name="name">The attribute name.</param> /// <returns>The collection of attribute values.</returns> public static T GetAggregateInstanceAttribute <T>(IFCAnyHandle handle, string name) where T : ICollection <IFCAnyHandle>, new() { if (handle == null) { throw new ArgumentNullException("handle"); } if (!handle.HasValue) { throw new ArgumentException("Invalid handle."); } IFCData ifcData = handle.GetAttribute(name); T aggregateAttribute = default(T); if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate aggregate = ifcData.AsAggregate(); if (aggregate != null) { aggregateAttribute = new T(); foreach (IFCData val in aggregate) { if (val.PrimitiveType == IFCDataPrimitiveType.Instance) { aggregateAttribute.Add(val.AsInstance()); } } } } return(aggregateAttribute); }
private double?GetTrimParameter(IFCData trim, IFCCurve basisCurve, IFCTrimmingPreference trimPreference, bool secondAttempt) { bool preferParam = !(trimPreference == IFCTrimmingPreference.Cartesian); if (secondAttempt) { preferParam = !preferParam; } double vertexEps = MathUtil.VertexEps; IFCAggregate trimAggregate = trim.AsAggregate(); foreach (IFCData trimParam in trimAggregate) { if (!preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Instance)) { IFCAnyHandle trimParamInstance = trimParam.AsInstance(); XYZ trimParamPt = IFCPoint.ProcessScaledLengthIFCCartesianPoint(trimParamInstance); if (trimParamPt == null) { IFCImportFile.TheLog.LogWarning(basisCurve.Id, "Invalid trim point for basis curve.", false); continue; } try { IntersectionResult result = basisCurve.Curve.Project(trimParamPt); if (result.Distance < vertexEps) { return(result.Parameter); } IFCImportFile.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false); } catch { IFCImportFile.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false); } } else if (preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Double)) { double trimParamDouble = trimParam.AsDouble(); if (basisCurve.Curve.IsCyclic) { trimParamDouble = IFCUnitUtil.ScaleAngle(trimParamDouble); } return(trimParamDouble); } } // Try again with opposite preference. if (!secondAttempt) { return(GetTrimParameter(trim, basisCurve, trimPreference, true)); } return(null); }
private double?GetRawTrimParameter(IFCData trim) { IFCAggregate trimAggregate = trim.AsAggregate(); foreach (IFCData trimParam in trimAggregate) { if (trimParam.PrimitiveType == IFCDataPrimitiveType.Double) { return(trimParam.AsDouble()); } } return(null); }
/// <summary> /// Get attribute of type IList of IList of Entity /// </summary> /// <param name="handle">The handle</param> /// <param name="name">attribute name</param> /// <returns>IList of IList of Entity</returns> public static IList <IList <IFCAnyHandle> > GetListOfListOfInstanceAttribute(IFCAnyHandle handle, string name) { if (handle == null) { throw new ArgumentNullException("handle"); } if (!handle.HasValue) { throw new ArgumentException("Invalid handle."); } IList <IList <IFCAnyHandle> > outerList = null; IFCData ifcData = handle.GetAttribute(name); if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate outer = ifcData.AsAggregate(); if (outer != null) { outerList = new List <IList <IFCAnyHandle> >(); foreach (IFCData outerVal in outer) { IFCAggregate inner = outerVal.AsAggregate(); if (inner != null) { IList <IFCAnyHandle> innerList = new List <IFCAnyHandle>(); foreach (IFCData innerVal in inner) { innerList.Add(innerVal.AsInstance()); } outerList.Add(innerList); } } } } return(outerList); }
/// <summary> /// Checks if an object handle has IfcRelDecomposes. /// </summary> /// <param name="objectHandle">The object handle.</param> /// <returns>True if it has, false if not.</returns> public static bool HasRelDecomposes(IFCAnyHandle objectHandle) { if (objectHandle == null) { throw new ArgumentNullException("objectHandle"); } if (!objectHandle.HasValue) { throw new ArgumentException("Invalid handle."); } if (!IsSubTypeOf(objectHandle, IFCEntityType.IfcObject) && !IsSubTypeOf(objectHandle, IFCEntityType.IfcTypeObject)) { throw new ArgumentException("The operation is not valid for this handle."); } IFCData ifcData = objectHandle.GetAttribute("Decomposes"); if (!ifcData.HasValue) { return(false); } else if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate aggregate = ifcData.AsAggregate(); if (aggregate != null && aggregate.Count > 0) { return(true); } else { return(false); } } throw new InvalidOperationException("Failed to get decomposes."); }
/// <summary> /// Gets the coordinates of an IfcCartesianPoint. /// </summary> /// <param name="axisPlacement">The IfcCartesianPoint.</param> /// <returns>The list of coordinates.</returns> public static IList <double> GetCoordinates(IFCAnyHandle cartesianPoint) { IList <double> coordinates = null; if (cartesianPoint == null) { throw new ArgumentNullException("cartesianPoint"); } if (!cartesianPoint.HasValue) { throw new ArgumentException("Invalid handle."); } if (!IsSubTypeOf(cartesianPoint, IFCEntityType.IfcCartesianPoint)) { throw new ArgumentException("Not an IfcCartesianPoint handle."); } IFCData ifcData = cartesianPoint.GetAttribute("Coordinates"); if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate aggregate = ifcData.AsAggregate(); if (aggregate != null && aggregate.Count > 0) { coordinates = new List <double>(); foreach (IFCData val in aggregate) { if (val.PrimitiveType == IFCDataPrimitiveType.Double) { coordinates.Add(val.AsDouble()); } } } } return(coordinates); }
/// <summary> /// Gets IfcRelDecomposes of an object handle. /// </summary> /// <param name="objectHandle">The object handle.</param> /// <returns>The collection of IfcRelDecomposes.</returns> public static HashSet <IFCAnyHandle> GetRelDecomposes(IFCAnyHandle objectHandle) { if (objectHandle == null) { throw new ArgumentNullException("objectHandle"); } if (!objectHandle.HasValue) { throw new ArgumentException("Invalid handle."); } if (!IsSubTypeOf(objectHandle, IFCEntityType.IfcObject) && !IsSubTypeOf(objectHandle, IFCEntityType.IfcTypeObject)) { throw new ArgumentException("The operation is not valid for this handle."); } HashSet <IFCAnyHandle> decomposes = new HashSet <IFCAnyHandle>(); IFCData ifcData = objectHandle.GetAttribute("IsDecomposedBy"); if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate aggregate = ifcData.AsAggregate(); if (aggregate != null && aggregate.Count > 0) { foreach (IFCData val in aggregate) { if (val.PrimitiveType == IFCDataPrimitiveType.Instance) { decomposes.Add(val.AsInstance()); } } } } return(decomposes); }
/// <summary> /// Gets IfcMaterialDefinitionRepresentation inverse set of an IfcMaterial handle. /// </summary> /// <param name="objectHandle">The IfcMaterial handle.</param> /// <returns>The collection of IfcMaterialDefinitionRepresentation.</returns> public static HashSet <IFCAnyHandle> GetHasRepresentation(IFCAnyHandle objectHandle) { if (objectHandle == null) { throw new ArgumentNullException("objectHandle"); } if (!objectHandle.HasValue) { throw new ArgumentException("Invalid handle."); } if (!IsSubTypeOf(objectHandle, IFCEntityType.IfcMaterial)) { throw new ArgumentException("The operation is not valid for this handle."); } HashSet <IFCAnyHandle> hasRepresentation = new HashSet <IFCAnyHandle>(); IFCData ifcData = objectHandle.GetAttribute("HasRepresentation"); if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate aggregate = ifcData.AsAggregate(); if (aggregate != null && aggregate.Count > 0) { foreach (IFCData val in aggregate) { if (val.PrimitiveType == IFCDataPrimitiveType.Instance) { hasRepresentation.Add(val.AsInstance()); } } } } return(hasRepresentation); }
/// <summary> /// Gets representations of a representation handle. /// </summary> /// <param name="representation">The representation handle.</param> /// <returns>The list of representations.</returns> public static List <IFCAnyHandle> GetRepresentations(IFCAnyHandle representation) { if (representation == null) { throw new ArgumentNullException("representation"); } if (!representation.HasValue) { throw new ArgumentException("Invalid handle."); } if (!IsSubTypeOf(representation, IFCEntityType.IfcProductRepresentation)) { throw new ArgumentException("The operation is not valid for this handle."); } List <IFCAnyHandle> representations = new List <IFCAnyHandle>(); IFCData ifcData = representation.GetAttribute("Representations"); if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate aggregate = ifcData.AsAggregate(); if (aggregate != null && aggregate.Count > 0) { foreach (IFCData val in aggregate) { if (val.PrimitiveType == IFCDataPrimitiveType.Instance) { representations.Add(val.AsInstance()); } } } } return(representations); }
private double? GetTrimParameter(IFCData trim, IFCCurve basisCurve, IFCTrimmingPreference trimPreference, bool secondAttempt) { bool preferParam = !(trimPreference == IFCTrimmingPreference.Cartesian); if (secondAttempt) preferParam = !preferParam; double vertexEps = IFCImportFile.TheFile.Document.Application.VertexTolerance; IFCAggregate trimAggregate = trim.AsAggregate(); foreach (IFCData trimParam in trimAggregate) { if (!preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Instance)) { IFCAnyHandle trimParamInstance = trimParam.AsInstance(); XYZ trimParamPt = IFCPoint.ProcessScaledLengthIFCCartesianPoint(trimParamInstance); if (trimParamPt == null) { Importer.TheLog.LogWarning(basisCurve.Id, "Invalid trim point for basis curve.", false); continue; } try { IntersectionResult result = basisCurve.Curve.Project(trimParamPt); if (result.Distance < vertexEps) return result.Parameter; Importer.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false); } catch { Importer.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false); } } else if (preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Double)) { double trimParamDouble = trimParam.AsDouble(); if (basisCurve.Curve.IsCyclic) trimParamDouble = IFCUnitUtil.ScaleAngle(trimParamDouble); else trimParamDouble = IFCUnitUtil.ScaleLength(trimParamDouble); return trimParamDouble; } } // Try again with opposite preference. if (!secondAttempt) return GetTrimParameter(trim, basisCurve, trimPreference, true); return null; }
/// <summary> /// Exports materials for host object. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="hostObject"> /// The host object. /// </param> /// <param name="elemHnds"> /// The host IFC handles. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="levelId"> /// The level id. /// </param> /// <param name="direction"> /// The IFCLayerSetDirection. /// </param> /// <returns> /// True if exported successfully, false otherwise. /// </returns> public static bool ExportHostObjectMaterials(ExporterIFC exporterIFC, HostObject hostObject, IList <IFCAnyHandle> elemHnds, GeometryElement geometryElement, IFCProductWrapper productWrapper, ElementId levelId, Toolkit.IFCLayerSetDirection direction) { if (hostObject == null) { return(true); //nothing to do } if (elemHnds == null || (elemHnds.Count == 0)) { return(true); //nothing to do } IFCFile file = exporterIFC.GetFile(); // Roofs with no components are only allowed one material. We will arbitrarily choose the thickest material. IFCAnyHandle primaryMaterialHnd = null; using (IFCTransaction tr = new IFCTransaction(file)) { if (productWrapper != null) { productWrapper.ClearFinishMaterials(); } double scale = exporterIFC.LinearScale; double scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0; Wall wall = hostObject as Wall; if (wall != null) { scaledWallWidth = wall.Width * scale; scaledOffset = -scaledWallWidth / 2.0; BoundingBoxXYZ boundingBox = wall.get_BoundingBox(null); if (boundingBox != null) { wallHeight = boundingBox.Max.Z - boundingBox.Min.Z; } } ElementId typeElemId = hostObject.GetTypeId(); IFCAnyHandle materialLayerSet = ExporterCacheManager.MaterialLayerSetCache.Find(typeElemId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet)) { HostObjAttributes hostObjAttr = hostObject.Document.GetElement(typeElemId) as HostObjAttributes; if (hostObjAttr == null) { return(true); //nothing to do } List <ElementId> matIds = new List <ElementId>(); List <double> widths = new List <double>(); List <MaterialFunctionAssignment> functions = new List <MaterialFunctionAssignment>(); ElementId baseMatId = CategoryUtil.GetBaseMaterialIdForElement(hostObject); CompoundStructure cs = hostObjAttr.GetCompoundStructure(); if (cs != null) { //TODO: Vertically compound structures are not yet supported by export. if (!cs.IsVerticallyHomogeneous() && !MathUtil.IsAlmostZero(wallHeight)) { cs = cs.GetSimpleCompoundStructure(wallHeight, wallHeight / 2.0); } for (int i = 0; i < cs.LayerCount; ++i) { ElementId matId = cs.GetMaterialId(i); if (matId != ElementId.InvalidElementId) { matIds.Add(matId); } else { matIds.Add(baseMatId); } widths.Add(cs.GetLayerWidth(i)); // save layer function into IFCProductWrapper, // it's used while exporting "Function" of Pset_CoveringCommon functions.Add(cs.GetLayerFunction(i)); } } if (matIds.Count == 0) { matIds.Add(baseMatId); widths.Add(cs != null ? cs.GetWidth() : 0); functions.Add(MaterialFunctionAssignment.None); } List <IFCAnyHandle> layers = new List <IFCAnyHandle>(); double thickestLayer = 0.0; for (int i = 0; i < matIds.Count; ++i) { if (widths[i] < MathUtil.Eps()) { continue; } IFCAnyHandle materialHnd = CategoryUtil.GetOrCreateMaterialHandle(hostObjAttr.Document, exporterIFC, matIds[i]); if (primaryMaterialHnd == null || (widths[i] > thickestLayer)) { primaryMaterialHnd = materialHnd; thickestLayer = widths[i]; } double scaledWidth = widths[i] * scale; IFCAnyHandle materialLayer = IFCInstanceExporter.CreateMaterialLayer(file, materialHnd, scaledWidth, null); layers.Add(materialLayer); if ((productWrapper != null) && (functions[i] == MaterialFunctionAssignment.Finish1 || functions[i] == MaterialFunctionAssignment.Finish2)) { productWrapper.AddFinishMaterial(materialHnd); } } if (layers.Count == 0) { return(false); } string layerSetName = NamingUtil.CreateIFCFamilyName(exporterIFC, -1); materialLayerSet = IFCInstanceExporter.CreateMaterialLayerSet(file, layers, layerSetName); ExporterCacheManager.MaterialLayerSetCache.Register(typeElemId, materialLayerSet); } // IfcMaterialLayerSetUsage is not supported for IfcWall, only IfcWallStandardCase. IFCAnyHandle layerSetUsage = null; for (int ii = 0; ii < elemHnds.Count; ii++) { IFCAnyHandle elemHnd = elemHnds[ii]; if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd)) { continue; } HashSet <IFCAnyHandle> relDecomposesSet = IFCAnyHandleUtil.GetRelDecomposes(elemHnd); IList <IFCAnyHandle> subElemHnds = new List <IFCAnyHandle>(); if (relDecomposesSet != null && relDecomposesSet.Count == 1) { IFCAnyHandle relAggregates = relDecomposesSet.First(); if (IFCAnyHandleUtil.IsTypeOf(relAggregates, IFCEntityType.IfcRelAggregates)) { IFCData ifcData = relAggregates.GetAttribute("RelatedObjects"); if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate aggregate = ifcData.AsAggregate(); if (aggregate != null && aggregate.Count > 0) { foreach (IFCData val in aggregate) { if (val.PrimitiveType == IFCDataPrimitiveType.Instance) { subElemHnds.Add(val.AsInstance()); } } } } } } bool hasSubElems = !(subElemHnds.Count == 0); bool isRoof = IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcRoof); if (!hasSubElems && !isRoof && !IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcWall)) { if (layerSetUsage == null) { bool flipDirSense = true; if (wall != null) { // if we have flipped the center curve on export, we need to take that into account here. // We flip the center curve on export if it is an arc and it has a negative Z direction. LocationCurve locCurve = wall.Location as LocationCurve; if (locCurve != null) { Curve curve = locCurve.Curve; Plane defPlane = new Plane(XYZ.BasisX, XYZ.BasisY, XYZ.Zero); bool curveFlipped = GeometryUtil.MustFlipCurve(defPlane, curve); flipDirSense = !(wall.Flipped ^ curveFlipped); } } else if (hostObject is Floor) { flipDirSense = false; } double offsetFromReferenceLine = flipDirSense ? -scaledOffset : scaledOffset; IFCDirectionSense sense = flipDirSense ? IFCDirectionSense.Negative : IFCDirectionSense.Positive; layerSetUsage = IFCInstanceExporter.CreateMaterialLayerSetUsage(file, materialLayerSet, direction, sense, offsetFromReferenceLine); } ExporterCacheManager.MaterialLayerRelationsCache.Add(layerSetUsage, elemHnd); } else { if (hasSubElems) { foreach (IFCAnyHandle subElemHnd in subElemHnds) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(subElemHnd)) { ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, subElemHnd); } } } else if (!isRoof) { ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, elemHnd); } else if (primaryMaterialHnd != null) { ExporterCacheManager.MaterialLayerRelationsCache.Add(primaryMaterialHnd, elemHnd); } } exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, hostObject.Id, levelId); } tr.Commit(); return(true); } }