private IList <GeometryObject> GetOrCloneGeometry(Document doc, IFCObjectDefinition objectDefinition) { if (!(objectDefinition is IFCBuildingElementPart)) { return(objectDefinition.CreatedGeometry); } // In the case of IFCBuildingElementPart, we want the container to have a copy of the geometry in the category of the parent, // as otherwise the geometry will be controlled by default by the Parts category instead of the parent category. IList <IFCSolidInfo> clonedGeometry = IFCElement.CloneElementGeometry(doc, objectDefinition as IFCProduct, this, false); if (clonedGeometry == null) { return(null); } IList <GeometryObject> geomObjs = new List <GeometryObject>(); foreach (IFCSolidInfo solid in clonedGeometry) { geomObjs.Add(solid.GeometryObject); } return(geomObjs); }
/// <summary> /// Add a double parameter to an element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element.</param> /// <param name="category">The category of the element.</param> /// <param name="parameterName">The parameter name.</param> /// <param name="specTypeId">Identifier of the parameter spec (e.g. length)</param> /// <param name="unitsTypeId">Identifier of the unscaled parameter units (e.g. mm)</param> /// <param name="parameterValue">The parameter value, scaled into document units.</param> /// <param name="parameterSetId">The id of the containing parameter set, for reporting errors.</param> /// <returns>True if the parameter was successfully added, false otherwise.</returns> public static bool AddParameterDouble(Document doc, Element element, Category category, IFCObjectDefinition objDef, string parameterName, ForgeTypeId specTypeId, ForgeTypeId unitsTypeId, double parameterValue, int parameterSetId) { if (doc == null || element == null || category == null) { return(false); } unitsTypeId = CalculateUnitsTypeId(unitsTypeId, specTypeId); bool?processedParameter = Importer.TheProcessor.ProcessParameter(objDef.Id, specTypeId, unitsTypeId, parameterSetId, parameterName, parameterValue); if (processedParameter.HasValue) { return(processedParameter.Value); } Parameter parameter = AddParameterBase(doc, element, category, parameterName, parameterSetId, specTypeId); if (parameter == null) { return(false); } parameter.Set(parameterValue); return(true); }
/// <summary> /// Create one or more elements /// </summary> /// <param name="doc">The document being populated.</param> /// <returns>The primary element associated with the IFCObjectDefinition, or InvalidElementId if it failed.</returns> public static ElementId CreateElement(Document doc, IFCObjectDefinition objDef) { // This would be a good place to check 'objDef.GlobalId'. ElementId createdElementId = objDef.CreatedElementId; try { if ((createdElementId == ElementId.InvalidElementId) && objDef.IsValidForCreation) { ElementId gstyleId; objDef.CategoryId = IFCCategoryUtil.GetCategoryIdForEntity(doc, objDef, out gstyleId); objDef.m_GraphicsStyleId = gstyleId; if (objDef is IFCObject) { IFCObject asObject = objDef as IFCObject; foreach (IFCTypeObject typeObject in asObject.TypeObjects) { IFCObjectDefinition.CreateElement(doc, typeObject); } } objDef.Create(doc); objDef.CreateParameters(doc); createdElementId = objDef.CreatedElementId; IFCImportFile.TheLog.AddCreatedEntity(doc, objDef); if (IFCImportFile.CleanEntitiesAfterCreate) { objDef.CleanEntity(); } } } catch (Exception ex) { if (objDef != null) { objDef.IsValidForCreation = false; IFCImportFile.TheLog.LogCreationError(objDef, ex.Message, false); } } return(createdElementId); }
/// <summary> /// Add a string parameter to an element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element.</param> /// <param name="objDef">The IFCObjectDefinition that created the element.</param> /// <param name="name">The enum corresponding to the parameter name.</param> /// <param name="parameterValue">The parameter value.</param> /// <param name="parameterSetId">The id of the containing parameter set, for reporting errors.</param> /// <returns>True if the parameter was successfully added, false otherwise.</returns> public static bool AddParameterString(Document doc, Element element, IFCObjectDefinition objDef, IFCSharedParameters name, string parameterValue, int parameterSetId) { if (objDef == null) { return(false); } string parameterName = objDef.GetSharedParameterName(name); Parameter parameter = AddParameterBase(doc, element, parameterName, parameterSetId, ParameterType.Text); if (parameter == null) { return(false); } parameter.Set(parameterValue); return(true); }
/// <summary> /// Creates or populates Revit elements based on the information contained in this class. /// </summary> /// <param name="doc">The document.</param> protected virtual void TraverseSubElements(Document doc) { IList <ElementId> subElementIds = new List <ElementId>(); if (ComposedObjectDefinitions != null) { foreach (IFCObjectDefinition objectDefinition in ComposedObjectDefinitions) { IFCObjectDefinition.CreateElement(doc, objectDefinition); if (objectDefinition.CreatedElementId != ElementId.InvalidElementId) { subElementIds.Add(objectDefinition.CreatedElementId); } } } if (GroupSubElements()) { if (subElementIds.Count > 0) { if (CreatedElementId != ElementId.InvalidElementId) { subElementIds.Add(CreatedElementId); } // We aren't yet actually grouping the elements. DirectShape doesn't support grouping, and // the Group element doesn't support adding parameters. For now, we will create a DirectShape that "forgets" // the association, which is good enough for link. DirectShape directShape = IFCElementUtil.CreateElement(doc, CategoryId, Importer.ImportAppGUID(), GlobalId); //Group group = doc.Create.NewGroup(subElementIds); if (directShape != null) { CreatedElementId = directShape.Id; } else { IFCImportFile.TheLog.LogCreationError(this, null, false); } } } }
/// <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) { 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; }
/// <summary> /// Create a property set for a given element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element being created.</param> /// <param name="parameterGroupMap">The parameters of the element. Cached for performance.</param> /// <returns>The name of the property set created, if it was created, and a Boolean value if it should be added to the property set list.</returns> public override Tuple <string, bool> CreatePropertySet(Document doc, Element element, IFCObjectDefinition objDef, IFCParameterSetByGroup parameterGroupMap) { IDictionary <string, IFCData> parametersToAdd = new Dictionary <string, IFCData>(); Category category = IFCPropertySet.GetCategoryForParameterIfValid(element, Id); foreach (KeyValuePair <Tuple <string, ForgeTypeId, AllowedValues>, double> property in DoubleProperties) { string name = property.Key.Item1; Parameter existingParameter = null; if (!parameterGroupMap.TryFindParameter(name, out existingParameter)) { ForgeTypeId valueType = property.Key.Item2; // If we aren't scaling values, all length values have come from Attributes // and so will always be in feet. ForgeTypeId unitType = (!Importer.TheProcessor.ScaleValues && valueType == SpecTypeId.Length) ? UnitTypeId.Feet : null; IFCPropertySet.AddParameterDouble(doc, element, category, objDef, name, valueType, unitType, property.Value, Id); continue; } switch (existingParameter.StorageType) { case StorageType.String: existingParameter.Set(property.Value.ToString()); break; case StorageType.Double: existingParameter.Set(property.Value); break; default: Importer.TheLog.LogError(Id, "couldn't create parameter: " + name + " of storage type: " + existingParameter.StorageType.ToString(), false); break; } } foreach (KeyValuePair <string, string> property in StringProperties) { string name = property.Key; Parameter existingParameter = null; if (!parameterGroupMap.TryFindParameter(name, out existingParameter)) { IFCPropertySet.AddParameterString(doc, element, category, objDef, property.Key, property.Value, Id); continue; } switch (existingParameter.StorageType) { case StorageType.String: existingParameter.Set(property.Value); break; default: Importer.TheLog.LogError(Id, "couldn't create parameter: " + name + " of storage type: " + existingParameter.StorageType.ToString(), false); break; } } return(Tuple.Create("\"" + EntityType.ToString() + "\"", false)); }
/// <summary> /// Create a quantity for a given element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element being created.</param> /// <param name="category">The element's category.</param> /// <param name="parameterMap">The parameters of the element. Cached for performance.</param> /// <param name="propertySetName">The name of the containing property set.</param> /// <param name="createdParameters">The names of the created parameters.</param> public override void Create(Document doc, Element element, Category category, IFCObjectDefinition objDef, IFCParameterSetByGroup parameterGroupMap, string propertySetName, ISet <string> createdParameters) { double baseValue = 0.0; IFCDataPrimitiveType type = Value.PrimitiveType; switch (type) { case IFCDataPrimitiveType.Double: baseValue = Value.AsDouble(); break; case IFCDataPrimitiveType.Integer: // This case isn't valid, but could happen when repairing a file Importer.TheLog.LogWarning(Id, "Unexpected integer parameter type, repairing.", false); baseValue = Value.AsInteger(); break; default: Importer.TheLog.LogError(Id, "Invalid parameter type: " + type.ToString() + " for IfcPhysicalSimpleQuantity", false); return; } double doubleValueToUse = Importer.TheProcessor.ScaleValues ? IFCUnit?.Convert(baseValue) ?? baseValue : baseValue; Parameter existingParameter = null; string originalParameterName = propertySetName + "." + Name; string parameterName = originalParameterName; if (!parameterGroupMap.TryFindParameter(parameterName, out existingParameter)) { int parameterNameCount = 2; while (createdParameters.Contains(parameterName)) { parameterName = originalParameterName + " " + parameterNameCount; parameterNameCount++; } if (parameterNameCount > 2) { Importer.TheLog.LogWarning(Id, "Renamed parameter: " + originalParameterName + " to: " + parameterName, false); } if (existingParameter == null) { ForgeTypeId specTypeId; ForgeTypeId unitsTypeId = null; if (IFCUnit != null) { specTypeId = IFCUnit.Spec; unitsTypeId = IFCUnit.Unit; } else { specTypeId = IFCDataUtil.GetUnitTypeFromData(Value, SpecTypeId.Number); } bool created = IFCPropertySet.AddParameterDouble(doc, element, category, objDef, parameterName, specTypeId, unitsTypeId, doubleValueToUse, Id); if (created) { createdParameters.Add(parameterName); } return; } } bool setValue = true; switch (existingParameter.StorageType) { case StorageType.String: existingParameter.Set(doubleValueToUse.ToString()); break; case StorageType.Double: existingParameter.Set(doubleValueToUse); break; default: setValue = false; break; } if (!setValue) { Importer.TheLog.LogError(Id, "Couldn't create parameter: " + Name + " of storage type: " + existingParameter.StorageType.ToString(), false); } }
/// <summary> /// Creates or populates Revit elements based on the information contained in this class. /// </summary> /// <param name="doc">The document.</param> protected virtual void TraverseSubElements(Document doc) { IList <ElementId> subElementIds = new List <ElementId>(); // These two should only be populated if GroupSubElements() is true and we are duplicating geometry for containers. List <GeometryObject> groupedSubElementGeometries = new List <GeometryObject>(); List <Curve> groupedSubElementFootprintCurves = new List <Curve>(); if (ComposedObjectDefinitions != null) { foreach (IFCObjectDefinition objectDefinition in ComposedObjectDefinitions) { IFCObjectDefinition.CreateElement(doc, objectDefinition); if (objectDefinition.CreatedElementId != ElementId.InvalidElementId) { subElementIds.Add(objectDefinition.CreatedElementId); // CreateDuplicateContainerGeometry is currently an API-only option (no UI), set to true by default. if (GroupSubElements() && Importer.TheOptions.CreateDuplicateContainerGeometry) { IList <GeometryObject> subGeometries = GetOrCloneGeometry(doc, objectDefinition); if (subGeometries != null) { groupedSubElementGeometries.AddRange(subGeometries); } if (objectDefinition is IFCProduct) { groupedSubElementFootprintCurves.AddRange((objectDefinition as IFCProduct).FootprintCurves); } } } } } if (GroupSubElements()) { if (subElementIds.Count > 0) { if (CreatedElementId != ElementId.InvalidElementId) { subElementIds.Add(CreatedElementId); } // We aren't yet actually grouping the elements. DirectShape doesn't support grouping, and // the Group element doesn't support adding parameters. For now, we will create a DirectShape that "forgets" // the association, which is good enough for link. DirectShape directShape = IFCElementUtil.CreateElement(doc, CategoryId, GlobalId, groupedSubElementGeometries); //Group group = doc.Create.NewGroup(subElementIds); if (directShape != null) { CreatedElementId = directShape.Id; CreatedGeometry = groupedSubElementGeometries; if (groupedSubElementFootprintCurves.Count != 0 && this is IFCProduct) { using (IFCImportShapeEditScope planViewScope = IFCImportShapeEditScope.Create(doc, this as IFCProduct)) { planViewScope.AddPlanViewCurves(groupedSubElementFootprintCurves, Id); planViewScope.SetPlanViewRep(directShape); } } } else { Importer.TheLog.LogCreationError(this, null, false); } } } }
/// <summary> /// Create a copying of the geometry of an entity with a different graphics style. /// </summary> /// <param name="doc">The document.</param> /// <param name="original">The IFCProduct we are partially copying.</param> /// <param name="parentEntity">The IFCObjectDefinition we are going to add the geometry to.</param> /// <param name="cloneParentMaterial">Determine whether to use the one material of the parent entity, if it exists and is unique.</param> /// <returns>The list of geometries created with a new category and possibly material.</returns> public static IList<IFCSolidInfo> CloneElementGeometry(Document doc, IFCProduct original, IFCObjectDefinition parentEntity, bool cloneParentMaterial) { using (TemporaryDisableLogging disableLogging = new TemporaryDisableLogging()) { IFCElement clone = new IFCElement(); // Note that the GlobalId is left to null here; this allows us to later decide not to create a DirectShape for the result. // Get the ObjectLocation and ProductRepresentation from the original entity, which is all we need to create geometry. clone.ObjectLocation = original.ObjectLocation; clone.ProductRepresentation = original.ProductRepresentation; clone.MaterialSelect = original.MaterialSelect; // Get the EntityType and PredefinedType from the parent to ensure that it "matches" the category and graphics style of the parent. clone.EntityType = parentEntity.EntityType; clone.PredefinedType = parentEntity.PredefinedType; if (cloneParentMaterial) { // This will only work if the parent entity has one material. IFCMaterial parentMaterial = parentEntity.GetTheMaterial(); if (parentMaterial != null) clone.MaterialSelect = parentMaterial; } IList<GeometryObject> geomObjs = new List<GeometryObject>(); CreateElement(doc, clone); return clone.Solids; } }
/// <summary> /// Create a copying of the geometry of an entity with a different graphics style. /// </summary> /// <param name="doc">The document.</param> /// <param name="original">The IFCProduct we are partially copying.</param> /// <param name="parentEntity">The IFCObjectDefinition we are going to add the geometry to.</param> /// <param name="cloneParentMaterial">Determine whether to use the one material of the parent entity, if it exists and is unique.</param> /// <returns>The list of geometries created with a new category and possibly material.</returns> public static IList <IFCSolidInfo> CloneElementGeometry(Document doc, IFCProduct original, IFCObjectDefinition parentEntity, bool cloneParentMaterial) { using (TemporaryDisableLogging disableLogging = new TemporaryDisableLogging()) { IFCElement clone = new IFCElement(); // Note that the GlobalId is left to null here; this allows us to later decide not to create a DirectShape for the result. // Get the ObjectLocation and ProductRepresentation from the original entity, which is all we need to create geometry. clone.ObjectLocation = original.ObjectLocation; clone.ProductRepresentation = original.ProductRepresentation; clone.MaterialSelect = original.MaterialSelect; // Get the EntityType and PredefinedType from the parent to ensure that it "matches" the category and graphics style of the parent. clone.EntityType = parentEntity.EntityType; clone.PredefinedType = parentEntity.PredefinedType; if (cloneParentMaterial) { // This will only work if the parent entity has one material. IFCMaterial parentMaterial = parentEntity.GetTheMaterial(); if (parentMaterial != null) { clone.MaterialSelect = parentMaterial; } } IList <GeometryObject> geomObjs = new List <GeometryObject>(); CreateElement(doc, clone); return(clone.Solids); } }
/// <summary> /// Get the entity type and predefined 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="typePredefinedType">The IfcTypeObject predefined type, if it exists.</param> private static void GetAssociatedTypeEntityInfo(IFCObjectDefinition entity, out IFCEntityType? typeEntityType, out string typePredefinedType) { typeEntityType = null; typePredefinedType = 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; typePredefinedType = typeObject.PredefinedType; } } }
/// <summary> /// Create quantities for a given element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element being created.</param> /// <param name="parameterGroupMap">The parameters of the element. Cached for performance.</param> /// <returns>The name of the property set created, if it was created, and a Boolean value if it should be added to the property set list.</returns> public override Tuple <string, bool> CreatePropertySet(Document doc, Element element, IFCObjectDefinition objDef, IFCParameterSetByGroup parameterGroupMap) { Category category = IFCPropertySet.GetCategoryForParameterIfValid(element, Id); string quotedName = "\"" + Name + "\""; ISet <string> parametersCreated = new HashSet <string>(); foreach (IFCPhysicalQuantity quantity in IFCQuantities.Values) { quantity.Create(doc, element, category, objDef, parameterGroupMap, Name, parametersCreated); } return(Tuple.Create(quotedName, true)); }
private IList<GeometryObject> GetOrCloneGeometry(Document doc, IFCObjectDefinition objectDefinition) { if (!(objectDefinition is IFCBuildingElementPart)) return objectDefinition.CreatedGeometry; // In the case of IFCBuildingElementPart, we want the container to have a copy of the geometry in the category of the parent, // as otherwise the geometry will be controlled by default by the Parts category instead of the parent category. IList<IFCSolidInfo> clonedGeometry = IFCElement.CloneElementGeometry(doc, objectDefinition as IFCProduct, this, false); if (clonedGeometry == null) return null; IList<GeometryObject> geomObjs = new List<GeometryObject>(); foreach (IFCSolidInfo solid in clonedGeometry) { geomObjs.Add(solid.GeometryObject); } return geomObjs; }
/// <summary> /// Add an int parameter to an element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element.</param> /// <param name="category">The category of the element.</param> /// <param name="parameterName">The parameter name.</param> /// <param name="parameterValue">The parameter value.</param> /// <param name="parameterSetId">The id of the containing parameter set, for reporting errors.</param> /// <returns>True if the parameter was successfully added, false otherwise.</returns> public static bool AddParameterInt(Document doc, Element element, Category category, IFCObjectDefinition objDef, string parameterName, int parameterValue, int parameterSetId) { if (doc == null || element == null || category == null) { return(false); } bool?processedParameter = Importer.TheProcessor.ProcessParameter(objDef.Id, parameterSetId, parameterName, parameterValue); if (processedParameter.HasValue) { return(processedParameter.Value); } Parameter parameter = AddParameterBase(doc, element, category, parameterName, parameterSetId, SpecTypeId.Int.Integer); if (parameter == null) { return(false); } parameter.Set(parameterValue); return(true); }
/// <summary> /// Adds a parameter with the name of an element represented by an ElementId to an element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element.</param> /// <param name="category">The category of the element.</param> /// <param name="parameterName">The parameter name.</param> /// <param name="parameterValue">The parameter value.</param> /// <param name="parameterSetId">The id of the containing parameter set, for reporting errors.</param> /// <returns>True if the parameter was successfully added, false otherwise.</returns> public static bool AddParameterElementId(Document doc, Element element, Category category, IFCObjectDefinition objDef, string parameterName, ElementId parameterValue, int parameterSetId) { if (doc == null || element == null || category == null) { return(false); } Element parameterElement = doc.GetElement(parameterValue); if (parameterElement == null) { return(false); } string name = parameterElement.Name; if (string.IsNullOrEmpty(name)) { return(false); } bool?processedParameter = Importer.TheProcessor.ProcessParameter(objDef.Id, parameterSetId, parameterName, parameterValue); if (processedParameter.HasValue) { return(processedParameter.Value); } Parameter parameter = AddParameterBase(doc, element, category, parameterName, parameterSetId, SpecTypeId.String.Text); if (parameter == null) { return(false); } parameter.Set(name); return(true); }
/// <summary> /// Create a property set for a given element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element being created.</param> /// <param name="parameterGroupMap">The parameters of the element. Cached for performance.</param> /// <returns>The name of the property set created, if it was created, and a Boolean value if it should be added to the property set list.</returns> public virtual Tuple <string, bool> CreatePropertySet(Document doc, Element element, IFCObjectDefinition objDef, IFCParameterSetByGroup parameterGroupMap) { return(new Tuple <string, bool>(null, false)); }
/// <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 typePredefinedType = null; GetAssociatedTypeEntityInfo(entity, out typeEntityType, out typePredefinedType); // Use the IfcTypeObject predefined type if the IfcElement predefined type is either null, empty, white space, or not defined. string predefinedType = entity.PredefinedType; if ((string.IsNullOrWhiteSpace(predefinedType) || (string.Compare(predefinedType, "NOTDEFINED", true) == 0)) && !string.IsNullOrWhiteSpace(typePredefinedType)) predefinedType = typePredefinedType; // Set "special" predefined types switch (entityType) { case IFCEntityType.IfcColumn: case IFCEntityType.IfcColumnType: if (IsColumnLoadBearing(entity)) predefinedType = "[LoadBearing]"; break; } ElementId catElemId = GetCategoryElementId(entityType, predefinedType); // 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, predefinedType); } Category subCategory = null; if (catElemId.IntegerValue == (int)BuiltInCategory.OST_GenericModel) { string subCategoryName = GetCustomCategoryName(entity); subCategory = GetOrCreateSubcategory(doc, entity.Id, subCategoryName); if (subCategory != null) { 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 && entityType != IFCEntityType.IfcSystem) { string msg = "Setting IFC entity "; if (string.IsNullOrWhiteSpace(predefinedType)) msg = entityType.ToString(); else msg = entityType.ToString() + "." + predefinedType; if (typeEntityType.HasValue) msg += " (" + typeEntityType.Value.ToString() + ")"; msg += " to Generic Models."; Importer.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; }
/// <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 predefinedType = entity.PredefinedType; IFCEntityType? typeEntityType = null; string typePredefinedType = null; GetAssociatedTypeEntityInfo(entity, out typeEntityType, out typePredefinedType); if (typeEntityType.HasValue) entityType = typeEntityType.Value; if (string.IsNullOrWhiteSpace(predefinedType) && !string.IsNullOrWhiteSpace(typePredefinedType)) predefinedType = typePredefinedType; string categoryName = entityType.ToString(); if (!string.IsNullOrWhiteSpace(predefinedType)) categoryName += "." + predefinedType; return categoryName; }
/// <summary> /// Add a string parameter to an element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element.</param> /// <param name="objDef">The IFCObjectDefinition that created the element.</param> /// <param name="name">The enum corresponding to the parameter name.</param> /// <param name="parameterValue">The parameter value.</param> /// <param name="parameterSetId">The id of the containing parameter set, for reporting errors.</param> /// <returns>True if the parameter was successfully added, false otherwise.</returns> public static bool AddParameterString(Document doc, Element element, IFCObjectDefinition objDef, IFCSharedParameters name, string parameterValue, int parameterSetId) { if (objDef == null) return false; string parameterName = objDef.GetSharedParameterName(name); Parameter parameter = AddParameterBase(doc, element, parameterName, parameterSetId, ParameterType.Text); if (parameter == null) return false; parameter.Set(parameterValue); return true; }
/// <summary> /// Add a string parameter to an element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element.</param> /// <param name="category">The category of the element.</param> /// <param name="objDef">The IFCObjectDefinition that created the element.</param> /// <param name="name">The enum corresponding to the parameter name.</param> /// <param name="parameterValue">The parameter value.</param> /// <param name="parameterSetId">The id of the containing parameter set, for reporting errors.</param> /// <returns>True if the parameter was successfully added, false otherwise.</returns> public static bool AddParameterString(Document doc, Element element, Category category, IFCObjectDefinition objDef, IFCSharedParameters name, string parameterValue, int parameterSetId) { if (doc == null || element == null || category == null || objDef == null) { return(false); } string parameterName = objDef.GetSharedParameterName(name, element is ElementType); bool?processedParameter = Importer.TheProcessor.ProcessParameter(objDef.Id, parameterSetId, parameterName, parameterValue); if (processedParameter.HasValue) { return(processedParameter.Value); } Parameter parameter = AddParameterBase(doc, element, category, parameterName, parameterSetId, SpecTypeId.String.Text); if (parameter == null) { return(false); } parameter.Set(parameterValue); return(true); }
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> /// Create one or more elements /// </summary> /// <param name="doc">The document being populated.</param> /// <returns>The primary element associated with the IFCObjectDefinition, or InvalidElementId if it failed.</returns> public static ElementId CreateElement(Document doc, IFCObjectDefinition objDef) { // This would be a good place to check 'objDef.GlobalId'. ElementId createdElementId = objDef.CreatedElementId; try { if ((createdElementId == ElementId.InvalidElementId) && objDef.IsValidForCreation) { ElementId gstyleId; objDef.CategoryId = IFCCategoryUtil.GetCategoryIdForEntity(doc, objDef, out gstyleId); objDef.GraphicsStyleId = gstyleId; if (objDef is IFCObject) { IFCObject asObject = objDef as IFCObject; foreach (IFCTypeObject typeObject in asObject.TypeObjects) IFCObjectDefinition.CreateElement(doc, typeObject); } objDef.Create(doc); objDef.CreateParameters(doc); createdElementId = objDef.CreatedElementId; Importer.TheLog.AddCreatedEntity(doc, objDef); } } catch (Exception ex) { if (objDef != null) { objDef.IsValidForCreation = false; Importer.TheLog.LogCreationError(objDef, ex.Message, false); } } return createdElementId; }
/// <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> /// Create a property for a given element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element being created.</param> /// <param name="category">The category of the element being created.</param> /// <param name="parameterMap">The parameters of the element. Cached for performance.</param> /// <param name="propertySetName">The name of the containing property set.</param> /// <param name="createdParameters">The names of the created parameters.</param> public void Create(Document doc, Element element, Category category, IFCObjectDefinition objDef, IFCParameterSetByGroup parameterGroupMap, string propertySetName, ISet <string> createdParameters) { // Try to get the single value from the property. If we can't get a single value, get it as a string. IFCPropertyValue propertyValueToUse = null; if (this is IFCSimpleProperty) { IFCSimpleProperty simpleProperty = this as IFCSimpleProperty; IList <IFCPropertyValue> propertyValues = simpleProperty.IFCPropertyValues; if (propertyValues != null && propertyValues.Count == 1) { // If the value isn't set, skip it. We won't warn. if (!propertyValues[0].HasValue()) { return; } propertyValueToUse = propertyValues[0]; } } IFCDataPrimitiveType dataType = IFCDataPrimitiveType.Unknown; ForgeTypeId specTypeId = new ForgeTypeId(); ForgeTypeId unitsTypeId = null; bool? boolValueToUse = null; IFCLogical?logicalValueToUse = null; int? intValueToUse = null; double? doubleValueToUse = null; ElementId elementIdValueToUse = null; string stringValueToUse = null; if (propertyValueToUse == null) { string propertyValueAsString = PropertyValueAsString(); if (propertyValueAsString == null) { Importer.TheLog.LogError(Id, "Couldn't create parameter: " + Name, false); return; } dataType = IFCDataPrimitiveType.String; stringValueToUse = propertyValueAsString; } else { dataType = propertyValueToUse.Value.PrimitiveType; if (dataType == IFCDataPrimitiveType.Instance) { IFCAnyHandle propertyValueHandle = propertyValueToUse.Value.AsInstance(); ElementId propertyValueAsId = IFCObjectReferenceSelect.ToElementId(propertyValueHandle); if (propertyValueAsId != ElementId.InvalidElementId) { elementIdValueToUse = propertyValueAsId; } else { stringValueToUse = IFCObjectReferenceSelect.ToString(propertyValueHandle); dataType = IFCDataPrimitiveType.String; } } else { switch (dataType) { case IFCDataPrimitiveType.String: case IFCDataPrimitiveType.Enumeration: case IFCDataPrimitiveType.Binary: stringValueToUse = propertyValueToUse.AsString(); break; case IFCDataPrimitiveType.Integer: intValueToUse = propertyValueToUse.AsInteger(); break; case IFCDataPrimitiveType.Boolean: boolValueToUse = propertyValueToUse.AsBoolean(); break; case IFCDataPrimitiveType.Logical: logicalValueToUse = propertyValueToUse.AsLogical(); break; case IFCDataPrimitiveType.Double: if (propertyValueToUse.IFCUnit != null) { specTypeId = propertyValueToUse.IFCUnit.Spec; unitsTypeId = propertyValueToUse.IFCUnit.Unit; } else { specTypeId = IFCDataUtil.GetUnitTypeFromData(propertyValueToUse.Value, SpecTypeId.Number); } doubleValueToUse = Importer.TheProcessor.ScaleValues ? propertyValueToUse.AsScaledDouble() : propertyValueToUse.AsUnscaledDouble(); break; default: Importer.TheLog.LogError(Id, "Unknown value type for parameter: " + Name, false); return; } } } if (stringValueToUse != null && stringValueToUse.Length == 0) { return; } Parameter existingParameter = null; bool elementIsType = (element is ElementType); string typeString = elementIsType ? " " + Resources.IFCTypeSchedule : string.Empty; string originalParameterName = propertySetName + "." + Name + typeString; string parameterName = originalParameterName; if (parameterGroupMap.TryFindParameter(parameterName, out existingParameter)) { if ((existingParameter != null) && !IsValidParameterType(existingParameter, dataType)) { existingParameter = null; } } if (existingParameter == null) { int parameterNameCount = 2; while (createdParameters.Contains(parameterName)) { parameterName = originalParameterName + " " + parameterNameCount; parameterNameCount++; } if (parameterNameCount > 2) { Importer.TheLog.LogWarning(Id, "Renamed parameter: " + originalParameterName + " to: " + parameterName, false); } bool created = false; switch (dataType) { case IFCDataPrimitiveType.String: case IFCDataPrimitiveType.Enumeration: case IFCDataPrimitiveType.Binary: created = IFCPropertySet.AddParameterString(doc, element, category, objDef, parameterName, stringValueToUse, Id); break; case IFCDataPrimitiveType.Integer: created = IFCPropertySet.AddParameterInt(doc, element, category, objDef, parameterName, intValueToUse.Value, Id); break; case IFCDataPrimitiveType.Boolean: created = IFCPropertySet.AddParameterBoolean(doc, element, category, objDef, parameterName, boolValueToUse.Value, Id); break; case IFCDataPrimitiveType.Logical: if (logicalValueToUse != IFCLogical.Unknown) { created = IFCPropertySet.AddParameterBoolean(doc, element, category, objDef, parameterName, (logicalValueToUse == IFCLogical.True), Id); } break; case IFCDataPrimitiveType.Double: created = IFCPropertySet.AddParameterDouble(doc, element, category, objDef, parameterName, specTypeId, unitsTypeId, doubleValueToUse.Value, Id); break; case IFCDataPrimitiveType.Instance: created = IFCPropertySet.AddParameterElementId(doc, element, category, objDef, parameterName, elementIdValueToUse, Id); break; } if (created) { createdParameters.Add(originalParameterName); } return; } bool couldSetValue = false; switch (existingParameter.StorageType) { case StorageType.String: { switch (dataType) { case IFCDataPrimitiveType.String: case IFCDataPrimitiveType.Enumeration: case IFCDataPrimitiveType.Binary: couldSetValue = existingParameter.Set(stringValueToUse); break; case IFCDataPrimitiveType.Integer: couldSetValue = existingParameter.Set(intValueToUse.Value.ToString()); break; case IFCDataPrimitiveType.Boolean: couldSetValue = existingParameter.Set(boolValueToUse.Value ? "True" : "False"); break; case IFCDataPrimitiveType.Logical: couldSetValue = existingParameter.Set(logicalValueToUse.ToString()); break; case IFCDataPrimitiveType.Double: couldSetValue = existingParameter.Set(doubleValueToUse.ToString()); break; default: break; } } break; case StorageType.Integer: if (dataType == IFCDataPrimitiveType.Integer) { couldSetValue = existingParameter.Set(intValueToUse.Value); } else if (dataType == IFCDataPrimitiveType.Boolean) { couldSetValue = existingParameter.Set(boolValueToUse.Value ? 1 : 0); } else if (dataType == IFCDataPrimitiveType.Logical) { couldSetValue = (logicalValueToUse == IFCLogical.Unknown) ? true : existingParameter.Set((logicalValueToUse == IFCLogical.True) ? 1 : 0); } break; case StorageType.Double: if (dataType == IFCDataPrimitiveType.Double) { couldSetValue = existingParameter.Set(doubleValueToUse.Value); } else if (dataType == IFCDataPrimitiveType.Integer) { couldSetValue = existingParameter.Set(intValueToUse.Value); } else if (dataType == IFCDataPrimitiveType.Boolean) { couldSetValue = existingParameter.Set(boolValueToUse.Value ? 1 : 0); } else if ((dataType == IFCDataPrimitiveType.Logical) && (logicalValueToUse != IFCLogical.Unknown)) { couldSetValue = existingParameter.Set((logicalValueToUse == IFCLogical.True) ? 1 : 0); } break; } if (!couldSetValue) { Importer.TheLog.LogError(Id, "Couldn't create parameter: " + Name + " of storage type: " + existingParameter.StorageType.ToString(), false); } }
/// <summary> /// Create a quantity for a given element. /// </summary> /// <param name="doc">The document.</param> /// <param name="element">The element being created.</param> /// <param name="category">The element's category.</param> /// <param name="parameterMap">The parameters of the element. Cached for performance.</param> /// <param name="propertySetName">The name of the containing property set.</param> /// <param name="createdParameters">The names of the created parameters.</param> public abstract void Create(Document doc, Element element, Category category, IFCObjectDefinition objDef, IFCParameterSetByGroup parameterGroupMap, string propertySetName, ISet <string> createdParameters);