public void UnitConversionTests() { var converter = new IfcUnitConverter("squaremetres"); var meterCubics = new[] { " cubic-metres ", "cubicmetres", "cubicmeters", "m3", "cubic meters" }; foreach (var cubic in meterCubics) { converter.Convert(cubic); Assert.IsTrue(Math.Abs(converter.ConversionFactor - 1.0) < 1e-9); Assert.IsNotNull(converter.SiUnitName); Assert.IsTrue(converter.SiUnitName.Value == IfcSIUnitName.CUBIC_METRE); Assert.IsNull(converter.SiPrefix); } }
private void AddQuantity(ValueBaseType valueBaseType, string cobiePropertyName, IfcUnitConverter actualUnits, IfcElementQuantity propertySetDefinition, NamedProperty namedProperty) { try { var cobieValue = valueBaseType.ConvertTo <double>(); //quantities are always doubles if (actualUnits.IsUndefined) { throw new ArgumentException("Invalid unit type " + actualUnits.UserDefinedSiUnitName + " has been pass to CreatePropertySingleValue"); } IfcPhysicalQuantity quantity; switch (actualUnits.UnitName) //they are all here for future proofing, time, mass and count though are not really used by COBie { case IfcUnitEnum.AREAUNIT: quantity = TargetRepository.Instances.New <IfcQuantityArea>( q => q.AreaValue = new IfcAreaMeasure(cobieValue)); break; case IfcUnitEnum.LENGTHUNIT: quantity = TargetRepository.Instances.New <IfcQuantityLength>( q => q.LengthValue = new IfcLengthMeasure(cobieValue)); break; case IfcUnitEnum.MASSUNIT: quantity = TargetRepository.Instances.New <IfcQuantityWeight>( q => q.WeightValue = new IfcMassMeasure(cobieValue)); break; case IfcUnitEnum.TIMEUNIT: quantity = TargetRepository.Instances.New <IfcQuantityTime>( q => q.TimeValue = new IfcTimeMeasure(cobieValue)); break; case IfcUnitEnum.VOLUMEUNIT: quantity = TargetRepository.Instances.New <IfcQuantityVolume>( q => q.VolumeValue = new IfcVolumeMeasure(cobieValue)); break; case IfcUnitEnum.USERDEFINED: //we will treat this as Item for now quantity = TargetRepository.Instances.New <IfcQuantityCount>( q => q.CountValue = new IfcCountMeasure(cobieValue)); break; default: throw new ArgumentOutOfRangeException(); } quantity.Description = "Converted from COBie " + cobiePropertyName; quantity.Name = namedProperty.PropertyName; propertySetDefinition.Quantities.Add(quantity); } catch (Exception e) { throw new Exception("Failed to convert a COBie Value to and Ifc Quantity. " + e.Message); } }
/// <summary> /// Creates the property and if required the property set, populates them with the correct values and adds them to the IfcObject /// If the value is null or empty no property is created /// </summary> /// <param name="ifcObject">Object to associate the property with</param> /// <param name="valueBaseType">COBie value to populate the property with</param> /// <param name="cobiePropertyName">Name of the COBie property being mapped</param> /// <param name="defaultUnits">Units to use if the COBie property does not specify</param> internal bool TryCreatePropertySingleValue(IfcObject ifcObject, ValueBaseType valueBaseType, string cobiePropertyName, IfcUnitConverter?defaultUnits) { if (!valueBaseType.HasValue()) { return(false); //nothing to do } try { NamedProperty namedProperty; if (CobieToIfcPropertyMap.TryGetValue(cobiePropertyName, out namedProperty)) { var actualUnits = new IfcUnitConverter(valueBaseType.UnitName); if (actualUnits.IsUndefined && defaultUnits.HasValue) { actualUnits = defaultUnits.Value; } List <IfcPropertySetDefinition> propertySetDefinitionList; if (!_objectsToPropertySets.TryGetValue(ifcObject, out propertySetDefinitionList)) { propertySetDefinitionList = new List <IfcPropertySetDefinition>(); _objectsToPropertySets.Add(ifcObject, propertySetDefinitionList); } var propertySetDef = propertySetDefinitionList.Find(p => p.Name == namedProperty.PropertySetName); //see what sets we have against this object if (propertySetDef == null) { //simplistic way to decide if this should be a quantity, IFC 4 specifies the name starts with QTO, under 2x3 most vendors have gone for BaseQuantities if (namedProperty.PropertySetName.StartsWith("qto_", true, CultureInfo.InvariantCulture) || namedProperty.PropertySetName.StartsWith("basequantities", true, CultureInfo.InvariantCulture)) { var quantitySet = TargetRepository.Instances.New <IfcElementQuantity>(); propertySetDefinitionList.Add(quantitySet); quantitySet.Name = namedProperty.PropertySetName; var relDef = TargetRepository.Instances.New <IfcRelDefinesByProperties>(); relDef.RelatingPropertyDefinition = quantitySet; relDef.RelatedObjects.Add(ifcObject); AddQuantity(valueBaseType, cobiePropertyName, actualUnits, quantitySet, namedProperty); } else //it is a normal property set { var propertySet = TargetRepository.Instances.New <IfcPropertySet>(); propertySetDefinitionList.Add(propertySet); propertySet.Name = namedProperty.PropertySetName; var relDef = TargetRepository.Instances.New <IfcRelDefinesByProperties>(); relDef.RelatingPropertyDefinition = propertySet; relDef.RelatedObjects.Add(ifcObject); AddProperty(ifcObject, valueBaseType.ConvertToIfcValue(), cobiePropertyName, propertySet, namedProperty); } } else //need to use an existing PropertySet definition { //simplistic way to decide if this should be a quantity, IFC 4 specifies the name starts with QTO, under 2x3 most vendors have gone for BaseQuantities if (namedProperty.PropertySetName.StartsWith("qto_", true, CultureInfo.InvariantCulture) || namedProperty.PropertySetName.StartsWith("basequantities", true, CultureInfo.InvariantCulture)) { AddQuantity(valueBaseType, cobiePropertyName, actualUnits, (IfcElementQuantity)propertySetDef, namedProperty); } else //it is a normal property set { AddProperty(ifcObject, valueBaseType.ConvertToIfcValue(), cobiePropertyName, (IfcPropertySet)propertySetDef, namedProperty); } } return(true); } throw new ArgumentException("Incorrect property map", "cobiePropertyName"); } catch (Exception e) { Debug.WriteLine("Incorrect property map, " + e.Message); Debug.Assert(false); return(false); } }
/// <summary> /// Converts an attribute in to an Ifc Property, still needs support for units adding /// </summary> /// <param name="attributeType"></param> /// <returns></returns> internal IfcSimpleProperty ConvertAttributeToIfcSimpleProperty(Attribute attributeType) { var attributeValue = attributeType.Value; IfcSimpleProperty theProperty; var simplePropertyType = attributeValue.SimplePropertyType(); switch (simplePropertyType) { case XbimSimplePropertyType.SimpleDecimal: case XbimSimplePropertyType.SimpleInteger: case XbimSimplePropertyType.SimpleBoolean: case XbimSimplePropertyType.SimpleMonetary: case XbimSimplePropertyType.SimpleString: case XbimSimplePropertyType.SimpleDateTime: case XbimSimplePropertyType.Null: theProperty = TargetRepository.Instances.New <IfcPropertySingleValue>(); break; case XbimSimplePropertyType.BoundedDecimal: case XbimSimplePropertyType.BoundedInteger: theProperty = TargetRepository.Instances.New <IfcPropertyBoundedValue>(); break; case XbimSimplePropertyType.EnumerationString: theProperty = TargetRepository.Instances.New <IfcPropertyEnumeratedValue>(); break; default: throw new ArgumentOutOfRangeException("attributeType", "Invalid attribute value type"); } theProperty.Name = attributeType.Name; theProperty.Description = attributeType.Description; if (attributeValue != null) { var simpleProperty = theProperty as IfcPropertySingleValue; if (simpleProperty != null) { var unitConverter = new IfcUnitConverter(attributeValue.Unit); if (!unitConverter.IsUndefined) { simpleProperty.Unit = unitConverter.IfcUnit(_units, TargetRepository); } } switch (simplePropertyType) { case XbimSimplePropertyType.SimpleDecimal: var decimalValue = attributeValue as DecimalAttributeValue; var simpleDecimalProperty = (IfcPropertySingleValue)theProperty; if (decimalValue != null) { if (decimalValue.Value.HasValue) { simpleDecimalProperty.NominalValue = new IfcReal(decimalValue.Value.Value); } } break; case XbimSimplePropertyType.BoundedDecimal: var boundedDecimal = attributeValue as DecimalAttributeValue; if (boundedDecimal != null) { var boundedProperty = (IfcPropertyBoundedValue)theProperty; if (boundedDecimal.MaximalValue.HasValue) { boundedProperty.UpperBoundValue = new IfcReal(boundedDecimal.MaximalValue.Value); } if (boundedDecimal.MinimalValue.HasValue) { boundedProperty.LowerBoundValue = new IfcReal(boundedDecimal.MinimalValue.Value); } } break; case XbimSimplePropertyType.SimpleInteger: var simpleInteger = attributeValue as IntegerAttributeValue; if (simpleInteger != null && simpleInteger.Value.HasValue) { var simpleIntProperty = (IfcPropertySingleValue)theProperty; simpleIntProperty.NominalValue = new IfcInteger(simpleInteger.Value.Value); } break; case XbimSimplePropertyType.BoundedInteger: var attributeBoundedIntegerValueType = attributeValue as IntegerAttributeValue; if (attributeBoundedIntegerValueType != null) { var boundedIntegerProperty = (IfcPropertyBoundedValue)theProperty; if (attributeBoundedIntegerValueType.MaximalValue.HasValue) { boundedIntegerProperty.UpperBoundValue = new IfcInteger(attributeBoundedIntegerValueType.MaximalValue.Value); } if (attributeBoundedIntegerValueType.MinimalValue.HasValue) { boundedIntegerProperty.LowerBoundValue = new IfcInteger(attributeBoundedIntegerValueType.MinimalValue.Value); } } break; case XbimSimplePropertyType.SimpleBoolean: var attributeBooleanValueType = attributeValue as BooleanAttributeValue; if (attributeBooleanValueType != null) { var simpleBooleanProperty = (IfcPropertySingleValue)theProperty; if (attributeBooleanValueType.Value.HasValue) { simpleBooleanProperty.NominalValue = new IfcBoolean(attributeBooleanValueType.Value.Value); } } break; //case XbimSimplePropertyType.SimpleMonetary: // var attributeMonetaryValueType = attributeValueType as AttributeMonetaryValueType; // if (attributeMonetaryValueType != null) // { // var simpleMonetaryProperty = (IfcPropertySingleValue) theProperty; // var monetaryValue = (double) attributeMonetaryValueType.MonetaryValue; // simpleMonetaryProperty.NominalValue = new IfcReal(monetaryValue); // IfcCurrencyEnum currencyEnum; // if (Enum.TryParse(attributeMonetaryValueType.MonetaryUnit.ToString(), true, out currencyEnum)) // simpleMonetaryProperty.Unit = new IfcMonetaryUnit {Currency = currencyEnum}; // } // break; case XbimSimplePropertyType.EnumerationString: var attributeEnumStringValueType = attributeValue as StringAttributeValue; if (attributeEnumStringValueType != null) { var simpleEnumStringProperty = (IfcPropertyEnumeratedValue)theProperty; simpleEnumStringProperty.EnumerationValues.Add( new IfcLabel(attributeEnumStringValueType.Value)); if (attributeEnumStringValueType.AllowedValues != null && attributeEnumStringValueType.AllowedValues.Any()) { simpleEnumStringProperty.EnumerationReference = TargetRepository.Instances.New <IfcPropertyEnumeration>(); foreach (var allowedValue in attributeEnumStringValueType.AllowedValues) { simpleEnumStringProperty.EnumerationReference.Name = attributeType.Name; simpleEnumStringProperty.EnumerationReference.EnumerationValues.Add( new IfcLabel(allowedValue)); } } } break; case XbimSimplePropertyType.SimpleString: case XbimSimplePropertyType.Null: var attributeStringValueType = attributeValue as StringAttributeValue; if (attributeStringValueType != null) { var simpleStringProperty = (IfcPropertySingleValue)theProperty; simpleStringProperty.NominalValue = new IfcText(attributeStringValueType.Value); } break; case XbimSimplePropertyType.SimpleDateTime: var attributeDateTimeValueType = attributeValue as DateTimeAttributeValue; if (attributeDateTimeValueType != null && attributeDateTimeValueType.Value.HasValue) { var simpleDateTimeProperty = (IfcPropertySingleValue)theProperty; simpleDateTimeProperty.NominalValue = IfcTimeStamp.ToTimeStamp(attributeDateTimeValueType.Value.Value); } break; default: throw new ArgumentOutOfRangeException("attributeType", "Invalid attribute value type"); } } return(theProperty); }