/// <summary> /// Processes an IFC unit in the property. /// </summary> /// <param name="ifcSimpleProperty">The simple property.</param> /// <param name="simplePropertyHandle">The simple property handle.</param> static protected void ProcessIFCSimplePropertyUnit(IFCSimpleProperty ifcSimpleProperty, IFCAnyHandle simplePropertyHandle) { IFCAnyHandle ifcUnitHandle = IFCImportHandleUtil.GetOptionalInstanceAttribute(simplePropertyHandle, "Unit"); IFCUnit ifcUnit = (ifcUnitHandle != null) ? IFCUnit.ProcessIFCUnit(ifcUnitHandle) : null; if (ifcUnit == null) { if (ifcSimpleProperty.IFCPropertyValues.Count > 0) { IFCPropertyValue propertyValue = ifcSimpleProperty.IFCPropertyValues[0]; if (propertyValue != null && propertyValue.HasValue() && (propertyValue.Type == IFCDataPrimitiveType.Integer) || (propertyValue.Type == IFCDataPrimitiveType.Double)) { string unitTypeName; UnitType unitType = IFCDataUtil.GetUnitTypeFromData(propertyValue.Value, UnitType.UT_Undefined, out unitTypeName); if (unitType != UnitType.UT_Undefined) { ifcUnit = IFCImportFile.TheFile.IFCUnits.GetIFCProjectUnit(unitType); } else { Importer.TheLog.LogWarning(simplePropertyHandle.StepId, "Unhandled unit type: " + unitTypeName, true); } } } } ifcSimpleProperty.m_IFCUnit = ifcUnit; }
/// <summary> /// Processes an IFC physical simple quantity. /// </summary> /// <param name="ifcPhysicalQuantity">The IfcPhysicalSimpleQuantity object.</param> /// <returns>The IFCPhysicalSimpleQuantity object.</returns> override protected void Process(IFCAnyHandle ifcPhysicalSimpleQuantity) { base.Process(ifcPhysicalSimpleQuantity); IFCAnyHandle unit = IFCImportHandleUtil.GetOptionalInstanceAttribute(ifcPhysicalSimpleQuantity, "Unit"); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(unit)) { IFCUnit = IFCUnit.ProcessIFCUnit(unit); } // Process subtypes of IfcPhysicalSimpleQuantity here. string attributeName = ifcPhysicalSimpleQuantity.TypeName.Substring(11) + "Value"; Value = ifcPhysicalSimpleQuantity.GetAttribute(attributeName); BaseUnitType = IFCDataUtil.GetUnitTypeFromData(Value, UnitType.UT_Undefined); if (BaseUnitType == UnitType.UT_Undefined) { // Determine it from the attributeName. if (string.Compare(attributeName, "LengthValue", true) == 0) { BaseUnitType = UnitType.UT_Length; } else if (string.Compare(attributeName, "AreaValue", true) == 0) { BaseUnitType = UnitType.UT_Area; } else if (string.Compare(attributeName, "VolumeValue", true) == 0) { BaseUnitType = UnitType.UT_Volume; } else if (string.Compare(attributeName, "CountValue", true) == 0) { BaseUnitType = UnitType.UT_Number; } else if (string.Compare(attributeName, "WeightValue", true) == 0) { BaseUnitType = UnitType.UT_Mass; } else if (string.Compare(attributeName, "TimeValue", true) == 0) { BaseUnitType = UnitType.UT_Number; // No time unit type in Revit. } else { Importer.TheLog.LogWarning(Id, "Can't determine unit type for IfcPhysicalSimpleQuantity of type: " + attributeName, true); BaseUnitType = UnitType.UT_Number; } } if (IFCUnit == null) { IFCUnit = IFCImportFile.TheFile.IFCUnits.GetIFCProjectUnit(BaseUnitType); } }
/// <summary> /// Processes a project unit. /// </summary> /// <param name="unitHnd">The unit handle.</param> /// <returns>The Unit object.</returns> public IFCUnit ProcessIFCProjectUnit(IFCAnyHandle unitHnd) { IFCUnit unit = IFCUnit.ProcessIFCUnit(unitHnd); if (unit != null) { m_ProjectUnitsDictionary[unit.Spec] = unit; } return(unit); }
/// <summary> /// Processes a conversion based unit. /// </summary> /// <param name="convUnitHnd">The unit handle.</param> void ProcessIFCConversionBasedUnit(IFCAnyHandle convUnitHnd) { IFCAnyHandle measureWithUnitHnd = IFCAnyHandleUtil.GetInstanceAttribute(convUnitHnd, "ConversionFactor"); if (IFCAnyHandleUtil.IsNullOrHasNoValue(measureWithUnitHnd)) { throw new InvalidOperationException("#" + convUnitHnd.StepId + ": Missing required attribute ConversionFactor."); } IFCUnit measureWithUnit = IFCUnit.ProcessIFCUnit(measureWithUnitHnd); if (measureWithUnit == null) { throw new InvalidOperationException("#" + convUnitHnd.StepId + ": Invalid base ConversionFactor, aborting."); } CopyUnit(measureWithUnit); // For some common cases, get the units correct. string unitType = IFCAnyHandleUtil.GetEnumerationAttribute(convUnitHnd, "UnitType"); if (string.Compare(unitType, "LENGTHUNIT", true) == 0) { UnitType = UnitType.UT_Length; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if (string.Compare(name, "FOOT", true) == 0 || string.Compare(name, "FEET", true) == 0) { UnitSystem = UnitSystem.Imperial; UnitName = UnitName.DUT_FEET_FRACTIONAL_INCHES; UnitSymbol = UnitSymbolType.UST_NONE; } else if (string.Compare(name, "INCH", true) == 0 || string.Compare(name, "INCHES", true) == 0) { UnitSystem = UnitSystem.Imperial; UnitName = UnitName.DUT_FRACTIONAL_INCHES; UnitSymbol = UnitSymbolType.UST_NONE; } } else if (string.Compare(unitType, "PLANEANGLEUNIT", true) == 0) { UnitType = UnitType.UT_Angle; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if (string.Compare(name, "GRAD", true) == 0 || string.Compare(name, "GRADIAN", true) == 0 || string.Compare(name, "GRADS", true) == 0 || string.Compare(name, "GRADIANS", true) == 0) { UnitSystem = UnitSystem.Metric; UnitName = UnitName.DUT_GRADS; UnitSymbol = UnitSymbolType.UST_GRAD; } else if (string.Compare(name, "DEGREE", true) == 0 || string.Compare(name, "DEGREES", true) == 0) { UnitSystem = UnitSystem.Imperial; UnitName = UnitName.DUT_DECIMAL_DEGREES; UnitSymbol = UnitSymbolType.UST_DEGREE_SYMBOL; } } else if (string.Compare(unitType, "AREAUNIT", true) == 0) { UnitType = UnitType.UT_Area; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if (string.Compare(name, "SQUARE FOOT", true) == 0 || string.Compare(name, "SQUARE_FOOT", true) == 0 || string.Compare(name, "SQUARE FEET", true) == 0 || string.Compare(name, "SQUARE_FEET", true) == 0) { UnitSystem = UnitSystem.Imperial; UnitName = UnitName.DUT_SQUARE_FEET; UnitSymbol = UnitSymbolType.UST_FT_SUP_2; } } else if (string.Compare(unitType, "VOLUMEUNIT", true) == 0) { UnitType = UnitType.UT_Volume; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if (string.Compare(name, "CUBIC FOOT", true) == 0 || string.Compare(name, "CUBIC_FOOT", true) == 0 || string.Compare(name, "CUBIC FEET", true) == 0 || string.Compare(name, "CUBIC_FEET", true) == 0) { UnitSystem = UnitSystem.Imperial; UnitName = UnitName.DUT_CUBIC_FEET; UnitSymbol = UnitSymbolType.UST_FT_SUP_3; } } else if (string.Compare(unitType, "THERMODYNAMICMEASUREUNIT", true) == 0) { UnitType = UnitType.UT_HVAC_Temperature; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if ((string.Compare(name, "F", true) == 0) || (string.Compare(name, "FAHRENHEIT", true) == 0)) { UnitSystem = UnitSystem.Imperial; UnitName = UnitName.DUT_FAHRENHEIT; UnitSymbol = UnitSymbolType.UST_DEGREE_F; } else if ((string.Compare(name, "R", true) == 0) || (string.Compare(name, "RANKINE", true) == 0)) { UnitSystem = UnitSystem.Imperial; UnitName = UnitName.DUT_RANKINE; UnitSymbol = UnitSymbolType.UST_DEGREE_R; } } }
/// <summary> /// Processes an IfcDerivedUnit. /// </summary> /// <param name="unitHnd">The unit handle.</param> void ProcessIFCDerivedUnit(IFCAnyHandle unitHnd) { List <IFCAnyHandle> elements = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(unitHnd, "Elements"); IList <KeyValuePair <IFCUnit, int> > derivedElementUnitHnds = new List <KeyValuePair <IFCUnit, int> >(); foreach (IFCAnyHandle subElement in elements) { IFCAnyHandle derivedElementUnitHnd = IFCImportHandleUtil.GetRequiredInstanceAttribute(subElement, "Unit", false); IFCUnit subUnit = IFCAnyHandleUtil.IsNullOrHasNoValue(derivedElementUnitHnd) ? null : IFCUnit.ProcessIFCUnit(derivedElementUnitHnd); if (subUnit != null) { bool found; int exponent = IFCImportHandleUtil.GetRequiredIntegerAttribute(subElement, "Exponent", out found); if (found) { derivedElementUnitHnds.Add(new KeyValuePair <IFCUnit, int>(subUnit, exponent)); } } } // the DerivedUnitExpectedTypes object is a description of one possible set of base units for a particular derived unit. // The IList allows for possible different interpretations. For example, Volumetric Flow Rate could be defined by m^3/s (length ^ 3 / time) or L/s (volume / time). IList <DerivedUnitExpectedTypes> expectedTypesList = new List <DerivedUnitExpectedTypes>(); string unitType = IFCAnyHandleUtil.GetEnumerationAttribute(unitHnd, "UnitType"); if (string.Compare(unitType, "LINEARVELOCITYUNIT", true) == 0) { UnitType = UnitType.UT_HVAC_Velocity; UnitSystem = UnitSystem.Metric; // Support only m / s. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitName.DUT_METERS_PER_SECOND, UnitSymbolType.UST_M_PER_S); expectedTypes.AddExpectedType(1, UnitType.UT_Length); expectedTypes.AddCustomExpectedType(-1, "TIMEUNIT"); expectedTypesList.Add(expectedTypes); } else if (string.Compare(unitType, "THERMALTRANSMITTANCEUNIT", true) == 0) { UnitType = UnitType.UT_HVAC_CoefficientOfHeatTransfer; UnitSystem = UnitSystem.Metric; // Support W / (K * m^2) or kg / (K * s^3) DerivedUnitExpectedTypes expectedTypesWinvKinvM2 = new DerivedUnitExpectedTypes(UnitName.DUT_WATTS_PER_SQUARE_METER_KELVIN, UnitSymbolType.UST_WATT_PER_SQ_M_K); expectedTypesWinvKinvM2.AddExpectedType(1, UnitType.UT_HVAC_Power); // UT_Electrical_Wattage is similar, but UT_HVAC_Power is the one we map to. expectedTypesWinvKinvM2.AddExpectedType(-1, UnitType.UT_HVAC_Temperature); expectedTypesWinvKinvM2.AddExpectedType(-2, UnitType.UT_Length); expectedTypesList.Add(expectedTypesWinvKinvM2); DerivedUnitExpectedTypes expectedTypesWinvKinvArea = new DerivedUnitExpectedTypes(UnitName.DUT_WATTS_PER_SQUARE_METER_KELVIN, UnitSymbolType.UST_WATT_PER_SQ_M_K); expectedTypesWinvKinvArea.AddExpectedType(1, UnitType.UT_HVAC_Power); // UT_Electrical_Wattage is similar, but UT_HVAC_Power is the one we map to. expectedTypesWinvKinvArea.AddExpectedType(-1, UnitType.UT_HVAC_Temperature); expectedTypesWinvKinvArea.AddExpectedType(-1, UnitType.UT_Area); expectedTypesList.Add(expectedTypesWinvKinvArea); DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitName.DUT_WATTS_PER_SQUARE_METER_KELVIN, UnitSymbolType.UST_WATT_PER_SQ_M_K); expectedTypes.AddExpectedType(1, UnitType.UT_Mass); expectedTypes.AddExpectedType(-1, UnitType.UT_HVAC_Temperature); expectedTypes.AddCustomExpectedType(-3, "TIMEUNIT"); expectedTypesList.Add(expectedTypes); } else if (string.Compare(unitType, "VOLUMETRICFLOWRATEUNIT", true) == 0) { UnitType = UnitType.UT_HVAC_Airflow; UnitSystem = UnitSystem.Metric; // Support L / s or m^3 / s in the IFC file. // L / s DerivedUnitExpectedTypes expectedTypesLPerS = new DerivedUnitExpectedTypes(UnitName.DUT_LITERS_PER_SECOND, UnitSymbolType.UST_L_PER_S); expectedTypesLPerS.AddExpectedType(1, UnitType.UT_Volume); expectedTypesLPerS.AddCustomExpectedType(-1, "TIMEUNIT"); expectedTypesList.Add(expectedTypesLPerS); // m^3 / s. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitName.DUT_CUBIC_METERS_PER_SECOND, UnitSymbolType.UST_CU_M_PER_S); expectedTypes.AddExpectedType(3, UnitType.UT_Length); expectedTypes.AddCustomExpectedType(-1, "TIMEUNIT"); expectedTypesList.Add(expectedTypes); } else if (string.Compare(unitType, "MASSDENSITYUNIT", true) == 0) { UnitType = UnitType.UT_MassDensity; UnitSystem = UnitSystem.Metric; // Support kg / m^3 in the IFC file. // kg / m^3. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitName.DUT_KILOGRAMS_PER_CUBIC_METER, UnitSymbolType.UST_KG_PER_CU_M); expectedTypes.AddExpectedType(1, UnitType.UT_Mass); expectedTypes.AddExpectedType(-3, UnitType.UT_Length); expectedTypesList.Add(expectedTypes); } else if (string.Compare(unitType, "USERDEFINED", true) == 0) { // Look at the sub-types to see what we support. string userDefinedType = IFCImportHandleUtil.GetOptionalStringAttribute(unitHnd, "UserDefinedType", null); if (!string.IsNullOrWhiteSpace(userDefinedType)) { if (string.Compare(userDefinedType, "Luminous Efficacy", true) == 0) { UnitType = UnitType.UT_Electrical_Efficacy; UnitSystem = UnitSystem.Metric; // Support only lm / W. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitName.DUT_LUMENS_PER_WATT, UnitSymbolType.UST_LM_PER_W); expectedTypes.AddExpectedType(-1, UnitType.UT_Mass); expectedTypes.AddExpectedType(-2, UnitType.UT_Length); expectedTypes.AddCustomExpectedType(3, "TIMEUNIT"); expectedTypes.AddExpectedType(1, UnitType.UT_Electrical_Luminous_Flux); expectedTypesList.Add(expectedTypes); } else if (string.Compare(userDefinedType, "Friction Loss", true) == 0) { UnitType = UnitType.UT_HVAC_Friction; UnitSystem = UnitSystem.Metric; // Support only Pa / m. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitName.DUT_PASCALS_PER_METER, UnitSymbolType.UST_PASCAL_PER_M); expectedTypes.AddExpectedType(-2, UnitType.UT_Length); expectedTypes.AddExpectedType(1, UnitType.UT_Mass); expectedTypes.AddCustomExpectedType(-2, "TIMEUNIT"); expectedTypesList.Add(expectedTypes); } } } foreach (DerivedUnitExpectedTypes derivedUnitExpectedTypes in expectedTypesList) { double scaleFactor = 1.0; if (derivedUnitExpectedTypes.Matches(derivedElementUnitHnds, out scaleFactor)) { // Found a match. UnitName = derivedUnitExpectedTypes.UnitName; UnitSymbol = derivedUnitExpectedTypes.UnitSymbol; ScaleFactor = scaleFactor; return; } } Importer.TheLog.LogUnhandledUnitTypeError(unitHnd, unitType); }
/// <summary> /// Processes a conversion based unit. /// </summary> /// <param name="convUnitHnd">The unit handle.</param> void ProcessIFCConversionBasedUnit(IFCAnyHandle convUnitHnd) { IFCAnyHandle measureWithUnitHnd = IFCAnyHandleUtil.GetInstanceAttribute(convUnitHnd, "ConversionFactor"); if (IFCAnyHandleUtil.IsNullOrHasNoValue(measureWithUnitHnd)) { throw new InvalidOperationException("#" + convUnitHnd.StepId + ": Missing required attribute ConversionFactor."); } IFCUnit measureWithUnit = IFCUnit.ProcessIFCUnit(measureWithUnitHnd); if (measureWithUnit == null) { throw new InvalidOperationException("#" + convUnitHnd.StepId + ": Invalid base ConversionFactor, aborting."); } CopyUnit(measureWithUnit); // For some common cases, get the units correct. string unitType = IFCAnyHandleUtil.GetEnumerationAttribute(convUnitHnd, "UnitType"); if (string.Compare(unitType, "LENGTHUNIT", true) == 0) { Spec = SpecTypeId.Length; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if (string.Compare(name, "FOOT", true) == 0 || string.Compare(name, "FEET", true) == 0) { UnitSystem = UnitSystem.Imperial; Unit = UnitTypeId.FeetFractionalInches; Symbol = new ForgeTypeId(); } else if (string.Compare(name, "INCH", true) == 0 || string.Compare(name, "INCHES", true) == 0) { UnitSystem = UnitSystem.Imperial; Unit = UnitTypeId.FractionalInches; Symbol = new ForgeTypeId(); } } else if (string.Compare(unitType, "PLANEANGLEUNIT", true) == 0) { Spec = SpecTypeId.Angle; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if (string.Compare(name, "GRAD", true) == 0 || string.Compare(name, "GRADIAN", true) == 0 || string.Compare(name, "GRADS", true) == 0 || string.Compare(name, "GRADIANS", true) == 0) { UnitSystem = UnitSystem.Metric; Unit = UnitTypeId.Gradians; Symbol = SymbolTypeId.Grad; } else if (string.Compare(name, "DEGREE", true) == 0 || string.Compare(name, "DEGREES", true) == 0) { UnitSystem = UnitSystem.Imperial; Unit = UnitTypeId.Degrees; Symbol = SymbolTypeId.Degree; } } else if (string.Compare(unitType, "AREAUNIT", true) == 0) { Spec = SpecTypeId.Area; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if (string.Compare(name, "SQUARE FOOT", true) == 0 || string.Compare(name, "SQUARE_FOOT", true) == 0 || string.Compare(name, "SQUARE FEET", true) == 0 || string.Compare(name, "SQUARE_FEET", true) == 0) { UnitSystem = UnitSystem.Imperial; Unit = UnitTypeId.SquareFeet; Symbol = SymbolTypeId.FtSup2; } } else if (string.Compare(unitType, "VOLUMEUNIT", true) == 0) { Spec = SpecTypeId.Volume; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if (string.Compare(name, "CUBIC FOOT", true) == 0 || string.Compare(name, "CUBIC_FOOT", true) == 0 || string.Compare(name, "CUBIC FEET", true) == 0 || string.Compare(name, "CUBIC_FEET", true) == 0) { UnitSystem = UnitSystem.Imperial; Unit = UnitTypeId.CubicFeet; Symbol = SymbolTypeId.FtSup3; } } else if (string.Compare(unitType, "THERMODYNAMICMEASUREUNIT", true) == 0) { Spec = SpecTypeId.HvacTemperature; string name = IFCAnyHandleUtil.GetStringAttribute(convUnitHnd, "Name"); if ((string.Compare(name, "F", true) == 0) || (string.Compare(name, "FAHRENHEIT", true) == 0)) { UnitSystem = UnitSystem.Imperial; Unit = UnitTypeId.Fahrenheit; Symbol = SymbolTypeId.DegreeF; } else if ((string.Compare(name, "R", true) == 0) || (string.Compare(name, "RANKINE", true) == 0)) { UnitSystem = UnitSystem.Imperial; Unit = UnitTypeId.Rankine; Symbol = SymbolTypeId.DegreeR; } } }
/// <summary> /// Processes an IfcDerivedUnit. /// </summary> /// <param name="unitHnd">The unit handle.</param> void ProcessIFCDerivedUnit(IFCAnyHandle unitHnd) { List <IFCAnyHandle> elements = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(unitHnd, "Elements"); IList <KeyValuePair <IFCUnit, int> > derivedElementUnitHnds = new List <KeyValuePair <IFCUnit, int> >(); foreach (IFCAnyHandle subElement in elements) { IFCAnyHandle derivedElementUnitHnd = IFCImportHandleUtil.GetRequiredInstanceAttribute(subElement, "Unit", false); IFCUnit subUnit = IFCAnyHandleUtil.IsNullOrHasNoValue(derivedElementUnitHnd) ? null : IFCUnit.ProcessIFCUnit(derivedElementUnitHnd); if (subUnit != null) { bool found; int exponent = IFCImportHandleUtil.GetRequiredIntegerAttribute(subElement, "Exponent", out found); if (found) { derivedElementUnitHnds.Add(new KeyValuePair <IFCUnit, int>(subUnit, exponent)); } } } // the DerivedUnitExpectedTypes object is a description of one possible set of base units for a particular derived unit. // The IList allows for possible different interpretations. For example, Volumetric Flow Rate could be defined by m^3/s (length ^ 3 / time) or L/s (volume / time). IList <DerivedUnitExpectedTypes> expectedTypesList = new List <DerivedUnitExpectedTypes>(); string unitType = IFCAnyHandleUtil.GetEnumerationAttribute(unitHnd, "UnitType"); if (string.Compare(unitType, "LINEARVELOCITYUNIT", true) == 0) { Spec = SpecTypeId.HvacVelocity; UnitSystem = UnitSystem.Metric; // Support only m / s. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitTypeId.MetersPerSecond, SymbolTypeId.MPerS); expectedTypes.AddExpectedType(1, SpecTypeId.Length); expectedTypes.AddCustomExpectedType(-1, "TIMEUNIT"); expectedTypesList.Add(expectedTypes); } else if (string.Compare(unitType, "THERMALTRANSMITTANCEUNIT", true) == 0) { Spec = SpecTypeId.HeatTransferCoefficient; UnitSystem = UnitSystem.Metric; // Support W / (K * m^2) or kg / (K * s^3) DerivedUnitExpectedTypes expectedTypesWinvKinvM2 = new DerivedUnitExpectedTypes(UnitTypeId.WattsPerSquareMeterKelvin, SymbolTypeId.WPerMSup2K); expectedTypesWinvKinvM2.AddExpectedType(1, SpecTypeId.HvacPower); // UT_Electrical_Wattage is similar, but UT_HVAC_Power is the one we map to. expectedTypesWinvKinvM2.AddExpectedType(-1, SpecTypeId.HvacTemperature); expectedTypesWinvKinvM2.AddExpectedType(-2, SpecTypeId.Length); expectedTypesList.Add(expectedTypesWinvKinvM2); DerivedUnitExpectedTypes expectedTypesWinvKinvArea = new DerivedUnitExpectedTypes(UnitTypeId.WattsPerSquareMeterKelvin, SymbolTypeId.WPerMSup2K); expectedTypesWinvKinvArea.AddExpectedType(1, SpecTypeId.HvacPower); // UT_Electrical_Wattage is similar, but UT_HVAC_Power is the one we map to. expectedTypesWinvKinvArea.AddExpectedType(-1, SpecTypeId.HvacTemperature); expectedTypesWinvKinvArea.AddExpectedType(-1, SpecTypeId.Area); expectedTypesList.Add(expectedTypesWinvKinvArea); DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitTypeId.WattsPerSquareMeterKelvin, SymbolTypeId.WPerMSup2K); expectedTypes.AddExpectedType(1, SpecTypeId.Mass); expectedTypes.AddExpectedType(-1, SpecTypeId.HvacTemperature); expectedTypes.AddCustomExpectedType(-3, "TIMEUNIT"); expectedTypesList.Add(expectedTypes); } else if (string.Compare(unitType, "VOLUMETRICFLOWRATEUNIT", true) == 0) { Spec = SpecTypeId.AirFlow; UnitSystem = UnitSystem.Metric; // Support L / s or m^3 / s in the IFC file. // L / s DerivedUnitExpectedTypes expectedTypesLPerS = new DerivedUnitExpectedTypes(UnitTypeId.LitersPerSecond, SymbolTypeId.LPerS); expectedTypesLPerS.AddExpectedType(1, SpecTypeId.Volume); expectedTypesLPerS.AddCustomExpectedType(-1, "TIMEUNIT"); expectedTypesList.Add(expectedTypesLPerS); // m^3 / s. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitTypeId.CubicMetersPerSecond, SymbolTypeId.MSup3PerS); expectedTypes.AddExpectedType(3, SpecTypeId.Length); expectedTypes.AddCustomExpectedType(-1, "TIMEUNIT"); expectedTypesList.Add(expectedTypes); } else if (string.Compare(unitType, "MASSDENSITYUNIT", true) == 0) { Spec = SpecTypeId.MassDensity; UnitSystem = UnitSystem.Metric; // Support kg / m^3 in the IFC file. // kg / m^3. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitTypeId.KilogramsPerCubicMeter, SymbolTypeId.KgPerMSup3); expectedTypes.AddExpectedType(1, SpecTypeId.Mass); expectedTypes.AddExpectedType(-3, SpecTypeId.Length); expectedTypesList.Add(expectedTypes); } else if (string.Compare(unitType, "LINEARFORCEUNIT", true) == 0) { Spec = SpecTypeId.LinearForce; UnitSystem = UnitSystem.Metric; // Support N / m in the IFC file. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitTypeId.NewtonsPerMeter, SymbolTypeId.NPerM); expectedTypes.AddExpectedType(1, SpecTypeId.LinearForce); expectedTypesList.Add(expectedTypes); // Support N / m in basic units DerivedUnitExpectedTypes expectedTypes2 = new DerivedUnitExpectedTypes(UnitTypeId.NewtonsPerMeter, SymbolTypeId.NPerM); expectedTypes2.AddExpectedType(1, SpecTypeId.Mass); expectedTypes2.AddExpectedType(1, SpecTypeId.Length); expectedTypes2.AddCustomExpectedType(-2, "TIMEUNIT"); expectedTypes2.AddExpectedType(-1, SpecTypeId.Length); expectedTypesList.Add(expectedTypes2); } else if (string.Compare(unitType, "PLANARFORCEUNIT", true) == 0) { Spec = SpecTypeId.AreaForce; UnitSystem = UnitSystem.Metric; // Support N / m^2 in the IFC file. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitTypeId.NewtonsPerSquareMeter, SymbolTypeId.NPerMSup2); expectedTypes.AddExpectedType(1, SpecTypeId.AreaForce); expectedTypesList.Add(expectedTypes); // Support N / m in basic units DerivedUnitExpectedTypes expectedTypes2 = new DerivedUnitExpectedTypes(UnitTypeId.NewtonsPerSquareMeter, SymbolTypeId.NPerMSup2); expectedTypes2.AddExpectedType(1, SpecTypeId.Mass); expectedTypes2.AddExpectedType(1, SpecTypeId.Length); expectedTypes2.AddCustomExpectedType(-2, "TIMEUNIT"); expectedTypes2.AddExpectedType(-2, SpecTypeId.Length); expectedTypesList.Add(expectedTypes2); } else if (string.Compare(unitType, "USERDEFINED", true) == 0) { // Look at the sub-types to see what we support. string userDefinedType = IFCImportHandleUtil.GetOptionalStringAttribute(unitHnd, "UserDefinedType", null); if (!string.IsNullOrWhiteSpace(userDefinedType)) { if (string.Compare(userDefinedType, "Luminous Efficacy", true) == 0) { Spec = SpecTypeId.Efficacy; UnitSystem = UnitSystem.Metric; // Support only lm / W. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitTypeId.LumensPerWatt, SymbolTypeId.LmPerW); expectedTypes.AddExpectedType(-1, SpecTypeId.Mass); expectedTypes.AddExpectedType(-2, SpecTypeId.Length); expectedTypes.AddCustomExpectedType(3, "TIMEUNIT"); expectedTypes.AddExpectedType(1, SpecTypeId.LuminousFlux); expectedTypesList.Add(expectedTypes); } else if (string.Compare(userDefinedType, "Friction Loss", true) == 0) { Spec = SpecTypeId.HvacFriction; UnitSystem = UnitSystem.Metric; // Support only Pa / m. DerivedUnitExpectedTypes expectedTypes = new DerivedUnitExpectedTypes(UnitTypeId.PascalsPerMeter, SymbolTypeId.PaPerM); expectedTypes.AddExpectedType(-2, SpecTypeId.Length); expectedTypes.AddExpectedType(1, SpecTypeId.Mass); expectedTypes.AddCustomExpectedType(-2, "TIMEUNIT"); expectedTypesList.Add(expectedTypes); } } } foreach (DerivedUnitExpectedTypes derivedUnitExpectedTypes in expectedTypesList) { double scaleFactor = 1.0; if (derivedUnitExpectedTypes.Matches(derivedElementUnitHnds, out scaleFactor)) { // Found a match. Unit = derivedUnitExpectedTypes.Unit; Symbol = derivedUnitExpectedTypes.Symbol; ScaleFactor = scaleFactor; return; } } Importer.TheLog.LogUnhandledUnitTypeError(unitHnd, unitType); }
/// <summary> /// Processes an IfcDerivedUnit. /// </summary> /// <param name="unitHnd">The unit handle.</param> void ProcessIFCDerivedUnit(IFCAnyHandle unitHnd) { List <IFCAnyHandle> elements = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(unitHnd, "Elements"); IList <KeyValuePair <IFCUnit, int> > derivedElementUnitHnds = new List <KeyValuePair <IFCUnit, int> >(); foreach (IFCAnyHandle subElement in elements) { IFCAnyHandle derivedElementUnitHnd = IFCImportHandleUtil.GetRequiredInstanceAttribute(subElement, "Unit", false); IFCUnit subUnit = IFCAnyHandleUtil.IsNullOrHasNoValue(derivedElementUnitHnd) ? null : IFCUnit.ProcessIFCUnit(derivedElementUnitHnd); if (subUnit != null) { bool found; int exponent = IFCImportHandleUtil.GetRequiredIntegerAttribute(subElement, "Exponent", out found); if (found) { derivedElementUnitHnds.Add(new KeyValuePair <IFCUnit, int>(subUnit, exponent)); } } } ISet <Tuple <int, UnitType, string> > expectedTypes = new HashSet <Tuple <int, UnitType, string> >(); string unitType = IFCAnyHandleUtil.GetEnumerationAttribute(unitHnd, "UnitType"); if (string.Compare(unitType, "THERMALTRANSMITTANCEUNIT", true) == 0) { UnitType = UnitType.UT_HVAC_CoefficientOfHeatTransfer; UnitSystem = UnitSystem.Metric; UnitName = UnitName.DUT_WATTS_PER_SQUARE_METER_KELVIN; // Support only kg / (K * s^3). expectedTypes.Add(new Tuple <int, Autodesk.Revit.DB.UnitType, string>(1, UnitType.UT_Mass, null)); expectedTypes.Add(new Tuple <int, Autodesk.Revit.DB.UnitType, string>(-1, UnitType.UT_HVAC_Temperature, null)); expectedTypes.Add(new Tuple <int, Autodesk.Revit.DB.UnitType, string>(-3, UnitType.UT_Custom, "TIMEUNIT")); } else if (string.Compare(unitType, "VOLUMETRICFLOWRATEUNIT", true) == 0) { UnitType = UnitType.UT_HVAC_Airflow; UnitSystem = UnitSystem.Metric; UnitName = UnitName.DUT_CUBIC_METERS_PER_SECOND; // Support only m^3 / s. expectedTypes.Add(new Tuple <int, Autodesk.Revit.DB.UnitType, string>(3, UnitType.UT_Length, null)); expectedTypes.Add(new Tuple <int, Autodesk.Revit.DB.UnitType, string>(-1, UnitType.UT_Custom, "TIMEUNIT")); } else if (string.Compare(unitType, "USERDEFINED", true) == 0) { // Look at the sub-types to see what we support. string userDefinedType = IFCImportHandleUtil.GetOptionalStringAttribute(unitHnd, "UserDefinedType", null); if (!string.IsNullOrWhiteSpace(userDefinedType)) { if (string.Compare(userDefinedType, "Luminous Efficacy", true) == 0) { UnitType = UnitType.UT_Electrical_Efficacy; UnitSystem = UnitSystem.Metric; UnitName = UnitName.DUT_LUMENS_PER_WATT; // Support only lm / W. expectedTypes.Add(new Tuple <int, Autodesk.Revit.DB.UnitType, string>(-1, UnitType.UT_Mass, null)); expectedTypes.Add(new Tuple <int, Autodesk.Revit.DB.UnitType, string>(-2, UnitType.UT_Length, null)); expectedTypes.Add(new Tuple <int, Autodesk.Revit.DB.UnitType, string>(3, UnitType.UT_Custom, "TIMEUNIT")); expectedTypes.Add(new Tuple <int, Autodesk.Revit.DB.UnitType, string>(1, UnitType.UT_Electrical_Luminous_Flux, null)); } } } double scaleFactor = 1.0; if (derivedElementUnitHnds.Count == expectedTypes.Count) { foreach (KeyValuePair <IFCUnit, int> derivedElementUnitHnd in derivedElementUnitHnds) { int dimensionality = derivedElementUnitHnd.Value; Tuple <int, UnitType, string> currKey = new Tuple <int, UnitType, string>(dimensionality, derivedElementUnitHnd.Key.UnitType, derivedElementUnitHnd.Key.CustomUnitType); if (expectedTypes.Contains(currKey)) { expectedTypes.Remove(currKey); scaleFactor *= Math.Pow(derivedElementUnitHnd.Key.ScaleFactor, dimensionality); } else { break; } } // Found all supported units. if (expectedTypes.Count == 0) { ScaleFactor = scaleFactor; return; } } IFCImportFile.TheLog.LogUnhandledUnitTypeError(unitHnd, unitType); }
/// <summary> /// Processes IfcProject attributes. /// </summary> /// <param name="ifcProjectHandle">The IfcProject handle.</param> protected override void Process(IFCAnyHandle ifcProjectHandle) { IFCAnyHandle unitsInContext = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcProjectHandle, "UnitsInContext", false); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(unitsInContext)) { IList <IFCAnyHandle> units = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(unitsInContext, "Units"); if (units != null) { m_UnitsInContext = new HashSet <IFCUnit>(); foreach (IFCAnyHandle unit in units) { IFCUnit ifcUnit = IFCImportFile.TheFile.IFCUnits.ProcessIFCProjectUnit(unit); if (!IFCUnit.IsNullOrInvalid(ifcUnit)) { m_UnitsInContext.Add(ifcUnit); } } } else { Importer.TheLog.LogMissingRequiredAttributeError(unitsInContext, "Units", false); } } var application = IFCImportFile.TheFile.Document.Application; var projectUnits = IFCImportFile.TheFile.IFCUnits.GetIFCProjectUnit(SpecTypeId.Length); IFCImportFile.TheFile.VertexTolerance = application.VertexTolerance; IFCImportFile.TheFile.ShortCurveTolerance = application.ShortCurveTolerance; Importer.TheProcessor.PostProcessProject(projectUnits?.ScaleFactor, projectUnits?.Unit); // We need to process the units before we process the rest of the file, since we will scale values as we go along. base.Process(ifcProjectHandle); // process true north - take the first valid representation context that has a true north value. HashSet <IFCAnyHandle> repContexts = IFCAnyHandleUtil.GetAggregateInstanceAttribute <HashSet <IFCAnyHandle> >(ifcProjectHandle, "RepresentationContexts"); bool hasMapConv = false; XYZ geoRef = XYZ.Zero; string geoRefName = null; double trueNorth = 0.0; if (repContexts != null) { foreach (IFCAnyHandle geomRepContextHandle in repContexts) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(geomRepContextHandle) && IFCAnyHandleUtil.IsSubTypeOf(geomRepContextHandle, IFCEntityType.IfcGeometricRepresentationContext)) { IFCRepresentationContext context = IFCRepresentationContext.ProcessIFCRepresentationContext(geomRepContextHandle); if (TrueNorthDirection == null && context.TrueNorth != null) { // TODO: Verify that we don't have inconsistent true norths. If we do, warn. TrueNorthDirection = new UV(context.TrueNorth.X, context.TrueNorth.Y); } if (WorldCoordinateSystem == null && context.WorldCoordinateSystem != null && !context.WorldCoordinateSystem.IsIdentity) { WorldCoordinateSystem = context.WorldCoordinateSystem; } // Process Map Conversion if any HashSet <IFCAnyHandle> coordOperation = IFCAnyHandleUtil.GetAggregateInstanceAttribute <HashSet <IFCAnyHandle> >(geomRepContextHandle, "HasCoordinateOperation"); if (coordOperation != null) { if (coordOperation.Count > 0) { if (IFCAnyHandleUtil.IsSubTypeOf(coordOperation.FirstOrDefault(), IFCEntityType.IfcMapConversion)) { hasMapConv = true; IFCAnyHandle mapConv = coordOperation.FirstOrDefault(); bool found = false; double eastings = IFCImportHandleUtil.GetRequiredScaledLengthAttribute(mapConv, "Eastings", out found); if (!found) { eastings = 0.0; } double northings = IFCImportHandleUtil.GetRequiredScaledLengthAttribute(mapConv, "Northings", out found); if (!found) { northings = 0.0; } double orthogonalHeight = IFCImportHandleUtil.GetRequiredScaledLengthAttribute(mapConv, "OrthogonalHeight", out found); if (!found) { orthogonalHeight = 0.0; } double xAxisAbs = IFCImportHandleUtil.GetOptionalRealAttribute(mapConv, "XAxisAbscissa", 1.0); double xAxisOrd = IFCImportHandleUtil.GetOptionalRealAttribute(mapConv, "XAxisOrdinate", 0.0); trueNorth = Math.Atan2(xAxisOrd, xAxisAbs); //angleToNorth = -((xAxisAngle > -Math.PI / 2.0) ? xAxisAngle - Math.PI / 2.0 : xAxisAngle + Math.PI * 1.5); double scale = IFCImportHandleUtil.GetOptionalRealAttribute(mapConv, "Scale", 1.0); geoRef = new XYZ(scale * eastings, scale * northings, scale * orthogonalHeight); // Process the IfcProjectedCRS IFCAnyHandle projCRS = IFCAnyHandleUtil.GetInstanceAttribute(mapConv, "TargetCRS"); if (projCRS != null && IFCAnyHandleUtil.IsSubTypeOf(projCRS, IFCEntityType.IfcProjectedCRS)) { geoRefName = IFCImportHandleUtil.GetRequiredStringAttribute(projCRS, "Name", false); string desc = IFCImportHandleUtil.GetOptionalStringAttribute(projCRS, "Description", null); string geodeticDatum = IFCImportHandleUtil.GetOptionalStringAttribute(projCRS, "GeodeticDatum", null); string verticalDatum = IFCImportHandleUtil.GetOptionalStringAttribute(projCRS, "VerticalDatum", null); string mapProj = IFCImportHandleUtil.GetOptionalStringAttribute(projCRS, "MapProjection", null); string mapZone = IFCImportHandleUtil.GetOptionalStringAttribute(projCRS, "MapZone", null); IFCAnyHandle mapUnit = IFCImportHandleUtil.GetOptionalInstanceAttribute(projCRS, "MapUnit"); Document doc = IFCImportFile.TheFile.Document; ProjectInfo projectInfo = doc.ProjectInformation; // We add this here because we want to make sure that external processors (e.g., Navisworks) // get a chance to add a container for the parameters that get added below. In general, // we should probably augment Processor.AddParameter to ensure that CreateOrUpdateElement // is called before anything is attempted to be added. This is a special case, though, // as in Revit we don't actually create an element for the IfcProject. Importer.TheProcessor.CreateOrUpdateElement(Id, GlobalId, EntityType.ToString(), CategoryId.IntegerValue, null); Category category = IFCPropertySet.GetCategoryForParameterIfValid(projectInfo, Id); IFCPropertySet.AddParameterString(doc, projectInfo, category, this, "IfcProjectedCRS.Name", geoRefName, Id); if (!string.IsNullOrEmpty(desc)) { IFCPropertySet.AddParameterString(doc, projectInfo, category, this, "IfcProjectedCRS.Description", desc, Id); } if (!string.IsNullOrEmpty(geodeticDatum)) { IFCPropertySet.AddParameterString(doc, projectInfo, category, this, "IfcProjectedCRS.GeodeticDatum", geodeticDatum, Id); } if (!string.IsNullOrEmpty(verticalDatum)) { IFCPropertySet.AddParameterString(doc, projectInfo, category, this, "IfcProjectedCRS.VerticalDatum", verticalDatum, Id); } if (!string.IsNullOrEmpty(mapProj)) { IFCPropertySet.AddParameterString(doc, projectInfo, category, this, "IfcProjectedCRS.MapProjection", mapProj, Id); } if (!string.IsNullOrEmpty(mapZone)) { IFCPropertySet.AddParameterString(doc, projectInfo, category, this, "IfcProjectedCRS.MapZone", mapZone, Id); } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(mapUnit)) { IFCUnit mapUnitIfc = IFCUnit.ProcessIFCUnit(mapUnit); string unitStr = UnitUtils.GetTypeCatalogStringForUnit(mapUnitIfc.Unit); IFCPropertySet.AddParameterString(doc, projectInfo, category, this, "IfcProjectedCRS.MapUnit", unitStr, Id); double convFactor = UnitUtils.Convert(1.0, mapUnitIfc.Unit, IFCImportFile.TheFile.IFCUnits.GetIFCProjectUnit(SpecTypeId.Length).Unit); eastings = convFactor * eastings; northings = convFactor * northings; orthogonalHeight = convFactor * orthogonalHeight; geoRef = new XYZ(eastings, northings, orthogonalHeight); } } } } } } } ProjectLocation projectLocation = IFCImportFile.TheFile.Document.ActiveProjectLocation; ProjectPosition projectPosition; if (projectLocation != null) { if (hasMapConv) { projectPosition = new ProjectPosition(geoRef.X, geoRef.Y, geoRef.Z, trueNorth); projectLocation.SetProjectPosition(XYZ.Zero, projectPosition); if (!string.IsNullOrEmpty(geoRefName)) { IFCImportFile.TheFile.Document.SiteLocation.SetGeoCoordinateSystem(geoRefName); } } else { // Set initial project location based on the information above. // This may be further modified by the site. trueNorth = 0.0; if (TrueNorthDirection != null) { trueNorth = -Math.Atan2(-TrueNorthDirection.U, TrueNorthDirection.V); } // TODO: Extend this to work properly if the world coordinate system // isn't a simple translation. XYZ origin = XYZ.Zero; if (WorldCoordinateSystem != null) { geoRef = WorldCoordinateSystem.Origin; double angleRot = Math.Atan2(WorldCoordinateSystem.BasisX.Y, WorldCoordinateSystem.BasisX.X); // If it is translation only, or if the WCS rotation is equal to trueNorth, we assume they are the same if (WorldCoordinateSystem.IsTranslation || MathUtil.IsAlmostEqual(angleRot, trueNorth)) { WorldCoordinateSystem = null; } else { // If the trueNorth is not set (=0), set the trueNorth by the rotation of the WCS, otherwise add the angle if (MathUtil.IsAlmostZero(trueNorth)) { trueNorth = angleRot; } else { trueNorth += angleRot; } WorldCoordinateSystem = null; } } projectPosition = new ProjectPosition(geoRef.X, geoRef.Y, geoRef.Z, trueNorth); projectLocation.SetProjectPosition(XYZ.Zero, projectPosition); } } } }