/// <summary> /// Process IfcTriangulatedFaceSet instance /// </summary> /// <param name="ifcTriangulatedFaceSet">the handle</param> protected override void Process(IFCAnyHandle ifcTriangulatedFaceSet) { base.Process(ifcTriangulatedFaceSet); IList <IList <double> > normals = IFCImportHandleUtil.GetListOfListOfDoubleAttribute(ifcTriangulatedFaceSet, "Normals"); if (normals != null) { if (normals.Count > 0) { Normals = normals; } } bool?closed = IFCAnyHandleUtil.GetBooleanAttribute(ifcTriangulatedFaceSet, "Closed"); if (closed != null) { Closed = closed; } IList <IList <int> > coordIndex = IFCImportHandleUtil.GetListOfListOfIntegerAttribute(ifcTriangulatedFaceSet, "CoordIndex"); if (coordIndex != null) { if (coordIndex.Count > 0) { CoordIndex = coordIndex; } } // Note that obsolete IFC4 files had a "NormalIndex". // We ignore this because we can't actually distinguish between these files. // "PnIndex" is new to IFC4Add2, so we'll protect here in case we see an obsolete file. try { if (IFCImportFile.TheFile.SchemaVersionAtLeast(IFCSchemaVersion.IFC4)) { IList <int> pnIndex = IFCAnyHandleUtil.GetAggregateIntAttribute <List <int> >(ifcTriangulatedFaceSet, "PnIndex"); if (pnIndex != null) { if (pnIndex.Count > 0) { PnIndex = pnIndex; } } } } catch (Exception ex) { if (IFCImportFile.HasUndefinedAttribute(ex)) { IFCImportFile.TheFile.DowngradeIFC4SchemaTo(IFCSchemaVersion.IFC4Add1Obsolete); } else { throw ex; } } }
/// <summary> /// Creates an IFCImportFile from a file on the disk. /// </summary> /// <param name="ifcFilePath">The path of the file.</param> /// <param name="options">The IFC import options.</param> /// <param name="doc">The optional document argument. If importing into Revit, not supplying a document may reduce functionality later.</param> /// <returns>The IFCImportFile.</returns> public static IFCImportFile Create(string ifcFilePath, IFCImportOptions options, Document doc) { m_sIFCImportFile = new IFCImportFile(); bool success = TheFile.Process(ifcFilePath, options, doc); if (success) { // Store the original levels in the template file for Open IFC. On export, we will delete these levels if we created any. // Note that we always have to preserve one level, regardless of what the ActiveView is. // TODO: Only for open, not import. if (doc != null) { IFCBuildingStorey.ExistingLevelIdToReuse = ElementId.InvalidElementId; View activeView = doc.ActiveView; if (activeView != null) { Level genLevel = activeView.GenLevel; if (genLevel != null) { IFCBuildingStorey.ExistingLevelIdToReuse = genLevel.Id; } } FilteredElementCollector levelCollector = new FilteredElementCollector(doc); ICollection <Element> levels = levelCollector.OfClass(typeof(Level)).ToElements(); ICollection <ElementId> levelIdsToDelete = new HashSet <ElementId>(); foreach (Element level in levels) { if (IFCBuildingStorey.ExistingLevelIdToReuse == ElementId.InvalidElementId) { IFCBuildingStorey.ExistingLevelIdToReuse = level.Id; } else if (level.Id != IFCBuildingStorey.ExistingLevelIdToReuse) { levelIdsToDelete.Add(level.Id); } } doc.Delete(levelIdsToDelete); // Collect material names, to avoid reusing. FilteredElementCollector materialCollector = new FilteredElementCollector(doc); ICollection <Element> materials = materialCollector.OfClass(typeof(Material)).ToElements(); foreach (Element materialAsElem in materials) { Material material = materialAsElem as Material; IFCMaterialInfo info = IFCMaterialInfo.Create(material.Color, material.Transparency, material.Shininess, material.Smoothness, material.Id); Importer.TheCache.CreatedMaterials.Add(material.Name, info); } } } else { // Close up the log file, set m_sIFCImportFile to null. TheFile.Close(); } return(m_sIFCImportFile); }
/// <summary> /// Close files at end of import. /// </summary> public void Close() { if (m_IfcFile != null) { m_IfcFile.Close(); } m_sIFCImportFile = null; }
/// <summary> /// Processes an IfcRepresentationItem entity handle. /// </summary> /// <param name="ifcRepresentationItem">The IfcRepresentationItem handle.</param> /// <returns>The IFCRepresentationItem object.</returns> public static IFCRepresentationItem ProcessIFCRepresentationItem(IFCAnyHandle ifcRepresentationItem) { if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcRepresentationItem)) { Importer.TheLog.LogNullError(IFCEntityType.IfcRepresentationItem); return(null); } if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcMappedItem)) { return(IFCMappedItem.ProcessIFCMappedItem(ifcRepresentationItem)); } if (IFCImportFile.TheFile.SchemaVersionAtLeast(IFCSchemaVersion.IFC2x2) && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcStyledItem)) { return(IFCStyledItem.ProcessIFCStyledItem(ifcRepresentationItem)); } if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcTopologicalRepresentationItem)) { return(IFCTopologicalRepresentationItem.ProcessIFCTopologicalRepresentationItem(ifcRepresentationItem)); } // TODO: Move everything below to IFCGeometricRepresentationItem, once it is created. if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcBooleanResult)) { return(IFCBooleanResult.ProcessIFCBooleanResult(ifcRepresentationItem)); } if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcCurve)) { return(IFCCurve.ProcessIFCCurve(ifcRepresentationItem)); } if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcFaceBasedSurfaceModel)) { return(IFCFaceBasedSurfaceModel.ProcessIFCFaceBasedSurfaceModel(ifcRepresentationItem)); } if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcGeometricSet)) { return(IFCGeometricSet.ProcessIFCGeometricSet(ifcRepresentationItem)); } if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcPoint)) { return(IFCPoint.ProcessIFCPoint(ifcRepresentationItem)); } if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcShellBasedSurfaceModel)) { return(IFCShellBasedSurfaceModel.ProcessIFCShellBasedSurfaceModel(ifcRepresentationItem)); } if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcSolidModel)) { return(IFCSolidModel.ProcessIFCSolidModel(ifcRepresentationItem)); } // TODO: Move the items below to IFCGeometricRepresentationItem->IFCTessellatedItem->IfcTessellatedFaceSet. if (IFCImportFile.TheFile.SchemaVersionAtLeast(IFCSchemaVersion.IFC4Obsolete) && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcTriangulatedFaceSet)) { return(IFCTriangulatedFaceSet.ProcessIFCTriangulatedFaceSet(ifcRepresentationItem)); } // There is no way to actually determine an IFC4Add2 file vs. a "vanilla" IFC4 file, which is // obsolete. The try/catch here allows us to read these obsolete files without crashing. try { if (IFCImportFile.TheFile.SchemaVersionAtLeast(IFCSchemaVersion.IFC4) && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcPolygonalFaceSet)) { return(IFCPolygonalFaceSet.ProcessIFCPolygonalFaceSet(ifcRepresentationItem)); } } catch (Exception ex) { // Once we fail once, downgrade the schema so we don't try again. if (IFCImportFile.HasUndefinedAttribute(ex)) { IFCImportFile.TheFile.DowngradeIFC4SchemaTo(IFCSchemaVersion.IFC4Add1Obsolete); } else { throw ex; } } Importer.TheLog.LogUnhandledSubTypeError(ifcRepresentationItem, IFCEntityType.IfcRepresentationItem, true); return(null); }
/// <summary> /// Creates an IFCImportFile from a file on the disk. /// </summary> /// <param name="ifcFilePath">The path of the file.</param> /// <param name="options">The IFC import options.</param> /// <param name="doc">The optional document argument. If importing into Revit, not supplying a document may reduce functionality later.</param> /// <returns>The IFCImportFile.</returns> public static IFCImportFile Create(string ifcFilePath, IFCImportOptions options, Document doc) { m_sIFCImportFile = new IFCImportFile(); bool success = TheFile.Process(ifcFilePath, options, doc); if (success) { // Store the original levels in the template file for Open IFC. On export, we will delete these levels if we created any. // Note that we always have to preserve one level, regardless of what the ActiveView is. if (doc != null) { IFCBuildingStorey.ExistingLevelIdToReuse = ElementId.InvalidElementId; View activeView = doc.ActiveView; if (activeView != null) { Level genLevel = activeView.GenLevel; if (genLevel != null) { IFCBuildingStorey.ExistingLevelIdToReuse = genLevel.Id; } } // For Link IFC, we will delete any unused levels at the end. Instead, we want to try to reuse them. // The for loop does a little unnecessary work if deleteLevelsNow, but the performance implications are very small. bool deleteLevelsNow = (Importer.TheOptions.Action != IFCImportAction.Link); FilteredElementCollector levelCollector = new FilteredElementCollector(doc); ICollection <Element> levels = levelCollector.OfClass(typeof(Level)).ToElements(); ICollection <ElementId> levelIdsToDelete = new HashSet <ElementId>(); foreach (Element level in levels) { if (level == null) { continue; } if (IFCBuildingStorey.ExistingLevelIdToReuse == ElementId.InvalidElementId) { IFCBuildingStorey.ExistingLevelIdToReuse = level.Id; } else if (level.Id != IFCBuildingStorey.ExistingLevelIdToReuse) { levelIdsToDelete.Add(level.Id); } } if (deleteLevelsNow) { doc.Delete(levelIdsToDelete); } // Collect material names, to avoid reusing. FilteredElementCollector materialCollector = new FilteredElementCollector(doc); ICollection <Element> materials = materialCollector.OfClass(typeof(Material)).ToElements(); foreach (Element materialAsElem in materials) { Material material = materialAsElem as Material; IFCMaterialInfo info = IFCMaterialInfo.Create(material.Color, material.Transparency, material.Shininess, material.Smoothness, material.Id); Importer.TheCache.CreatedMaterials.Add(material.Name, info); } } } else { // Close up the log file, set m_sIFCImportFile to null. TheFile.Close(); } return(m_sIFCImportFile); }
/// <summary> /// Close files at end of import. /// </summary> public void Close() { if (m_IfcFile != null) m_IfcFile.Close(); if (m_Log != null) m_Log.Close(); m_sIFCImportFile = null; }
/// <summary> /// Creates an IFCImportFile from a file on the disk. /// </summary> /// <param name="ifcFilePath">The path of the file.</param> /// <param name="options">The IFC import options.</param> /// <param name="doc">The optional document argument. If importing into Revit, not supplying a document may reduce functionality later.</param> /// <returns>The IFCImportFile.</returns> public static IFCImportFile Create(string ifcFilePath, IFCImportOptions options, Document doc) { m_sIFCImportFile = new IFCImportFile(); bool success = TheFile.Process(ifcFilePath, options, doc); if (success) { // Store the original levels in the template file for Open IFC. On export, we will delete these levels if we created any. // Note that we always have to preserve one level, regardless of what the ActiveView is. // TODO: Only for open, not import. if (doc != null) { IFCBuildingStorey.ExistingLevelIdToReuse = ElementId.InvalidElementId; View activeView = doc.ActiveView; if (activeView != null) { Level genLevel = activeView.GenLevel; if (genLevel != null) IFCBuildingStorey.ExistingLevelIdToReuse = genLevel.Id; } FilteredElementCollector levelCollector = new FilteredElementCollector(doc); ICollection<Element> levels = levelCollector.OfClass(typeof(Level)).ToElements(); ICollection<ElementId> levelIdsToDelete = new HashSet<ElementId>(); foreach (Element level in levels) { if (IFCBuildingStorey.ExistingLevelIdToReuse == ElementId.InvalidElementId) IFCBuildingStorey.ExistingLevelIdToReuse = level.Id; else if (level.Id != IFCBuildingStorey.ExistingLevelIdToReuse) levelIdsToDelete.Add(level.Id); } doc.Delete(levelIdsToDelete); // Collect material names, to avoid reusing. FilteredElementCollector materialCollector = new FilteredElementCollector(doc); ICollection<Element> materials = materialCollector.OfClass(typeof(Material)).ToElements(); foreach (Element materialAsElem in materials) { Material material = materialAsElem as Material; IFCMaterialInfo info = IFCMaterialInfo.Create(material.Color, material.Transparency, material.Shininess, material.Smoothness, material.Id); Importer.TheCache.CreatedMaterials.Add(material.Name, info); } } } else { // Close up the log file, set m_sIFCImportFile to null. TheFile.Close(); } return m_sIFCImportFile; }
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); }