/// <summary> /// Processes IfcSpace attributes. /// </summary> /// <param name="ifcSpace">The IfcSpace handle.</param> protected override void Process(IFCAnyHandle ifcSpace) { base.Process(ifcSpace); ElevationWithFlooring = IFCImportHandleUtil.GetOptionalScaledLengthAttribute(ifcSpace, "ElevationWithFlooring", 0.0); }
/// <summary> /// Processes IfcRepresentation attributes. /// </summary> /// <param name="ifcRepresentation">The IfcRepresentation handle.</param> override protected void Process(IFCAnyHandle ifcRepresentation) { base.Process(ifcRepresentation); IFCAnyHandle representationContext = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcRepresentation, "ContextOfItems", false); if (representationContext != null) { Context = IFCRepresentationContext.ProcessIFCRepresentationContext(representationContext); } string identifier = IFCImportHandleUtil.GetOptionalStringAttribute(ifcRepresentation, "RepresentationIdentifier", null); Identifier = GetRepresentationIdentifier(identifier, ifcRepresentation); // Don't read in Box represenation unless options allow it. bool isBoundingBox = (Identifier == IFCRepresentationIdentifier.Box); if (isBoundingBox && !IFCImportFile.TheFile.Options.ProcessBoundingBoxGeometry) { throw new InvalidOperationException("BoundingBox not imported with ProcessBoundingBoxGeometry=false"); } Type = IFCImportHandleUtil.GetOptionalStringAttribute(ifcRepresentation, "RepresentationType", null); HashSet <IFCAnyHandle> items = IFCAnyHandleUtil.GetAggregateInstanceAttribute <HashSet <IFCAnyHandle> >(ifcRepresentation, "Items"); LayerAssignment = IFCPresentationLayerAssignment.GetTheLayerAssignment(ifcRepresentation, true); foreach (IFCAnyHandle item in items) { IFCRepresentationItem repItem = null; try { if (NotAllowedInRepresentation(item)) { IFCEntityType entityType = IFCAnyHandleUtil.GetEntityType(item); Importer.TheLog.LogWarning(item.StepId, "Ignoring unhandled representation item of type " + entityType.ToString() + " in " + Identifier.ToString() + " representation.", true); continue; } // Special processing for bounding boxes - only IfcBoundingBox allowed. if (isBoundingBox) { BoundingBox = ProcessBoundingBox(item); if (BoundingBox != null) { break; } } else { repItem = IFCRepresentationItem.ProcessIFCRepresentationItem(item); } } catch (Exception ex) { Importer.TheLog.LogError(item.StepId, ex.Message, false); } if (repItem != null) { RepresentationItems.Add(repItem); } } }
/// <summary> /// Processes IfcObjectDefinition attributes. /// </summary> /// <param name="ifcObjectDefinition">The IfcObjectDefinition handle.</param> protected override void Process(IFCAnyHandle ifcObjectDefinition) { base.Process(ifcObjectDefinition); PredefinedType = GetPredefinedType(ifcObjectDefinition); // If we aren't importing this category, skip processing. if (!IFCCategoryUtil.CanImport(EntityType, PredefinedType)) { throw new InvalidOperationException("Don't Import"); } // Before IFC2x3, IfcTypeObject did not have IsDecomposedBy. HashSet <IFCAnyHandle> elemSet = null; if (IFCImportFile.TheFile.SchemaVersion >= IFCSchemaVersion.IFC2x3 || !IFCAnyHandleUtil.IsSubTypeOf(ifcObjectDefinition, IFCEntityType.IfcTypeObject)) { elemSet = IFCAnyHandleUtil.GetAggregateInstanceAttribute <HashSet <IFCAnyHandle> >(ifcObjectDefinition, "IsDecomposedBy"); } if (elemSet != null) { foreach (IFCAnyHandle elem in elemSet) { ProcessIFCRelDecomposes(elem); } } HashSet <IFCAnyHandle> hasAssociations = IFCAnyHandleUtil.GetAggregateInstanceAttribute <HashSet <IFCAnyHandle> >(ifcObjectDefinition, "HasAssociations"); if (hasAssociations != null) { foreach (IFCAnyHandle hasAssociation in hasAssociations) { if (IFCAnyHandleUtil.IsSubTypeOf(hasAssociation, IFCEntityType.IfcRelAssociatesMaterial)) { ProcessIFCRelAssociatesMaterial(hasAssociation); } else if (IFCAnyHandleUtil.IsSubTypeOf(hasAssociation, IFCEntityType.IfcRelAssociatesClassification)) { ProcessRelAssociatesClassification(hasAssociation); } else { Importer.TheLog.LogUnhandledSubTypeError(hasAssociation, IFCEntityType.IfcRelAssociates, false); } } } // The default IFC2x3_TC1.exp file does not have this INVERSE attribute correctly set. Encapsulate this function. ISet <IFCAnyHandle> hasAssignments = IFCImportHandleUtil.GetHasAssignments(ifcObjectDefinition); if (hasAssignments != null) { foreach (IFCAnyHandle hasAssignment in hasAssignments) { ProcessIFCRelAssigns(hasAssignment); } } Importer.TheLog.AddToElementCount(); }
/// <summary> /// Processes IfcBuildingStorey attributes. /// </summary> /// <param name="ifcIFCBuildingStorey">The IfcBuildingStorey handle.</param> protected override void Process(IFCAnyHandle ifcIFCBuildingStorey) { base.Process(ifcIFCBuildingStorey); Elevation = IFCImportHandleUtil.GetOptionalScaledLengthAttribute(ifcIFCBuildingStorey, "Elevation", 0.0); }
override protected void Process(IFCAnyHandle item) { base.Process(item); Name = IFCImportHandleUtil.GetOptionalStringAttribute(item, "Name", null); }
/// <summary> /// Processes IfcGridAxis attributes. /// </summary> /// <param name="ifcGridAxis">The IfcGridAxis handle.</param> protected override void Process(IFCAnyHandle ifcGridAxis) { base.Process(ifcGridAxis); AxisTag = IFCImportHandleUtil.GetOptionalStringAttribute(ifcGridAxis, "AxisTag", null); if (AxisTag == null) { AxisTag = "Z"; // arbitrary; all Revit Grids have names. } IFCAnyHandle axisCurve = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcGridAxis, "AxisCurve", true); AxisCurve = IFCCurve.ProcessIFCCurve(axisCurve); bool found = false; bool sameSense = IFCImportHandleUtil.GetRequiredBooleanAttribute(ifcGridAxis, "SameSense", out found); SameSense = found ? sameSense : true; // We are going to check if this grid axis is a vertical duplicate of any existing axis. // If so, we will throw an exception so that we don't create duplicate grids. // We will only initialize these values if we actually intend to use them below. IList <Curve> curves = null; int curveCount = 0; ElementId gridId = ElementId.InvalidElementId; if (Importer.TheCache.GridNameToElementMap.TryGetValue(AxisTag, out gridId)) { Grid grid = IFCImportFile.TheFile.Document.GetElement(gridId) as Grid; if (grid != null) { IList <Curve> otherCurves = new List <Curve>(); Curve gridCurve = grid.Curve; if (gridCurve != null) { otherCurves.Add(gridCurve); long matchingGridId = FindMatchingGrid(otherCurves, grid.Id.IntegerValue, ref curves, ref curveCount); if (matchingGridId != -1) { Importer.TheCache.UseGrid(grid); CreatedElementId = grid.Id; return; } } } } IDictionary <string, IFCGridAxis> gridAxes = IFCImportFile.TheFile.IFCProject.GridAxes; IFCGridAxis gridAxis = null; if (gridAxes.TryGetValue(AxisTag, out gridAxis)) { long matchingGridId = FindMatchingGrid(gridAxis, ref curves, ref curveCount); if (matchingGridId != -1) { DuplicateAxisId = matchingGridId; return; } else { // Revit doesn't allow grid lines to have the same name. If it isn't a duplicate, rename it. // Note that this will mean that we may miss some "duplicate" grid lines because of the renaming. AxisTag = MakeAxisTagUnique(AxisTag); } } gridAxes.Add(new KeyValuePair <string, IFCGridAxis>(AxisTag, this)); }
protected override void Process(IFCAnyHandle ifcCurve) { base.Process(ifcCurve); bool found = false; bool sameSense = IFCImportHandleUtil.GetRequiredBooleanAttribute(ifcCurve, "SenseAgreement", out found); if (!found) { sameSense = true; } IFCAnyHandle basisCurve = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurve, "BasisCurve", true); IFCCurve ifcBasisCurve = IFCCurve.ProcessIFCCurve(basisCurve); if (ifcBasisCurve == null || (ifcBasisCurve.Curve == null && ifcBasisCurve.CurveLoop == null)) { // LOG: ERROR: Error processing BasisCurve # for IfcTrimmedCurve #. return; } if (ifcBasisCurve.Curve == null) { // LOG: ERROR: Expected a single curve, not a curve loop for BasisCurve # for IfcTrimmedCurve #. return; } IFCData trim1 = ifcCurve.GetAttribute("Trim1"); if (trim1.PrimitiveType != IFCDataPrimitiveType.Aggregate) { // LOG: ERROR: Invalid data type for Trim1 attribute for IfcTrimmedCurve #. return; } IFCData trim2 = ifcCurve.GetAttribute("Trim2"); if (trim2.PrimitiveType != IFCDataPrimitiveType.Aggregate) { // LOG: ERROR: Invalid data type for Trim1 attribute for IfcTrimmedCurve #. return; } // Note that these are the "unprocessed" values. These can be used for, e.g., adding up the IFC parameter length // of the file, to account for export errors. The "processed" values can be determined from the Revit curves. Trim1 = GetRawTrimParameter(trim1); Trim2 = GetRawTrimParameter(trim2); IFCTrimmingPreference trimPreference = IFCEnums.GetSafeEnumerationAttribute <IFCTrimmingPreference>(ifcCurve, "MasterRepresentation", IFCTrimmingPreference.Parameter); double param1 = 0.0, param2 = 0.0; try { GetTrimParameters(trim1, trim2, ifcBasisCurve, trimPreference, out param1, out param2); } catch (Exception ex) { Importer.TheLog.LogError(ifcCurve.StepId, ex.Message, false); return; } Curve baseCurve = ifcBasisCurve.Curve; if (baseCurve.IsCyclic) { if (!sameSense) { MathUtil.Swap(ref param1, ref param2); } if (param2 < param1) { param2 = MathUtil.PutInRange(param2, param1 + Math.PI, 2 * Math.PI); } if (param2 - param1 > 2.0 * Math.PI - MathUtil.Eps()) { Importer.TheLog.LogWarning(ifcCurve.StepId, "IfcTrimmedCurve length is greater than 2*PI, leaving unbound.", false); Curve = baseCurve; return; } Curve = baseCurve.Clone(); try { Curve.MakeBound(param1, param2); } catch (Exception ex) { if (ex.Message.Contains("too small")) { Curve = null; Importer.TheLog.LogError(Id, "curve length is invalid, ignoring.", false); return; } else { throw ex; } } } else { if (MathUtil.IsAlmostEqual(param1, param2)) { Importer.TheLog.LogError(Id, "Param1 = Param2 for IfcTrimmedCurve #, ignoring.", false); return; } if (param1 > param2 - MathUtil.Eps()) { Importer.TheLog.LogWarning(Id, "Param1 > Param2 for IfcTrimmedCurve #, reversing.", false); MathUtil.Swap(ref param1, ref param2); return; } Curve copyCurve = baseCurve.Clone(); double length = param2 - param1; if (length <= IFCImportFile.TheFile.Document.Application.ShortCurveTolerance) { string lengthAsString = IFCUnitUtil.FormatLengthAsString(length); Importer.TheLog.LogError(Id, "curve length of " + lengthAsString + " is invalid, ignoring.", false); return; } copyCurve.MakeBound(param1, param2); if (sameSense) { Curve = copyCurve; } else { Curve = copyCurve.CreateReversed(); } } CurveLoop = new CurveLoop(); CurveLoop.Append(Curve); }
protected override void Process(IFCAnyHandle ifcCurve) { base.Process(ifcCurve); bool found = false; bool sameSense = IFCImportHandleUtil.GetRequiredBooleanAttribute(ifcCurve, "SenseAgreement", out found); if (!found) { sameSense = true; } IFCAnyHandle basisCurve = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurve, "BasisCurve", true); IFCCurve ifcBasisCurve = IFCCurve.ProcessIFCCurve(basisCurve); if (ifcBasisCurve == null || (ifcBasisCurve.IsEmpty())) { // LOG: ERROR: Error processing BasisCurve # for IfcTrimmedCurve #. return; } if (ifcBasisCurve.Curve == null) { // LOG: ERROR: Expected a single curve, not a curve loop for BasisCurve # for IfcTrimmedCurve #. return; } IFCData trim1 = ifcCurve.GetAttribute("Trim1"); if (trim1.PrimitiveType != IFCDataPrimitiveType.Aggregate) { // LOG: ERROR: Invalid data type for Trim1 attribute for IfcTrimmedCurve #. return; } IFCData trim2 = ifcCurve.GetAttribute("Trim2"); if (trim2.PrimitiveType != IFCDataPrimitiveType.Aggregate) { // LOG: ERROR: Invalid data type for Trim1 attribute for IfcTrimmedCurve #. return; } // Note that these are the "unprocessed" values. These can be used for, e.g., adding up the IFC parameter length // of the file, to account for export errors. The "processed" values can be determined from the Revit curves. Trim1 = GetRawTrimParameter(trim1); Trim2 = GetRawTrimParameter(trim2); IFCTrimmingPreference trimPreference = IFCEnums.GetSafeEnumerationAttribute <IFCTrimmingPreference>(ifcCurve, "MasterRepresentation", IFCTrimmingPreference.Parameter); double param1 = 0.0, param2 = 0.0; Curve baseCurve = ifcBasisCurve.Curve; try { GetTrimParameters(ifcBasisCurve.Id, trim1, trim2, baseCurve, trimPreference, out param1, out param2); if (NeedToReverseBaseCurve(baseCurve, param1, param2, trimPreference)) { Importer.TheLog.LogWarning(Id, "Invalid Param1 > Param2 for non-cyclic IfcTrimmedCurve using Cartesian trimming preference, reversing.", false); baseCurve = baseCurve.CreateReversed(); GetTrimParameters(ifcBasisCurve.Id, trim1, trim2, baseCurve, trimPreference, out param1, out param2); } } catch (Exception ex) { Importer.TheLog.LogError(ifcCurve.StepId, ex.Message, false); return; } if (MathUtil.IsAlmostEqual(param1, param2)) { Importer.TheLog.LogError(Id, "Param1 = Param2 for IfcTrimmedCurve #, ignoring.", false); return; } Curve curve = null; if (baseCurve.IsCyclic) { double period = baseCurve.Period; if (!sameSense) { MathUtil.Swap(ref param1, ref param2); } // We want to make sure both values are within period of one another. param1 = MathUtil.PutInRange(param1, 0, period); param2 = MathUtil.PutInRange(param2, 0, period); if (param2 < param1) { param2 = MathUtil.PutInRange(param2, param1 + period / 2, period); } // This is effectively an unbound curve. double numberOfPeriods = (param2 - param1) / period; if (MathUtil.IsAlmostEqual(numberOfPeriods, Math.Round(numberOfPeriods))) { Importer.TheLog.LogWarning(Id, "Start and end parameters indicate a zero-length closed curve, assuming unbound is intended.", false); curve = baseCurve; } else { curve = baseCurve.Clone(); if (!SafelyBoundCurve(curve, param1, param2)) { return; } } } else { if (param1 > param2 - MathUtil.Eps()) { Importer.TheLog.LogWarning(Id, "Param1 > Param2 for IfcTrimmedCurve #, reversing.", false); MathUtil.Swap(ref param1, ref param2); sameSense = !sameSense; } Curve copyCurve = baseCurve.Clone(); double length = param2 - param1; if (length <= IFCImportFile.TheFile.Document.Application.ShortCurveTolerance) { string lengthAsString = IFCUnitUtil.FormatLengthAsString(length); Importer.TheLog.LogError(Id, "curve length of " + lengthAsString + " is invalid, ignoring.", false); return; } if (!SafelyBoundCurve(copyCurve, param1, param2)) { return; } if (sameSense) { curve = copyCurve; } else { curve = copyCurve.CreateReversed(); } } CurveLoop curveLoop = new CurveLoop(); curveLoop.Append(curve); SetCurveLoop(curveLoop); }
override protected void Process(IFCAnyHandle item) { base.Process(item); IFCAnyHandle localOrigin = IFCImportHandleUtil.GetRequiredInstanceAttribute(item, "LocalOrigin", false); XYZ origin = null; if (localOrigin != null) { origin = IFCPoint.ProcessScaledLengthIFCCartesianPoint(localOrigin); } else { origin = XYZ.Zero; } IFCAnyHandle axis1 = IFCImportHandleUtil.GetOptionalInstanceAttribute(item, "Axis1"); XYZ xAxis = null; if (axis1 != null) { xAxis = IFCPoint.ProcessNormalizedIFCDirection(axis1); } IFCAnyHandle axis2 = IFCImportHandleUtil.GetOptionalInstanceAttribute(item, "Axis2"); XYZ yAxis = null; if (axis2 != null) { yAxis = IFCPoint.ProcessNormalizedIFCDirection(axis2); } Scale = IFCImportHandleUtil.GetOptionalRealAttribute(item, "Scale", 1.0); XYZ zAxis = null; if (IFCAnyHandleUtil.IsSubTypeOf(item, IFCEntityType.IfcCartesianTransformationOperator2DnonUniform)) { ScaleY = IFCImportHandleUtil.GetOptionalRealAttribute(item, "Scale2", Scale); } else if (IFCAnyHandleUtil.IsSubTypeOf(item, IFCEntityType.IfcCartesianTransformationOperator3D)) { IFCAnyHandle axis3 = IFCImportHandleUtil.GetOptionalInstanceAttribute(item, "Axis3"); if (axis3 != null) { zAxis = IFCPoint.ProcessNormalizedIFCDirection(axis3); } if (IFCAnyHandleUtil.IsSubTypeOf(item, IFCEntityType.IfcCartesianTransformationOperator3DnonUniform)) { ScaleY = IFCImportHandleUtil.GetOptionalRealAttribute(item, "Scale2", Scale); ScaleZ = IFCImportHandleUtil.GetOptionalRealAttribute(item, "Scale3", Scale); } } // Set the axes based on what is specified. // If all three axes are set, ensure they are truly orthogonal. // If two axes are set, ensure they are orthogonal and set the 3rd axis to be the cross product. // If one axis is set, arbitrarily set the next axis to be the basis vector which // If no axes are set, use identity transform. if (xAxis == null) { if (yAxis == null) { if (zAxis == null) { xAxis = XYZ.BasisX; yAxis = XYZ.BasisY; zAxis = XYZ.BasisZ; } } else if (zAxis == null) { // Special case - Y axis is in XY plane. if (MathUtil.IsAlmostZero(yAxis[2])) { xAxis = new XYZ(yAxis[1], -yAxis[0], 0.0); zAxis = XYZ.BasisZ; } else { throw new InvalidOperationException("#" + item.StepId + ": IfcCartesianTransformOperator has only y axis defined, ignoring."); } } else { xAxis = yAxis.CrossProduct(zAxis); } } else if (yAxis == null) { if (zAxis == null) { // Special case - X axis is in XY plane. if (MathUtil.IsAlmostZero(xAxis[2])) { yAxis = new XYZ(xAxis[1], -xAxis[0], 0.0); zAxis = XYZ.BasisZ; } else { throw new InvalidOperationException("#" + item.StepId + ": IfcCartesianTransformOperator has only x axis defined, ignoring."); } } else { yAxis = zAxis.CrossProduct(xAxis); } } else if (zAxis == null) { zAxis = xAxis.CrossProduct(yAxis); } // Make sure that the axes are really orthogonal. if (!MathUtil.IsAlmostZero(xAxis.DotProduct(zAxis))) { zAxis = xAxis.CrossProduct(yAxis); } if (!MathUtil.IsAlmostZero(xAxis.DotProduct(yAxis))) { yAxis = zAxis.CrossProduct(xAxis); } Transform = Transform.CreateTranslation(origin); Transform.set_Basis(0, xAxis); Transform.set_Basis(1, yAxis); Transform.set_Basis(2, zAxis); }