Skip to content

Commit

Permalink
CNX-751: Add Units to reportProperties (#389)
Browse files Browse the repository at this point in the history
* Datatype

Main change is the switch from Tekla.Structures.Drawing to Tekla.Structures.Datatype for units. Problem is, that Settings > Options > Units and decimals don't seem to affect API returns. Will confirm with Tekla team. Rudimentary fix applied for now.

* Weight Unit

* Weight Unit

* Consisten representation of internal units

* Distance.CurrentUnitType

As discussed

---------

Co-authored-by: Oğuzhan Koral <[email protected]>
  • Loading branch information
bjoernsteinhagen and oguzhankoral authored Nov 19, 2024
1 parent 4215f90 commit 8822761
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using Speckle.Converters.Common;
using Speckle.Converters.Common.Registration;
using Speckle.Sdk;
using Tekla.Structures.Drawing;
using Tekla.Structures.Datatype;

namespace Speckle.Converter.Tekla2024;

Expand All @@ -22,7 +22,7 @@ public static IServiceCollection AddTeklaConverters(this IServiceCollection serv
serviceCollection.AddScoped<ReportPropertyExtractor>();

serviceCollection.AddRootCommon<TeklaRootToSpeckleConverter>(converterAssembly);
serviceCollection.AddApplicationConverters<TeklaToSpeckleUnitConverter, Units>(converterAssembly);
serviceCollection.AddApplicationConverters<TeklaToSpeckleUnitConverter, Distance.UnitType>(converterAssembly);
serviceCollection.AddScoped<
IConverterSettingsStore<TeklaConversionSettings>,
ConverterSettingsStore<TeklaConversionSettings>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
using Speckle.Converters.Common;
using Speckle.InterfaceGenerator;
using Tekla.Structures.Datatype;
using Tekla.Structures.Model;
using TSD = Tekla.Structures.Drawing;

namespace Speckle.Converter.Tekla2024;

[GenerateAutoInterface]
public class TeklaConversionSettingsFactory(
IHostToSpeckleUnitConverter<TSD.Units> unitsConverter,
IHostToSpeckleUnitConverter<Distance.UnitType> unitsConverter,
IConverterSettingsStore<TeklaConversionSettings> settingsStore
) : ITeklaConversionSettingsFactory
{
public TeklaConversionSettings Current => settingsStore.Current;

// only handles automatic rn
// NOTE: Distance.CurrentUnitType reflects Settings > Options > Units and decimals
// Internal units (mm) are, however, always returned.
// If model units != internal units, user can rely on units appended to each report parameter
public TeklaConversionSettings Create(Model document, bool sendRebarsAsSolid) =>
new(document, sendRebarsAsSolid, unitsConverter.ConvertOrThrow(TSD.Units.Automatic));
new(document, sendRebarsAsSolid, unitsConverter.ConvertOrThrow(Distance.CurrentUnitType));
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,25 @@
using Speckle.Converters.Common;
using Speckle.Sdk.Common.Exceptions;
using Tekla.Structures.Datatype;
using SSC = Speckle.Sdk.Common;
using TSD = Tekla.Structures.Drawing;

namespace Speckle.Converter.Tekla2024;

public class TeklaToSpeckleUnitConverter : IHostToSpeckleUnitConverter<TSD.Units>
public class TeklaToSpeckleUnitConverter : IHostToSpeckleUnitConverter<Distance.UnitType>
{
private readonly Dictionary<TSD.Units, string> _unitMapping = new();
private readonly Dictionary<Distance.UnitType, string> _unitMapping = new();

public TeklaToSpeckleUnitConverter()
{
_unitMapping[TSD.Units.Automatic] = SSC.Units.Millimeters;
_unitMapping[TSD.Units.Millimeters] = SSC.Units.Millimeters;
_unitMapping[TSD.Units.Centimeters] = SSC.Units.Centimeters;
_unitMapping[TSD.Units.Meters] = SSC.Units.Meters;
_unitMapping[TSD.Units.Inches] = SSC.Units.Inches;
_unitMapping[TSD.Units.Feet] = SSC.Units.Feet;

// there are also other units in tekla, not sure how to handle them in speckle
// auto unit option in tekla is based on the selected environment
//_unitMapping[TSD.Units.FeetAndInches]
//_unitMapping[TSD.Units.CentimetersOrMeters]
_unitMapping[Distance.UnitType.Millimeter] = SSC.Units.Millimeters;
_unitMapping[Distance.UnitType.Centimeter] = SSC.Units.Centimeters;
_unitMapping[Distance.UnitType.Meter] = SSC.Units.Meters;
_unitMapping[Distance.UnitType.Inch] = SSC.Units.Inches;
_unitMapping[Distance.UnitType.Foot] = SSC.Units.Feet;
}

public string ConvertOrThrow(TSD.Units hostUnit)
{
if (_unitMapping.TryGetValue(hostUnit, out string? value))
{
return value;
}

throw new UnitNotSupportedException($"The Unit System \"{hostUnit}\" is unsupported.");
}
public string ConvertOrThrow(Distance.UnitType hostUnit) =>
_unitMapping.TryGetValue(hostUnit, out string? value)
? value
: throw new UnitNotSupportedException($"The Unit System \"{hostUnit}\" is unsupported.");
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ public ClassPropertyExtractor() { }

private void AddBeamProperties(TSM.Beam beam, Dictionary<string, object?> properties)
{
properties["Name"] = beam.Name;
properties["name"] = beam.Name;
properties["profile"] = beam.Profile.ProfileString;
properties["material"] = beam.Material.MaterialString;
}

private void AddContourPlateProperties(TSM.ContourPlate plate, Dictionary<string, object?> properties)
{
properties["Name"] = plate.Name;
properties["name"] = plate.Name;
properties["profile"] = plate.Profile.ProfileString;
properties["material"] = plate.Material.MaterialString;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Speckle.Converter.Tekla2024.ToSpeckle.Helpers;
using Tekla.Structures.Datatype;

namespace Speckle.Converter.Tekla2024.ToSpeckle.Helpers;

public class ReportPropertyExtractor
{
Expand Down Expand Up @@ -44,45 +46,63 @@ public class ReportPropertyExtractor
{ typeof(TSM.BoltArray), new[] { "BOLT_SIZE", "NUMBER_OF_BOLTS", "BOLT_STANDARD", "BOLT_TYPE", "LENGTH" } }
};

public Dictionary<string, object?> GetProperties(TSM.ModelObject modelObject)
public Dictionary<string, Dictionary<string, object?>> GetReportProperties(TSM.ModelObject modelObject)
{
var properties = new Dictionary<string, object?>();
var reportProperties = new Dictionary<string, Dictionary<string, object?>>();

if (!s_typeSpecificProperties.TryGetValue(modelObject.GetType(), out var propertyNames))
{
// if no specific properties defined, return empty dictionary
return properties;
// NOTE: Return empty dictionary if no specific properties defined
return reportProperties;
}

foreach (string propertyName in propertyNames)
{
TryGetReportProperty(modelObject, propertyName, properties);
TryGetReportProperty(modelObject, propertyName, reportProperties);
}

return properties;
return reportProperties;
}

private void TryGetReportProperty(
TSM.ModelObject modelObject,
string propertyName,
Dictionary<string, object?> properties
Dictionary<string, Dictionary<string, object?>> properties
)
{
var reportProperty = new Dictionary<string, object?> { ["name"] = propertyName };

// NOTE: ModelObject.GetReportProperty has specific overloads (not generic), we need to try each overload
double doubleValue = 0.0;
int intValue = 0;
string stringValue = "";
string stringValue = string.Empty;

if (modelObject.GetReportProperty(propertyName, ref doubleValue))
{
properties[propertyName] = doubleValue;
// NOTE: It seems default is millimeter https://developer.tekla.com/doc/tekla-structures/2023/millimeters-property-12484#
reportProperty["value"] = doubleValue;
reportProperty["units"] = propertyName switch
{
"LENGTH" or "WIDTH" or "HEIGHT" => Distance.MILLIMETERS, // NOTE: This is horrible, I know! Waiting on response from Tekla
"VOLUME" => $"Cubic {Distance.MILLIMETERS.ToString().ToLower()}",
"AREA" => $"Square {Distance.MILLIMETERS.ToString().ToLower()}", // NOTE: Weird number, but corresponds with generated report
"WEIGHT" => "Kilograms",
_ => null // NOTE: No units appended for other parameters
};
}
else if (modelObject.GetReportProperty(propertyName, ref intValue))
{
properties[propertyName] = intValue;
reportProperty["value"] = intValue;
}
else if (modelObject.GetReportProperty(propertyName, ref stringValue) && !string.IsNullOrEmpty(stringValue))
{
properties[propertyName] = stringValue;
reportProperty["value"] = stringValue;
}

// NOTE: Only assign if it actually contains a value
if (reportProperty.ContainsKey("value"))
{
properties[propertyName] = reportProperty;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public Base Convert(object target)
Dictionary<string, object?> properties = new();

// get report properties
var reportProperties = _reportPropertyExtractor.GetProperties(modelObject);
var reportProperties = _reportPropertyExtractor.GetReportProperties(modelObject);
if (reportProperties.Count > 0)
{
properties["report"] = reportProperties;
Expand Down

0 comments on commit 8822761

Please sign in to comment.