/// <summary> /// Finds all related objects in IfcRelAssigns. /// </summary> /// <param name="ifcRelAssigns">The IfcRelAssigns handle.</param> /// <returns>The related objects, or null if not found.</returns> static public ICollection <IFCObjectDefinition> ProcessRelatedObjects(IFCAnyHandle ifcRelAssignsOrAggregates) { try { ValidateIFCRelAssignsOrAggregates(ifcRelAssignsOrAggregates); } catch { //LOG: ERROR: Couldn't find valid IfcRelAssignsToGroup for IfcGroup. return(null); } HashSet <IFCAnyHandle> relatedObjects = IFCAnyHandleUtil.GetAggregateInstanceAttribute <HashSet <IFCAnyHandle> >(ifcRelAssignsOrAggregates, "RelatedObjects"); // Receiving apps need to decide whether to post an error or not. if (relatedObjects == null) { return(null); } ICollection <IFCObjectDefinition> relatedObjectSet = new HashSet <IFCObjectDefinition>(); foreach (IFCAnyHandle relatedObject in relatedObjects) { IFCObjectDefinition objectDefinition = IFCObjectDefinition.ProcessIFCObjectDefinition(relatedObject); if (objectDefinition != null) { relatedObjectSet.Add(objectDefinition); } } return(relatedObjectSet); }
/// <summary> /// Create a custom sub-category name for an entity. /// </summary> /// <param name="entity">The entity.</param> /// <returns>The category name.</returns> /// <remarks>This will also be used to populate the IfcExportAs parameter.</remarks> public static string GetCustomCategoryName(IFCObjectDefinition entity) { IFCEntityType entityType = entity.EntityType; string shapeType = entity.ShapeType; IFCEntityType?typeEntityType = null; string typeShapeType = null; GetAssociatedTypeEntityInfo(entity, out typeEntityType, out typeShapeType); if (typeEntityType.HasValue) { entityType = typeEntityType.Value; } if (string.IsNullOrWhiteSpace(shapeType) && !string.IsNullOrWhiteSpace(typeShapeType)) { shapeType = typeShapeType; } string categoryName = entityType.ToString(); if (!string.IsNullOrWhiteSpace(shapeType)) { categoryName += "." + shapeType; } return(categoryName); }
/// <summary> /// Finds all related objects in IfcRelAssigns. /// </summary> /// <param name="relatedTo">The entity receiving the collection of objects and the IFCObjectDefinition will record the inverse relationship</param> /// <param name="ifcRelAssignsOrAggregates">The IfcRelAssigns handle.</param> /// <returns>The related objects, or null if not found.</returns> static public ICollection <IFCObjectDefinition> ProcessRelatedObjects(IFCObjectDefinition relatedTo, IFCAnyHandle ifcRelAssignsOrAggregates) { try { ValidateIFCRelAssignsOrAggregates(ifcRelAssignsOrAggregates); } catch { //LOG: ERROR: Couldn't find valid IfcRelAssignsToGroup for IfcGroup. return(null); } HashSet <IFCAnyHandle> relatedObjects = IFCAnyHandleUtil.GetAggregateInstanceAttribute <HashSet <IFCAnyHandle> >(ifcRelAssignsOrAggregates, "RelatedObjects"); // Receiving apps need to decide whether to post an error or not. if (relatedObjects == null) { return(null); } ICollection <IFCObjectDefinition> relatedObjectSet = new HashSet <IFCObjectDefinition>(); // If relatedTo is an IFCGroup then it will be added to the list of group that the relatedObject is assigned to. // else it will become the relatedObject's composing object bool relatedIsGroup = relatedTo is IFCGroup; foreach (IFCAnyHandle relatedObject in relatedObjects) { if (relatedObject.Id == relatedTo.Id) { Importer.TheLog.LogError(ifcRelAssignsOrAggregates.Id, "An objected is related to itself, ignoring.", false); continue; } IFCObjectDefinition objectDefinition = IFCObjectDefinition.ProcessIFCObjectDefinition(relatedObject); if (objectDefinition != null) { if (relatedIsGroup) { objectDefinition.AssignmentGroups.Add(relatedTo as IFCGroup); } else { objectDefinition.Decomposes = relatedTo; } relatedObjectSet.Add(objectDefinition); } } return(relatedObjectSet); }
private static bool IsColumnLoadBearing(IFCObjectDefinition entity) { if (entity == null) { throw new InvalidOperationException("Function called for null entity."); } // TODO: Figure out load bearing for IfcColumnType. if (!(entity is IFCObject)) { return(false); } IFCObject columnEntity = entity as IFCObject; IDictionary <string, IFCPropertySetDefinition> columnPropertySets = columnEntity.PropertySets; IFCPropertySetDefinition psetColumnCommonDef = null; if (columnPropertySets == null || (!columnPropertySets.TryGetValue("Pset_ColumnCommon", out psetColumnCommonDef))) { return(false); } if (!(psetColumnCommonDef is IFCPropertySet)) { throw new InvalidOperationException("Invalid Pset_ColumnCommon class."); } IFCPropertySet psetColumnCommon = psetColumnCommonDef as IFCPropertySet; IDictionary <string, IFCProperty> columnCommonProperties = psetColumnCommon.IFCProperties; IFCProperty loadBearingPropertyBase = null; if (columnCommonProperties == null || (!columnCommonProperties.TryGetValue("LoadBearing", out loadBearingPropertyBase))) { return(false); } if (!(loadBearingPropertyBase is IFCSimpleProperty)) { throw new InvalidOperationException("Invalid Pset_ColumnCommon::LoadBearing property."); } IFCSimpleProperty loadBearingProperty = loadBearingPropertyBase as IFCSimpleProperty; IList <IFCPropertyValue> propertyValues = loadBearingProperty.IFCPropertyValues; if (propertyValues == null || propertyValues.Count == 0) { return(false); } return(propertyValues[0].AsBoolean()); }
/// <summary> /// Get the entity type and shape type for the IfcTypeObject of the entity. /// </summary> /// <param name="entity">The entity.</param> /// <param name="typeEntityType">The IfcTypeObject entity type, if it exists.</param> /// <param name="typeShapeType">The IfcTypeObject shape type, if it exists.</param> private static void GetAssociatedTypeEntityInfo(IFCObjectDefinition entity, out IFCEntityType?typeEntityType, out string typeShapeType) { typeEntityType = null; typeShapeType = null; if (entity is IFCObject) { IFCObject ifcObject = entity as IFCObject; if (ifcObject.TypeObjects != null && ifcObject.TypeObjects.Count > 0) { IFCTypeObject typeObject = ifcObject.TypeObjects.First(); typeEntityType = typeObject.EntityType; typeShapeType = typeObject.ShapeType; } } }
/// <summary> /// Keep track of elements that have been created, for later summary count. /// </summary> /// <param name="doc">The document.</param> /// <param name="objDef">The created entity.</param> public void AddCreatedEntity(Document doc, IFCObjectDefinition objDef) { if (objDef == null) { return; } ISet <ElementId> createdElementIds = new HashSet <ElementId>(); objDef.GetCreatedElementIds(createdElementIds); foreach (ElementId createdElementId in createdElementIds) { Element createdElement = doc.GetElement(createdElementId); if (createdElement == null) { continue; } Category elementCategory = createdElement.Category; string catName = (elementCategory == null) ? "" : elementCategory.Name; string typeName = createdElement.GetType().Name; CreatedElementsKey mapKey = new CreatedElementsKey(catName, typeName); if (m_CreatedElements.ContainsKey(mapKey)) { m_CreatedElements[mapKey]++; } else { m_CreatedElements.Add(new KeyValuePair <CreatedElementsKey, int>(mapKey, 1)); } m_TotalCreatedElements++; UpdateStatusBarAfterCreate(); } }
/// <summary> /// Import an IFC file into a given document for Reference only. /// </summary> /// <param name="document">The host document for the import.</param> /// <param name="origFullFileName">The full file name of the document.</param> /// <param name="options">The list of configurable options for this import.</param> public void ReferenceIFC(Document document, string origFullFileName, IDictionary <String, String> options) { // We need to generate a local file name for all of the intermediate files (the log file, the cache file, and the shared parameters file). string localFileName = ImporterIFCUtils.GetLocalFileName(document, origFullFileName); if (localFileName == null) { throw new InvalidOperationException("Could not generate local file name for: " + origFullFileName); } // An early check, based on the options set - if we are allowed to use an up-to-date existing file on disk, use it. // It is possible that the log file may have been created in CreateImporter above, // if it is used by an external developer. if (TheLog == null) { m_ImportLog = IFCImportLog.CreateLog(localFileName, "log.html", !m_ImportOptions.DisableLogging); } Document originalDocument = document; Document ifcDocument = null; if (TheOptions.Action == IFCImportAction.Link) { string linkedFileName = IFCImportFile.GetRevitFileName(localFileName); ifcDocument = LoadOrCreateLinkDocument(originalDocument, linkedFileName); } else { ifcDocument = originalDocument; } bool useCachedRevitFile = DocumentUpToDate(ifcDocument, localFileName); // In the case where the document is already opened as a link, but it has been updated on disk, // give the user a warning and use the cached value. if (!useCachedRevitFile && ifcDocument.IsLinked) { useCachedRevitFile = true; Importer.AddDelayedLinkError(BuiltInFailures.ImportFailures.IFCCantUpdateLinkedFile); } if (!useCachedRevitFile) { m_ImportCache = IFCImportCache.Create(ifcDocument, localFileName); // Limit creating the cache to Link, but may either remove limiting or make it more restrict (reload only) later. if (TheOptions.Action == IFCImportAction.Link) { TheCache.CreateExistingElementMaps(ifcDocument); } // TheFile will contain the same value as the return value for this function. IFCImportFile.Create(localFileName, m_ImportOptions, ifcDocument); } if (useCachedRevitFile || IFCImportFile.TheFile != null) { IFCImportFile theFile = IFCImportFile.TheFile; if (theFile != null) { if (theFile.IFCProject != null) { IFCObjectDefinition.CreateElement(ifcDocument, theFile.IFCProject); } // Also process any other entities to create. foreach (IFCObjectDefinition objDef in IFCImportFile.TheFile.OtherEntitiesToCreate) { IFCObjectDefinition.CreateElement(ifcDocument, objDef); } theFile.EndImport(ifcDocument, localFileName); } if (TheOptions.Action == IFCImportAction.Link) { // If we have an original Revit link file name, don't create a new RevitLinkType - // we will use the existing one. bool useExistingType = (TheOptions.RevitLinkFileName != null); ElementId revitLinkTypeId = IFCImportFile.LinkInFile(origFullFileName, localFileName, ifcDocument, originalDocument, useExistingType, !useCachedRevitFile); } } if (m_ImportCache != null) { m_ImportCache.Reset(ifcDocument); } }
/// <summary> /// Import an IFC file into a given document for Reference only. /// </summary> /// <param name="document">The host document for the import.</param> /// <param name="fullFileName">The full file name of the document.</param> /// <param name="options">The list of configurable options for this import.</param> public void ReferenceIFC(Document document, string fullFileName, IDictionary <String, String> options) { // An early check, based on the options set - if we are allowed to use an up-to-date existing file on disk, use it. m_ImportLog = IFCImportLog.CreateLog(fullFileName, "log.html"); Document originalDocument = document; Document ifcDocument = null; if (TheOptions.Action == IFCImportAction.Link) { string linkedFileName = IFCImportFile.GetRevitFileName(fullFileName); ifcDocument = LoadOrCreateLinkDocument(originalDocument, linkedFileName); if (ifcDocument == null) { return; } } else { ifcDocument = originalDocument; } bool useCachedRevitFile = DocumentUpToDate(ifcDocument, fullFileName); // In the case where the document is already opened as a link, but it has been updated on disk, // give the user a warning and use the cached value. if (!useCachedRevitFile && ifcDocument.IsLinked) { useCachedRevitFile = true; Importer.AddDelayedLinkError(BuiltInFailures.ImportFailures.IFCCantUpdateLinkedFile); } if (!useCachedRevitFile) { m_ImportCache = IFCImportCache.Create(ifcDocument, fullFileName); // Limit creating the cache to Link, but may either remove limiting or make it more restrict (reload only) later. if (TheOptions.Action == IFCImportAction.Link) { TheCache.CreateExistingElementMaps(ifcDocument); } // TheFile will contain the same value as the return value for this function. IFCImportFile.Create(fullFileName, m_ImportOptions, ifcDocument); } if (useCachedRevitFile || IFCImportFile.TheFile != null) { IFCImportFile theFile = IFCImportFile.TheFile; if (theFile != null) { if (theFile.IFCProject != null) { IFCObjectDefinition.CreateElement(ifcDocument, theFile.IFCProject); } // Also process any other entities to create. foreach (IFCObjectDefinition objDef in IFCImportFile.TheFile.OtherEntitiesToCreate) { IFCObjectDefinition.CreateElement(ifcDocument, objDef); } theFile.EndImport(ifcDocument, fullFileName); } if (TheOptions.Action == IFCImportAction.Link) { // If we have an original Revit link file name, don't create a new RevitLinkType - // we will use the existing one. bool useExistingType = (TheOptions.RevitLinkFileName != null); ElementId revitLinkTypeId = IFCImportFile.LinkInFile(fullFileName, ifcDocument, originalDocument, useExistingType, !useCachedRevitFile); } } if (m_ImportCache != null) { m_ImportCache.Reset(ifcDocument); } }
/// <summary> /// Get the top-level Built-in category id for an IFC entity. /// </summary> /// <param name="doc">The doument.</param> /// <param name="entity">The entity.</param> /// <param name="gstyleId">The graphics style, if the returned category is not top level. This allows shapes to have their visibility controlled by the sub-category.</param> /// <returns>The element id for the built-in category.</returns> public static ElementId GetCategoryIdForEntity(Document doc, IFCObjectDefinition entity, out ElementId gstyleId) { gstyleId = ElementId.InvalidElementId; IFCEntityType entityType = entity.EntityType; IFCEntityType?typeEntityType = null; string typeShapeType = null; GetAssociatedTypeEntityInfo(entity, out typeEntityType, out typeShapeType); // Use the IfcTypeObject shape type if the IfcElement shape type is either null, empty, white space, or not defined. string shapeType = entity.ShapeType; if ((string.IsNullOrWhiteSpace(shapeType) || (string.Compare(shapeType, "NOTDEFINED", true) == 0)) && !string.IsNullOrWhiteSpace(typeShapeType)) { shapeType = typeShapeType; } // Set "special" shape types switch (entityType) { case IFCEntityType.IfcColumn: case IFCEntityType.IfcColumnType: if (IsColumnLoadBearing(entity)) { shapeType = "[LoadBearing]"; } break; } ElementId catElemId = GetCategoryElementId(entityType, shapeType); // If we didn't find a category, or if we found the generic model category, try again with the IfcTypeObject, if there is one. if (catElemId == ElementId.InvalidElementId || catElemId.IntegerValue == (int)BuiltInCategory.OST_GenericModel) { if (typeEntityType.HasValue) { catElemId = GetCategoryElementId(typeEntityType.Value, shapeType); } } Category subCategory = null; if (catElemId.IntegerValue == (int)BuiltInCategory.OST_GenericModel) { string subCategoryName = GetCustomCategoryName(entity); if (!string.IsNullOrWhiteSpace(subCategoryName)) { IDictionary <string, Category> createdSubcategories = Importer.TheCache.CreatedSubcategories; if (!createdSubcategories.TryGetValue(subCategoryName, out subCategory)) { // Category may have been created by a previous action (probably a previous import). Look first. try { CategoryNameMap subCategories = Importer.TheCache.GenericModelsCategory.SubCategories; subCategory = subCategories.get_Item(subCategoryName); } catch { subCategory = null; } if (subCategory == null) { subCategory = Importer.TheCache.DocumentCategories.NewSubcategory(Importer.TheCache.GenericModelsCategory, subCategoryName); SetMaterialForSpacesAndOpenings(doc, entity.Id, subCategory, subCategoryName); } createdSubcategories[subCategoryName] = subCategory; } GraphicsStyle graphicsStyle = subCategory.GetGraphicsStyle(GraphicsStyleType.Projection); if (graphicsStyle != null) { gstyleId = graphicsStyle.Id; } } } else if (catElemId == ElementId.InvalidElementId) { catElemId = new ElementId(BuiltInCategory.OST_GenericModel); // Top level entities that are OK to be here. if (entityType != IFCEntityType.IfcProject && entityType != IFCEntityType.IfcBuilding && entityType != IFCEntityType.IfcBuildingStorey && entityType != IFCEntityType.IfcElementAssembly) { string msg = "Setting IFC entity "; if (string.IsNullOrWhiteSpace(shapeType)) { msg = entityType.ToString(); } else { msg = entityType.ToString() + "." + shapeType; } if (typeEntityType.HasValue) { msg += " (" + typeEntityType.Value.ToString() + ")"; } msg += " to Generic Models."; IFCImportFile.TheLog.LogWarning(entity.Id, msg, true); } } Category categoryToCheck = null; if (catElemId.IntegerValue < 0) { categoryToCheck = Importer.TheCache.DocumentCategories.get_Item((BuiltInCategory)catElemId.IntegerValue); } else { categoryToCheck = subCategory; } if (categoryToCheck != null) { // We'll assume that a negative value means a built-in category. It may still be a sub-category, in which case we need to get the parent category and assign the gstyle. // We could optimize this, but this is safer. Category parentCategory = categoryToCheck.Parent; if (parentCategory != null) { catElemId = parentCategory.Id; } // Not already set by subcategory. if (gstyleId == ElementId.InvalidElementId) { GraphicsStyle graphicsStyle = categoryToCheck.GetGraphicsStyle(GraphicsStyleType.Projection); if (graphicsStyle != null) { gstyleId = graphicsStyle.Id; } } } return(catElemId); }
public void ImportIFC(ImporterIFC importer) { TheImporter = this; IDictionary <String, String> options = importer.GetOptions(); TheOptions = m_ImportOptions = IFCImportOptions.Create(options); // An early check, based on the options set - if we are allowed to use an up-to-date existing file on disk, use it. try { string revitFileName = IFCImportFile.GetRevitFileName(importer.FullFileName); if (!TheOptions.ForceImport && !NeedsReload(importer.FullFileName, revitFileName)) { return; } // Clear the category mapping table, to force reload of options. IFCCategoryUtil.Clear(); if (TheOptions.Intent != IFCImportIntent.Reference) { IFCImportFile.Import(importer); } else { Document originalDocument = importer.Document; Document ifcDocument = null; if (TheOptions.Action == IFCImportAction.Link) { string linkedFileName = IFCImportFile.GetRevitFileName(importer.FullFileName); ifcDocument = LoadOrCreateLinkDocument(originalDocument, linkedFileName); if (ifcDocument == null) { return; } } else { ifcDocument = originalDocument; } bool useCachedRevitFile = DocumentUpToDate(ifcDocument, importer.FullFileName); // In the case where the document is already opened as a link, but it has been updated on disk, // give the user a warning and use the cached value. if (!useCachedRevitFile && ifcDocument.IsLinked) { useCachedRevitFile = true; Importer.AddDelayedLinkError(BuiltInFailures.ImportFailures.IFCCantUpdateLinkedFile); } if (!useCachedRevitFile) { m_ImportCache = IFCImportCache.Create(ifcDocument, importer.FullFileName); // Limit creating the cache to Link, but may either remove limiting or make it more restrict (reload only) later. if (TheOptions.Action == IFCImportAction.Link) { TheCache.CreateExistingElementMaps(ifcDocument); } // TheFile will contain the same value as the return value for this function. IFCImportFile.Create(importer.FullFileName, m_ImportOptions, ifcDocument); } if (useCachedRevitFile || IFCImportFile.TheFile != null) { if (IFCImportFile.TheFile != null) { if (IFCImportFile.TheFile.IFCProject != null) { IFCObjectDefinition.CreateElement(ifcDocument, IFCImportFile.TheFile.IFCProject); } IFCImportFile.TheFile.EndImport(ifcDocument, importer.FullFileName); } if (TheOptions.Action == IFCImportAction.Link) { // If we have an original Revit link file name, don't create a new RvtLinkSymbol - // we will use the existing one. bool useExistingType = (TheOptions.RevitLinkFileName != null); IFCImportFile.LinkInFile(importer.FullFileName, ifcDocument, originalDocument, useExistingType, !useCachedRevitFile); } } m_ImportCache.Reset(ifcDocument); } } catch (Exception ex) { if (IFCImportFile.TheFile != null) { IFCImportFile.TheFile.Log.LogError(-1, ex.Message, false); } } finally { if (IFCImportFile.TheFile != null) { IFCImportFile.TheFile.Close(); } } }