/// <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> /// Sets IFCValue aggregate attribute for the handle. /// </summary> /// <remarks> /// If values collection is null, the attribute will be unset. /// </remarks> /// <param name="handle">The handle.</param> /// <param name="name">The attribute name.</param> /// <param name="values">The values.</param> /// <exception cref="ArgumentException">If the name is null or empty.</exception> public static void SetAttribute(IFCAnyHandle handle, string name, ICollection <IFCData> values) { if (String.IsNullOrEmpty(name)) { throw new ArgumentException("The name is empty.", "name"); } if (values != null) { if (values.Contains(null)) { throw new ArgumentException("The collection contains null values.", "values"); } IFCAggregate aggregateAttribute = handle.CreateAggregateAttribute(name); if (aggregateAttribute != null) { foreach (IFCData value in values) { aggregateAttribute.Add(value); } } } }
/// <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); }
/// <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); } }
protected override void Process(IFCAnyHandle ifcCurve) { base.Process(ifcCurve); IFCAnyHandle points = IFCAnyHandleUtil.GetInstanceAttribute(ifcCurve, "Points"); if (IFCAnyHandleUtil.IsNullOrHasNoValue(points)) { Importer.TheLog.LogMissingRequiredAttributeError(ifcCurve, "Points", true); return; } IList <IFCData> segments = null; try { // The Segments attribute is new to IFC4 Add1, and we don't know that we may have a // vanilla IFC4 file. If we can't find the attribute, we will assume the points represent // the vertices of a polyline. segments = IFCAnyHandleUtil.GetAggregateAttribute <List <IFCData> >(ifcCurve, "Segments"); } catch (Exception ex) { if (IFCImportFile.HasUndefinedAttribute(ex)) { IFCImportFile.TheFile.DowngradeIFC4SchemaTo(IFCSchemaVersion.IFC4); } else { throw ex; } } IFCCartesianPointList pointList = IFCCartesianPointList.ProcessIFCCartesianPointList(points); IList <XYZ> pointListXYZs = pointList.CoordList; int numPoints = pointListXYZs.Count; CurveLoop curveLoop = null; IList <XYZ> pointXYZs = null; if (segments == null) { // Simple case: no segment information, just treat the curve as a polyline. pointXYZs = pointListXYZs; curveLoop = IFCGeometryUtil.CreatePolyCurveLoop(pointXYZs, null, Id, false); } else { curveLoop = new CurveLoop(); // Assure that we don't add the same point twice for a polyline segment. This could // happen by error, or, e.g., there are two IfcLineIndex segments in a row (although // this could also be considered an error condition.) int lastIndex = -1; // The list of all of the points, in the order that they are added. This can be // used as a backup representation. pointXYZs = new List <XYZ>(); IList <XYZ> currentLineSegmentPoints = new List <XYZ>(); foreach (IFCData segment in segments) { string indexType = ValidateSegment(segment); if (indexType == null) { Importer.TheLog.LogError(Id, "Unknown segment type in IfcIndexedPolyCurve.", false); continue; } IFCAggregate segmentInfo = segment.AsAggregate(); if (indexType.Equals("IfcLineIndex", StringComparison.OrdinalIgnoreCase)) { foreach (IFCData segmentInfoIndex in segmentInfo) { int?currentIndex = GetValidIndex(segmentInfoIndex, numPoints); if (currentIndex == null) { continue; } int validCurrentIndex = currentIndex.Value; if (lastIndex != validCurrentIndex) { pointXYZs.Add(pointListXYZs[validCurrentIndex]); currentLineSegmentPoints.Add(pointListXYZs[validCurrentIndex]); lastIndex = validCurrentIndex; } } } else if (indexType.Equals("IfcArcIndex", StringComparison.OrdinalIgnoreCase)) { // Create any line segments that haven't been already created. CreateLineSegments(curveLoop, currentLineSegmentPoints); if (segmentInfo.Count != 3) { Importer.TheLog.LogError(Id, "Invalid IfcArcIndex in IfcIndexedPolyCurve.", false); continue; } int?startIndex = GetValidIndex(segmentInfo[0], numPoints); int?pointIndex = GetValidIndex(segmentInfo[1], numPoints); int?endIndex = GetValidIndex(segmentInfo[2], numPoints); if (startIndex == null || pointIndex == null || endIndex == null) { continue; } Arc arcSegment = null; XYZ startPoint = pointListXYZs[startIndex.Value]; XYZ pointOnArc = pointListXYZs[pointIndex.Value]; XYZ endPoint = pointListXYZs[endIndex.Value]; try { arcSegment = Arc.Create(startPoint, pointOnArc, endPoint); if (arcSegment != null) { curveLoop.Append(arcSegment); } } catch { // We won't do anything here; it may be that the arc is very small, and can // be repaired as a gap in the curve loop. If it can't, this will fail later. // We will monitor usage to see if anything more needs to be done here. } if (lastIndex != startIndex.Value) { pointXYZs.Add(startPoint); } pointXYZs.Add(pointOnArc); pointXYZs.Add(endPoint); lastIndex = endIndex.Value; } else { Importer.TheLog.LogError(Id, "Unsupported segment type in IfcIndexedPolyCurve.", false); continue; } } // Create any line segments that haven't been already created. CreateLineSegments(curveLoop, currentLineSegmentPoints); } SetCurveLoop(curveLoop, pointXYZs); }