├── .github └── workflows │ └── contrast_security_app.yaml ├── .gitignore ├── CreatingAndAnalyzingModel ├── BeamDeflectionResults.cs ├── ColumnResults.cs ├── CreateLoading.cs ├── CreateModelObjects.cs ├── CreatingAndAnalyzingModel.csproj ├── MidSpanResults.cs ├── Program.cs └── ResultsOutput.cs ├── ExportingFireCheckDataToUDA ├── Commands.cs ├── DataApplier.cs ├── DataCollector.cs ├── ExportingFireCheckDataToUDA.csproj ├── Extensions │ ├── CalculationsNodeExtensions.cs │ ├── ReadOnlyPropertyExtensions.cs │ └── ReportTableExtensions.cs ├── FireCheckData.cs ├── Orchestrator.cs ├── Program.cs └── ProgressIndicator.cs ├── Extracting1DElementData ├── App.config ├── ApplicationPage.Designer.cs ├── ApplicationPage.cs ├── ApplicationPage.resx ├── ConnectionForm.Designer.cs ├── ConnectionForm.cs ├── ConnectionForm.resx ├── Exporters │ └── Element1dExporter.cs ├── Extracting1DElementData.csproj ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Program.cs └── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── ExtractingModelData ├── DataOutputFileCreator.cs ├── ExtractingModelData.csproj ├── OutputConnectionData.cs ├── OutputMemberData.cs ├── OutputSlabData.cs ├── OutputWallData.cs └── Program.cs ├── ExtractingResultsTableItem ├── ExtractingResultsTableItem.csproj ├── Program.cs └── ResultsValuesOutputter.cs ├── ExtractingSteelBeamData ├── ExtractingSteelBeamData.csproj └── ExtractingSteelBeamDataExample.cs ├── LICENSE ├── PythonNetExperiment ├── Program.cs ├── PythonNetExperiment.csproj ├── PythonNetExperiment.py ├── PythonNetExperiment.sln └── TsdApiPythonGuide.md ├── README.md ├── ReactingToSelection ├── App.xaml ├── App.xaml.cs ├── AssemblyInfo.cs ├── Helpers │ ├── ListWithNotify.cs │ ├── ReadOnlyPropertyExtensions.cs │ ├── RelayCommand.cs │ ├── TaskExtensions.cs │ ├── UiHelpers.cs │ └── ViewModelBase.cs ├── Models │ ├── ConnectionFetcher.cs │ ├── MemberSpanFetcher.cs │ └── Model.cs ├── ReactingToSelection.csproj ├── ViewModels │ ├── AnchorPlate.cs │ ├── BasePlate.cs │ ├── BasePlateAsymmetricBoltLayout.cs │ ├── BasePlateBoltData.cs │ ├── BasePlateBoltLayout.cs │ ├── BasePlateConcreteData.cs │ ├── BasePlateFourBoltLayout.cs │ ├── BasePlateProperties.cs │ ├── BasePlateSymmetricBoltLayout.cs │ ├── BasePlateWelds.cs │ ├── Bolt.cs │ ├── BoltEc.cs │ ├── BoltUs.cs │ ├── ConnectedMember.cs │ ├── Connection.cs │ ├── ConnectionDetails.cs │ ├── MainWindowViewModel.cs │ ├── SpanReleases.cs │ ├── SupportReaction.cs │ └── WeldedWasher.cs └── Views │ ├── AnchorPlate.xaml │ ├── AnchorPlate.xaml.cs │ ├── BasePlate.xaml │ ├── BasePlate.xaml.cs │ ├── BasePlateAsymmetricBoltLayout.xaml │ ├── BasePlateAsymmetricBoltLayout.xaml.cs │ ├── BasePlateBoltData.xaml │ ├── BasePlateBoltData.xaml.cs │ ├── BasePlateBoltLayout.xaml │ ├── BasePlateBoltLayout.xaml.cs │ ├── BasePlateConcreteData.xaml │ ├── BasePlateConcreteData.xaml.cs │ ├── BasePlateFourBoltLayout.xaml │ ├── BasePlateFourBoltLayout.xaml.cs │ ├── BasePlateProperties.xaml │ ├── BasePlateProperties.xaml.cs │ ├── BasePlateSymmetricBoltLayout.xaml │ ├── BasePlateSymmetricBoltLayout.xaml.cs │ ├── BasePlateWelds.xaml │ ├── BasePlateWelds.xaml.cs │ ├── Bolt.xaml │ ├── Bolt.xaml.cs │ ├── BoltEc.xaml │ ├── BoltEc.xaml.cs │ ├── BoltUs.xaml │ ├── BoltUs.xaml.cs │ ├── ConnectedMember.xaml │ ├── ConnectedMember.xaml.cs │ ├── Connection.xaml │ ├── Connection.xaml.cs │ ├── ConnectionDetails.xaml │ ├── ConnectionDetails.xaml.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── SpanReleases.xaml │ ├── SpanReleases.xaml.cs │ ├── SupportReaction.xaml │ ├── SupportReaction.xaml.cs │ ├── WeldedWasher.xaml │ └── WeldedWasher.xaml.cs ├── ReleaseNotes ├── 2023.md ├── 2024.md └── 2025.md └── RemotingAPIExamples.sln /.github/workflows/contrast_security_app.yaml: -------------------------------------------------------------------------------- 1 | # DISCLAIMER: This workflow file has been auto-generated and committed to the repo by the GitHub App from Contrast Security. 2 | # Manual edits to this file could cause the integration to produce unexpected behavior or break. 3 | # Version: 1.0.0 4 | # Last updated: 2024-02-13T15:58:18.544081668Z 5 | name: Contrast Security App Workflow 6 | on: 7 | workflow_dispatch: 8 | push: 9 | branches: 10 | - master 11 | pull_request: 12 | types: [opened, synchronize, reopened] 13 | branches: 14 | - master 15 | jobs: 16 | fingerprint_repo: 17 | if: ${{ github.actor != 'dependabot[bot]' }} 18 | runs-on: ubuntu-22.04 19 | steps: 20 | - name: Clone repository 21 | uses: actions/checkout@v3 22 | - name: Run Contrast SCA Fingerprint 23 | id: fingerprint 24 | uses: 'Contrast-Security-OSS/contrast-sca-action@v2' 25 | with: 26 | apiKey: ${{ secrets.CONTRAST_GITHUB_APP_API_KEY }} 27 | authHeader: ${{ secrets.CONTRAST_GITHUB_APP_AUTH_HEADER }} 28 | orgId: ${{ vars.CONTRAST_GITHUB_APP_ORG_ID }} 29 | apiUrl: ${{ vars.CONTRAST_GITHUB_APP_TS_URL }} 30 | repoUrl: ${{ github.server_url }}/${{ github.repository }} 31 | repoName: ${{ github.repository }} 32 | externalId: ${{ vars.CONTRAST_GITHUB_APP_ID }} 33 | command: fingerprint 34 | outputs: 35 | fingerprint: ${{ steps.fingerprint.outputs.fingerprint }} 36 | analyze_dependencies: 37 | if: ${{ needs.fingerprint_repo.outputs.fingerprint != '' }} 38 | needs: fingerprint_repo 39 | runs-on: ubuntu-22.04 40 | strategy: 41 | fail-fast: false 42 | matrix: 43 | manifest: 44 | - ${{ fromJson(needs.fingerprint_repo.outputs.fingerprint) }} 45 | steps: 46 | - name: Clone repository 47 | uses: actions/checkout@v3 48 | - name: Run Contrast SCA Audit 49 | uses: 'Contrast-Security-OSS/contrast-sca-action@v2' 50 | with: 51 | apiKey: ${{ secrets.CONTRAST_GITHUB_APP_API_KEY }} 52 | authHeader: ${{ secrets.CONTRAST_GITHUB_APP_AUTH_HEADER }} 53 | orgId: ${{ vars.CONTRAST_GITHUB_APP_ORG_ID }} 54 | apiUrl: ${{ vars.CONTRAST_GITHUB_APP_TS_URL }} 55 | filePath: ${{ matrix.manifest.filePath }} 56 | repositoryId: ${{ matrix.manifest.repositoryId }} 57 | projectGroupId: ${{ matrix.manifest.projectGroupId }} 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Ignore thumbnails created by Windows 2 | Thumbs.db 3 | #Ignore files built by Visual Studio 4 | *.obj 5 | *.exe 6 | *.pdb 7 | *.user 8 | *.aps 9 | *.pch 10 | *.vspscc 11 | *_i.c 12 | *_p.c 13 | *.ncb 14 | *.suo 15 | *.tlb 16 | *.tlh 17 | *.bak 18 | *.cache 19 | *.ilk 20 | *.log 21 | [Bb]in 22 | [Dd]ebug/ 23 | *.lib 24 | *.sbr 25 | obj/ 26 | [Rr]elease/ 27 | _ReSharper*/ 28 | [Tt]est[Rr]esult* 29 | .vs/ 30 | #Nuget packages folder 31 | packages/ 32 | -------------------------------------------------------------------------------- /CreatingAndAnalyzingModel/BeamDeflectionResults.cs: -------------------------------------------------------------------------------- 1 | namespace CreatingAndAnalyzingModel 2 | { 3 | /// 4 | /// Stores the results required for identifying and reporting critical beam deflection 5 | /// 6 | public class BeamDeflectionResults 7 | { 8 | #region Properties 9 | 10 | /// 11 | /// Gets or sets the member name 12 | /// 13 | public string MemberName { get; set; } 14 | 15 | /// 16 | /// Gets or sets the members total length (includes all spans) (in [mm]) 17 | /// 18 | public double MemberTotalLength { get; set; } 19 | 20 | /// 21 | /// Gets or sets the name of the critical combination 22 | /// 23 | public string CriticalCombinationName { get; set; } 24 | 25 | /// 26 | /// Gets or sets the value of the maximum deflection (in [mm]) 27 | /// 28 | public double MaximumDeflectionValue { get; set; } 29 | 30 | /// 31 | /// Gets or sets the span index at which the maximum deflection occurs 32 | /// 33 | public int MaximumDeflectionSpanIndex { get; set; } 34 | 35 | /// 36 | /// Gets or sets the position at which the maximum deflection occurs, relative to the appropriate span (in [mm]) 37 | /// 38 | public double MaximumDeflectionPosition { get; set; } 39 | 40 | /// 41 | /// Gets or sets the value of the maximum moment (in [Nmm]) 42 | /// 43 | public double MaximumMomentValue { get; set; } 44 | 45 | /// 46 | /// Gets or sets the span index at which the maximum moment occurs 47 | /// 48 | public int MaximumMomentSpanIndex { get; set; } 49 | 50 | /// 51 | /// Gets or sets the position at which the maximum moment occurs, relative to the appropriate span (in [mm]) 52 | /// 53 | public double MaximumMomentPosition { get; set; } 54 | 55 | #endregion 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /CreatingAndAnalyzingModel/ColumnResults.cs: -------------------------------------------------------------------------------- 1 | namespace CreatingAndAnalyzingModel 2 | { 3 | /// 4 | /// Stores the results required for identifying and reporting critical column forces 5 | /// 6 | public class ColumnResults 7 | { 8 | #region Properties 9 | 10 | /// 11 | /// Gets or sets the member name 12 | /// 13 | public string MemberName { get; set; } 14 | 15 | /// 16 | /// Gets or sets the span number 17 | /// 18 | public int SpanNumber { get; set; } 19 | 20 | /// 21 | /// Gets or sets the span length (in [mm]) 22 | /// 23 | public double SpanLength { get; set; } 24 | 25 | /// 26 | /// Gets or sets the name of the critical combination for major moment 27 | /// 28 | public string CriticalMajorMomentCombinationName { get; set; } 29 | 30 | /// 31 | /// Gets or sets the name of the critical combination for minor moment 32 | /// 33 | public string CriticalMinorMomentCombinationName { get; set; } 34 | 35 | /// 36 | /// Gets or sets the name of the critical combination for axial force 37 | /// 38 | public string CriticalAxialForceCombinationName { get; set; } 39 | 40 | /// 41 | /// Gets or sets the value of the maximum major moment (in [Nmm]) 42 | /// 43 | public double MaximumMajorMomentValue { get; set; } 44 | 45 | /// 46 | /// Gets or sets the value of the maximum minor moment (in [Nmm]) 47 | /// 48 | public double MaximumMinorMomentValue { get; set; } 49 | 50 | /// 51 | /// Gets or sets the value of the maximum axial force (in [N]) 52 | /// 53 | public double MaximumAxialForceValue { get; set; } 54 | 55 | #endregion 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /CreatingAndAnalyzingModel/CreateLoading.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using TSD.API.Remoting.Common; 6 | using TSD.API.Remoting.Loading; 7 | using TSD.API.Remoting.Loading.Create; 8 | using TSD.API.Remoting.Structure; 9 | 10 | namespace CreatingAndAnalyzingModel 11 | { 12 | /// 13 | /// Contains methods to create the model loading 14 | /// 15 | public class CreateLoading 16 | { 17 | #region Methods 18 | 19 | public async Task Create( IModel model ) 20 | { 21 | await CreateLoads( model ); 22 | 23 | await CreateCombinations( model ); 24 | 25 | Console.WriteLine( "Loading created" ); 26 | } 27 | 28 | private static async Task CreateLoads( IModel model ) 29 | { 30 | var loadcases = (await model.GetLoadcasesAsync()).ToList(); 31 | 32 | var createLoadParams = new List(); 33 | 34 | var levels = (await model.GetLevelsAsync()).ToList(); 35 | 36 | // Create some level loading for each loadcase 37 | foreach( var loadcase in loadcases ) 38 | { 39 | var load = 0.0; 40 | 41 | if( loadcase.Name.Contains( "Dead" ) ) 42 | { 43 | load = 0.004; // 0.004 N/mm^2 = 4kN/m^2 44 | } 45 | else if( loadcase.Name.Contains( "Services" ) ) 46 | { 47 | load = 0.003; // 0.003 N/mm^2 = 3kN/m^2 48 | } 49 | else if( loadcase.Name.Contains( "Imposed" ) ) 50 | { 51 | load = 0.005; // 0.005 N/mm^2 = 5kN/m^2 52 | } 53 | else 54 | { 55 | continue; 56 | } 57 | 58 | foreach( var level in levels.Where( l => l.Level.Value > 0.001 ) ) // ignore base level 59 | { 60 | var planeLoad = ConstructionPlaneLoadParams.AlongPlaneNormal( level, load ); 61 | createLoadParams.Add( planeLoad ); 62 | } 63 | 64 | await loadcase.CreateLoadAsync( createLoadParams ); 65 | createLoadParams.Clear(); 66 | } 67 | 68 | // Create a lateral load on the structure for the imposed load case 69 | var imposedLoadcase = loadcases.First( l => l.Type.Value == LoadcaseType.Imposed ); 70 | 71 | var members = await model.GetMembersAsync(); 72 | var constructionPoints = await model.GetConstructionPointsAsync(); 73 | 74 | // Find edge beam points where X co-ordinate is 0 at first floor 75 | var edgeBeamPoints = constructionPoints.Where( c => Math.Abs( c.Coordinates.Value.X ) < 0.001 && Math.Abs( c.Coordinates.Value.Z - 3000.0 ) < 0.001 ); 76 | 77 | foreach( var member in members.Where( m => m.Data.Value.MemberType.Value == MemberType.Beam ) ) 78 | { 79 | foreach( var span in await member.GetSpanAsync( new[] { 0, member.SpanCount.Value - 1 } ) ) 80 | { 81 | if( edgeBeamPoints.Select( p => p.Index ).ToList().Contains( span.EndMemberNode.ConstructionPointIndex.Value ) ) 82 | { 83 | var memberSpanInfo = new MemberSpanInfo( member.Id, span.Id ); 84 | var memberLateralLoad = MemberFullUniformlyDistributedLoadParams.Local( memberSpanInfo, 10.0, MemberLoadParams.LoadDirectionLocal.Y ); 85 | createLoadParams.Add( memberLateralLoad ); 86 | } 87 | } 88 | } 89 | 90 | await imposedLoadcase.CreateLoadAsync( createLoadParams ); 91 | 92 | createLoadParams.Clear(); 93 | 94 | // Create a snow load 95 | var loadcaseParams = new List() 96 | { 97 | LoadcaseParams.Create(), 98 | }; 99 | 100 | await model.CreateEntityAsync( loadcaseParams ); 101 | 102 | var snowLoadcase = (await model.GetLoadcasesAsync()).Last(); 103 | 104 | await snowLoadcase.UserName.SetValueAndUpdateAsync( "Snow" ); 105 | await snowLoadcase.Type.SetValueAndUpdateAsync( LoadcaseType.Snow ); 106 | 107 | var roofSlab = (await model.GetSlabsAsync()).Last(); 108 | var slabSnowLoad = SlabLoadParams.AlongSlabNormal( roofSlab, 0.00063 ); 109 | createLoadParams.Add( slabSnowLoad ); 110 | await snowLoadcase.CreateLoadAsync( createLoadParams ); 111 | } 112 | 113 | private static async Task CreateCombinations( IModel model ) 114 | { 115 | var loadcases = (await model.GetLoadcasesAsync()).ToList(); 116 | 117 | var cbParams = new List() 118 | { 119 | CombinationParams.Create(), 120 | }; 121 | 122 | // Create 4 combinations 123 | for( int i = 0; i < 4; i++ ) 124 | { 125 | await model.CreateEntityAsync( cbParams ); 126 | } 127 | 128 | var combinations = (await model.GetCombinationsAsync()).ToList(); 129 | 130 | foreach( var combination in combinations ) 131 | { 132 | switch( combination.Index ) 133 | { 134 | case 1: 135 | await combination.UserName.SetValueAndUpdateAsync( "Dead + Imposed" ); 136 | 137 | break; 138 | 139 | case 2: 140 | await combination.UserName.SetValueAndUpdateAsync( "Dead only" ); 141 | 142 | break; 143 | 144 | case 3: 145 | await combination.UserName.SetValueAndUpdateAsync( "Imposed only" ); 146 | 147 | break; 148 | 149 | case 4: 150 | await combination.UserName.SetValueAndUpdateAsync( "Dead + Imposed + Snow" ); 151 | 152 | break; 153 | } 154 | 155 | // Add each loadcase to the combination 156 | foreach( var loadcase in loadcases ) 157 | { 158 | if( AddLoadcaseToCombination( combination.Index, loadcase.Type.Value ) ) 159 | await combination.AddLoadcaseAsync( loadcase ); 160 | } 161 | } 162 | 163 | // Create an envelope of all combinations 164 | var envParams = new List() 165 | { 166 | EnvelopeParams.Create(), 167 | }; 168 | 169 | await model.CreateEntityAsync( envParams ); 170 | 171 | var envelope = (await model.GetEnvelopesAsync()).ToList().FirstOrDefault(); 172 | 173 | if( envelope == null ) 174 | return; 175 | 176 | foreach( var combination in combinations ) 177 | { 178 | await envelope.AddCombinationAsync( combination ); 179 | } 180 | 181 | bool AddLoadcaseToCombination( int combinationIndex, LoadcaseType loadcaseType ) 182 | { 183 | if( combinationIndex == 1 && (loadcaseType == LoadcaseType.Dead || loadcaseType == LoadcaseType.Imposed) ) 184 | return true; 185 | 186 | if( combinationIndex == 2 && loadcaseType is LoadcaseType.Dead ) 187 | return true; 188 | 189 | if( combinationIndex == 3 && loadcaseType is LoadcaseType.Imposed ) 190 | return true; 191 | 192 | if( combinationIndex == 4 && (loadcaseType == LoadcaseType.Dead || loadcaseType == LoadcaseType.Imposed || loadcaseType == LoadcaseType.Snow) ) 193 | return true; 194 | 195 | return false; 196 | } 197 | } 198 | 199 | #endregion 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /CreatingAndAnalyzingModel/CreatingAndAnalyzingModel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 7.3 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /CreatingAndAnalyzingModel/MidSpanResults.cs: -------------------------------------------------------------------------------- 1 | namespace CreatingAndAnalyzingModel 2 | { 3 | /// 4 | /// Stores the results required for identifying and reporting mid span forces 5 | /// 6 | public class MidSpanResults 7 | { 8 | #region Properties 9 | 10 | /// 11 | /// Gets or sets the member name 12 | /// 13 | public string MemberName { get; set; } 14 | 15 | /// 16 | /// Gets or sets the span index 17 | /// 18 | public int SpanIndex { get; set; } 19 | 20 | /// 21 | /// Gets or sets the position of the mid span (in [mm]) 22 | /// 23 | public double MidSpanPosition { get; set; } 24 | 25 | /// 26 | /// Gets or sets the name of the combination 27 | /// 28 | public string CombinationName { get; set; } 29 | 30 | /// 31 | /// Gets or sets the value of the major moment at the mid span (in [Nmm]) 32 | /// 33 | public double MidSpanMajorMomentValue { get; set; } 34 | 35 | /// 36 | /// Gets or sets the value of the major shear at the mid span (in [N]) 37 | /// 38 | public double MidSpanMajorShearValue { get; set; } 39 | 40 | /// 41 | /// Gets or sets the value of the axial force at the mid span (in [N]) 42 | /// 43 | public double MidSpanAxialValue { get; set; } 44 | 45 | /// 46 | /// Gets or sets the value of the torsion at the mid span (in [Nmm]) 47 | /// 48 | public double MidSpanTorsionValue { get; set; } 49 | 50 | /// 51 | /// Gets or sets the value of the deflection at the mid span (in [mm]) 52 | /// 53 | public double MidSpanDeflectionValue { get; set; } 54 | 55 | #endregion 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /CreatingAndAnalyzingModel/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using TSD.API.Remoting; 6 | using TSD.API.Remoting.Solver; 7 | 8 | namespace CreatingAndAnalyzingModel 9 | { 10 | class Program 11 | { 12 | public static async Task Main() 13 | { 14 | // Get the first running TSD instance found 15 | using( var tsdInstance = await ApplicationFactory.GetFirstRunningApplicationAsync() ) 16 | { 17 | if( tsdInstance == null ) 18 | { 19 | Console.WriteLine( "No running instances of TSD found!" ); 20 | 21 | return; 22 | } 23 | 24 | // Output the version number of TSD 25 | Console.WriteLine( await tsdInstance.GetVersionStringAsync() ); 26 | 27 | // Get the active document from the running instance of TSD 28 | var document = await tsdInstance.GetDocumentAsync(); 29 | 30 | if( document == null ) 31 | { 32 | Console.WriteLine( "No document was found in the TSD instance!" ); 33 | 34 | return; 35 | } 36 | 37 | // Get the model from the document 38 | var model = await document.GetModelAsync(); 39 | 40 | if( model == null ) 41 | { 42 | Console.WriteLine( "No model was found in the document!" ); 43 | 44 | return; 45 | } 46 | 47 | var createModelObjects = new CreateModelObjects(); 48 | await createModelObjects.Create( model ); 49 | 50 | var createLoading = new CreateLoading(); 51 | await createLoading.Create( model ); 52 | 53 | await RunValidation( model ); 54 | 55 | var requestedAnalysisType = AnalysisType.FirstOrderLinear; 56 | 57 | var solvedLoading = await RunAnalysis( model, requestedAnalysisType ); 58 | 59 | var resultsOutput = new ResultsOutput(); 60 | await resultsOutput.OutputResults( model, solvedLoading, requestedAnalysisType ); 61 | } 62 | } 63 | 64 | private static async Task RunValidation( TSD.API.Remoting.Structure.IModel model ) 65 | { 66 | await model.ValidateAsync(); 67 | 68 | var validationData = await model.GetValidationDataAsync(); 69 | 70 | Console.WriteLine( validationData.OverallStatus.Value.ToString() ); 71 | } 72 | 73 | private static async Task> RunAnalysis( TSD.API.Remoting.Structure.IModel model, AnalysisType requestedAnalysisType ) 74 | { 75 | var analysedLoading = await model.RunAnalysisAsync( requestedAnalysisType ); 76 | 77 | Console.WriteLine( requestedAnalysisType.ToString() + " analysis complete" ); 78 | 79 | return analysedLoading; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /ExportingFireCheckDataToUDA/Commands.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | 3 | namespace ExportingFireCheckDataToUDA; 4 | 5 | /// 6 | /// Contains command line commands 7 | /// 8 | internal static class Commands 9 | { 10 | #region Fields 11 | 12 | /// 13 | /// The option for API port 14 | /// 15 | private static readonly Option _apiPortOption = new( "--api-port", "The port TSD API is listening on." ); 16 | 17 | #endregion 18 | 19 | #region Properties 20 | 21 | /// 22 | /// Gets the root command 23 | /// 24 | public static RootCommand RootCommand 25 | { 26 | get 27 | { 28 | var command = new RootCommand 29 | { 30 | _apiPortOption, 31 | }; 32 | 33 | command.SetHandler( Orchestrator.ExportDataToUdaAsync, _apiPortOption ); 34 | 35 | return command; 36 | } 37 | } 38 | 39 | #endregion 40 | } 41 | -------------------------------------------------------------------------------- /ExportingFireCheckDataToUDA/ExportingFireCheckDataToUDA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | 12.0 7 | enable 8 | enable 9 | false 10 | 11 | 12 | 13 | bin\publish 14 | en-US 15 | false 16 | true 17 | 18 | 19 | 20 | 21 | 22 | $(AllowedReferenceRelatedFileExtensions.Replace('.pdb;','').Replace('.xml;','')) 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ExportingFireCheckDataToUDA/Extensions/CalculationsNodeExtensions.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Report; 2 | 3 | namespace ExportingFireCheckDataToUDA.Extensions; 4 | 5 | /// 6 | /// Contains extension methods for 7 | /// 8 | internal static class CalculationsNodeExtensions 9 | { 10 | #region Methods 11 | 12 | /// 13 | /// Returns a child node of the given node with the specified name 14 | /// 15 | /// The node to query the child nodes of 16 | /// The name of the node to look for 17 | /// Returns a child node of the given node with the specified name (or if no such exists) 18 | public static ICalculationsNode? GetChildNode( this ICalculationsNode node, string name ) 19 | => node.Nodes.SingleOrDefault( n => n.Name.Equals( name, StringComparison.InvariantCultureIgnoreCase ) ); 20 | 21 | /// 22 | /// Returns a child node of the given node that matches the predicate 23 | /// 24 | /// The node to query the child nodes of 25 | /// The predicate to use to look for the child node 26 | /// Returns a child node of the given node that matches the predicate (or if no such exists) 27 | public static ICalculationsNode? GetChildNode( this ICalculationsNode node, Func predicate ) 28 | => node.Nodes.SingleOrDefault( predicate ); 29 | 30 | #endregion 31 | } 32 | -------------------------------------------------------------------------------- /ExportingFireCheckDataToUDA/Extensions/ReadOnlyPropertyExtensions.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Common.Properties; 2 | 3 | namespace ExportingFireCheckDataToUDA.Extensions; 4 | 5 | /// 6 | /// Contains extension methods for the interface 7 | /// 8 | internal static class ReadOnlyPropertyExtensions 9 | { 10 | #region Methods 11 | 12 | /// 13 | /// Returns the value of this property or the given default value in case the property is not applicable 14 | /// 15 | /// The property to get value of 16 | /// The default value to use in case the property is not applicable 17 | /// The type of value stored in the property 18 | public static TValue? GetValueOrDefault( this IReadOnlyProperty property, TValue? defaultValue = default ) 19 | => property is { IsApplicable: true } ? property.Value : defaultValue; 20 | 21 | #endregion 22 | } 23 | -------------------------------------------------------------------------------- /ExportingFireCheckDataToUDA/Extensions/ReportTableExtensions.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Report; 2 | 3 | namespace ExportingFireCheckDataToUDA.Extensions; 4 | 5 | /// 6 | /// Contains extension methods for 7 | /// 8 | internal static class ReportTableExtensions 9 | { 10 | #region Methods 11 | 12 | /// 13 | /// Returns a value associated with item with the given name from the specified table 14 | /// 15 | /// The table to retrieve value from 16 | /// The name of the item to retrieve value of 17 | public static double? GetValue( this IReportTable table, string name ) 18 | { 19 | if( table.GetLine( name ) is not { } line ) 20 | return null; 21 | 22 | var itemWithValue = line.Items 23 | .OfType() 24 | .FirstOrDefault(); 25 | 26 | return itemWithValue is { Value: var value } ? value : null; 27 | } 28 | 29 | /// 30 | /// Returns a line containing an item with the given name from the specified table 31 | /// 32 | /// The table to retrieve line from 33 | /// The name of the item to retrieve the associated line 34 | public static IReportTableLine? GetLine( this IReportTable table, string name ) 35 | => table.Lines.FirstOrDefault( l => l.Items.OfType().Any( i => i.Text.Equals( name ) ) ); 36 | 37 | #endregion 38 | } 39 | -------------------------------------------------------------------------------- /ExportingFireCheckDataToUDA/FireCheckData.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Structure; 2 | 3 | namespace ExportingFireCheckDataToUDA; 4 | 5 | /// 6 | /// Contains the fire check data 7 | /// 8 | /// The owning member of the span the fire check data belong to 9 | /// The member span the fire check data belong to 10 | /// The fire exposure of the member span 11 | /// The time of fire exposure of the member span 12 | /// The critical temperature for the member span 13 | /// The ambient utilization ratio for the member span 14 | /// The load reduction factor for the member span 15 | /// The reference index of the combination 16 | internal readonly record struct FireCheckData( 17 | IMember Member, 18 | IMemberSpan MemberSpan, 19 | ExposedSides? Exposure, 20 | TimeOfFireExposure? NominalFireExposure, 21 | double? CriticalTemperature, 22 | double? AmbientUtilizationRatio, 23 | double? LoadReductionFactor, 24 | int? CombinationReferenceIndex 25 | ); 26 | -------------------------------------------------------------------------------- /ExportingFireCheckDataToUDA/Orchestrator.cs: -------------------------------------------------------------------------------- 1 | using ExportingFireCheckDataToUDA.Extensions; 2 | using TSD.API.Remoting; 3 | using TSD.API.Remoting.Materials; 4 | using TSD.API.Remoting.Structure; 5 | 6 | namespace ExportingFireCheckDataToUDA; 7 | 8 | /// 9 | /// Orchestrates the whole export process 10 | /// 11 | internal static class Orchestrator 12 | { 13 | #region Methods 14 | 15 | /// 16 | /// Exports the fire check data to UDA 17 | /// 18 | /// The port TSD API is listening on (if the first running application will be used) 19 | public static async Task ExportDataToUdaAsync( int? apiPort ) 20 | { 21 | var model = await GetModelAsync( apiPort ); 22 | 23 | var eligibleMembers = (await model.GetMembersAsync()) 24 | .Where( IsEligible ) 25 | .ToList(); 26 | 27 | Console.WriteLine( $"Found {eligibleMembers.Count} eligible members" ); 28 | 29 | var spans = new System.Collections.Concurrent.ConcurrentBag<(IMember Member, IEnumerable Spans)>(); 30 | 31 | await Task.Run( () => Parallel.ForEachAsync( eligibleMembers, async ( m, cancellationToken ) => 32 | { 33 | spans.Add( (Member: m, await m.GetSpanAsync( cancellationToken: cancellationToken )) ); 34 | } ) ); 35 | 36 | var fireCheckData = spans 37 | .SelectMany( tuple => tuple.Spans.Select( s => GetFireCheckData( tuple.Member, s ) ) ) 38 | .ToList(); 39 | 40 | Console.WriteLine( $"Found {fireCheckData.Count} eligible member spans" ); 41 | 42 | var dataList = await DataCollector.PopulateFireCheckDataAsync( fireCheckData ); 43 | 44 | await DataApplier.ApplyFireCheckDataAsync( model, dataList ); 45 | } 46 | 47 | /// 48 | /// Returns a value indicating whether the given member is eligible for the fire check 49 | /// 50 | /// The member to check 51 | private static bool IsEligible( IMember member ) 52 | { 53 | if( member.Data.GetValueOrDefault() is not { } memberData ) 54 | return false; 55 | 56 | if( memberData.MaterialType.GetValueOrDefault() is not MaterialType.Steel and not MaterialType.ColdFormed ) 57 | return false; 58 | 59 | return true; 60 | } 61 | 62 | /// 63 | /// Returns a fire check data associated with the given member span 64 | /// 65 | /// The owning member of the span to check 66 | /// The member span to check 67 | /// Returns a fire check data associated with the given member span (or in case the member span is not eligible) 68 | private static FireCheckData GetFireCheckData( IMember member, IMemberSpan memberSpan ) 69 | { 70 | var fireCheckData = memberSpan.FireCheckData.GetValueOrDefault(); 71 | 72 | return new FireCheckData 73 | { 74 | Member = member, 75 | MemberSpan = memberSpan, 76 | Exposure = fireCheckData?.ExposedSides.IsApplicable is true ? fireCheckData.ExposedSides.Value : null, 77 | NominalFireExposure = fireCheckData?.TimeOfFireExposure.IsApplicable is true ? fireCheckData.TimeOfFireExposure.Value : null, 78 | }; 79 | } 80 | 81 | /// 82 | /// Returns the currently active model 83 | /// 84 | /// The port TSD API is listening on (if the first running application will be used) 85 | private static async Task GetModelAsync( int? apiPort ) 86 | { 87 | var application = await ConnectAsync( apiPort ); 88 | 89 | if( await application.GetDocumentAsync() is not { } document ) 90 | throw new InvalidOperationException( "Could not obtain document!" ); 91 | 92 | if( await document.GetModelAsync() is not { } model ) 93 | throw new InvalidOperationException( "Could not obtain model!" ); 94 | 95 | return model; 96 | } 97 | 98 | /// 99 | /// Connects to TSD 100 | /// 101 | /// The port TSD API is listening on (if the first running application will be used) 102 | /// The connected application 103 | private static async Task ConnectAsync( int? apiPort ) 104 | { 105 | if( apiPort is { } specifiedPort ) 106 | { 107 | if( await ApplicationFactory.ConnectToRunningApplicationAsync( specifiedPort ) is not { } application ) 108 | throw new InvalidOperationException( $"Could not connect to TSD API at port {specifiedPort}!" ); 109 | 110 | return application; 111 | } 112 | else 113 | { 114 | if( await ApplicationFactory.GetFirstRunningApplicationAsync() is not { } application ) 115 | throw new InvalidOperationException( "Could not connect to TSD API!" ); 116 | 117 | return application; 118 | } 119 | } 120 | 121 | #endregion 122 | } 123 | -------------------------------------------------------------------------------- /ExportingFireCheckDataToUDA/Program.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | 3 | namespace ExportingFireCheckDataToUDA; 4 | 5 | /// 6 | /// Contains entry point of the application 7 | /// 8 | internal static class Program 9 | { 10 | #region Methods 11 | 12 | /// 13 | /// Executes the application logic 14 | /// 15 | /// The command line arguments 16 | /// The exit code indicating how the application terminated 17 | private static int Main( string[] args ) => Commands.RootCommand.Invoke( args ); 18 | 19 | #endregion 20 | } 21 | -------------------------------------------------------------------------------- /ExportingFireCheckDataToUDA/ProgressIndicator.cs: -------------------------------------------------------------------------------- 1 | namespace ExportingFireCheckDataToUDA; 2 | 3 | /// 4 | /// Contains methods for indicating progress 5 | /// 6 | internal static class ProgressIndicator 7 | { 8 | #region Methods 9 | 10 | /// 11 | /// Returns the text indicating the current progress 12 | /// 13 | /// The number of decimal places of the total number of data chunks 14 | /// The index of the currently processed data chunk 15 | /// The total number of data chunks 16 | public static string GetText( int decimalPlaces, int currentChunkIndex, int totalChunkCount ) 17 | => $"{(currentChunkIndex + 1).ToString().PadLeft( decimalPlaces )}/{totalChunkCount}"; 18 | 19 | #endregion 20 | } 21 | -------------------------------------------------------------------------------- /Extracting1DElementData/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Extracting1DElementData/ApplicationPage.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | False 122 | 123 | 124 | False 125 | 126 | 127 | False 128 | 129 | 130 | False 131 | 132 | 133 | False 134 | 135 | 136 | False 137 | 138 | -------------------------------------------------------------------------------- /Extracting1DElementData/ConnectionForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Extracting1DElementData 2 | { 3 | partial class ConnectionForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose( bool disposing ) 15 | { 16 | if( disposing && (components != null) ) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose( disposing ); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.Windows.Forms.Label label1; 32 | System.Windows.Forms.Label label2; 33 | this._address = new System.Windows.Forms.TextBox(); 34 | this._port = new System.Windows.Forms.TextBox(); 35 | this._cancel = new System.Windows.Forms.Button(); 36 | this._ok = new System.Windows.Forms.Button(); 37 | label1 = new System.Windows.Forms.Label(); 38 | label2 = new System.Windows.Forms.Label(); 39 | this.SuspendLayout(); 40 | // 41 | // label1 42 | // 43 | label1.AutoSize = true; 44 | label1.Location = new System.Drawing.Point(12, 9); 45 | label1.Name = "label1"; 46 | label1.Size = new System.Drawing.Size(51, 13); 47 | label1.TabIndex = 0; 48 | label1.Text = "Address :"; 49 | // 50 | // label2 51 | // 52 | label2.AutoSize = true; 53 | label2.Location = new System.Drawing.Point(12, 35); 54 | label2.Name = "label2"; 55 | label2.Size = new System.Drawing.Size(32, 13); 56 | label2.TabIndex = 1; 57 | label2.Text = "Port :"; 58 | // 59 | // _address 60 | // 61 | this._address.Location = new System.Drawing.Point(68, 6); 62 | this._address.Name = "_address"; 63 | this._address.Size = new System.Drawing.Size(112, 20); 64 | this._address.TabIndex = 1; 65 | this._address.Text = "localhost"; 66 | // 67 | // _port 68 | // 69 | this._port.Location = new System.Drawing.Point(68, 32); 70 | this._port.Name = "_port"; 71 | this._port.Size = new System.Drawing.Size(112, 20); 72 | this._port.TabIndex = 0; 73 | this._port.TextChanged += new System.EventHandler(this.OnPortTextChanged); 74 | // 75 | // _cancel 76 | // 77 | this._cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 78 | this._cancel.Location = new System.Drawing.Point(15, 58); 79 | this._cancel.Name = "_cancel"; 80 | this._cancel.Size = new System.Drawing.Size(75, 23); 81 | this._cancel.TabIndex = 3; 82 | this._cancel.Text = "Cancel"; 83 | this._cancel.UseVisualStyleBackColor = true; 84 | // 85 | // _ok 86 | // 87 | this._ok.DialogResult = System.Windows.Forms.DialogResult.OK; 88 | this._ok.Location = new System.Drawing.Point(105, 58); 89 | this._ok.Name = "_ok"; 90 | this._ok.Size = new System.Drawing.Size(75, 23); 91 | this._ok.TabIndex = 2; 92 | this._ok.Text = "OK"; 93 | this._ok.UseVisualStyleBackColor = true; 94 | // 95 | // ConnectionForm 96 | // 97 | this.AcceptButton = this._ok; 98 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 99 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 100 | this.CancelButton = this._cancel; 101 | this.ClientSize = new System.Drawing.Size(194, 93); 102 | this.ControlBox = false; 103 | this.Controls.Add(this._ok); 104 | this.Controls.Add(this._cancel); 105 | this.Controls.Add(this._port); 106 | this.Controls.Add(this._address); 107 | this.Controls.Add(label2); 108 | this.Controls.Add(label1); 109 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 110 | this.Name = "ConnectionForm"; 111 | this.ShowInTaskbar = false; 112 | this.Text = "Connect to..."; 113 | this.ResumeLayout(false); 114 | this.PerformLayout(); 115 | 116 | } 117 | 118 | #endregion 119 | 120 | private System.Windows.Forms.TextBox _address; 121 | private System.Windows.Forms.TextBox _port; 122 | private System.Windows.Forms.Button _cancel; 123 | private System.Windows.Forms.Button _ok; 124 | } 125 | } -------------------------------------------------------------------------------- /Extracting1DElementData/ConnectionForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace Extracting1DElementData 5 | { 6 | public partial class ConnectionForm : Form 7 | { 8 | public ConnectionForm() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | private void OnPortTextChanged( object sender, EventArgs e ) 14 | { 15 | _ok.Enabled = _port.Text.Length > 0 && int.TryParse( _port.Text, out _ ); 16 | } 17 | 18 | public string Host => _address.Text; 19 | 20 | public int Port => int.Parse( _port.Text ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Extracting1DElementData/ConnectionForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | False 122 | 123 | 124 | False 125 | 126 | -------------------------------------------------------------------------------- /Extracting1DElementData/Extracting1DElementData.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0-windows 5 | WinExe 6 | Copyright © 2022 7 | 1.0.0.0 8 | true 9 | 7.3 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Extracting1DElementData/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Extracting1DElementData 2 | { 3 | partial class MainForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose( bool disposing ) 15 | { 16 | if( disposing && (components != null) ) 17 | { 18 | Clear(); 19 | components.Dispose(); 20 | } 21 | base.Dispose( disposing ); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this._refreshButton = new System.Windows.Forms.Button(); 33 | this._statusLabel = new System.Windows.Forms.Label(); 34 | this._table = new System.Windows.Forms.TableLayoutPanel(); 35 | this._directConnect = new System.Windows.Forms.Button(); 36 | this.SuspendLayout(); 37 | // 38 | // _refreshButton 39 | // 40 | this._refreshButton.Location = new System.Drawing.Point(12, 12); 41 | this._refreshButton.Name = "_refreshButton"; 42 | this._refreshButton.Size = new System.Drawing.Size(75, 23); 43 | this._refreshButton.TabIndex = 1; 44 | this._refreshButton.Text = "Refresh"; 45 | this._refreshButton.UseVisualStyleBackColor = true; 46 | this._refreshButton.Click += new System.EventHandler(this.OnRefreshButtonClick); 47 | // 48 | // _statusLabel 49 | // 50 | this._statusLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 51 | | System.Windows.Forms.AnchorStyles.Right))); 52 | this._statusLabel.AutoSize = true; 53 | this._statusLabel.Location = new System.Drawing.Point(218, 17); 54 | this._statusLabel.Name = "_statusLabel"; 55 | this._statusLabel.Size = new System.Drawing.Size(35, 13); 56 | this._statusLabel.TabIndex = 2; 57 | this._statusLabel.Text = "label1"; 58 | // 59 | // _table 60 | // 61 | this._table.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 62 | | System.Windows.Forms.AnchorStyles.Left) 63 | | System.Windows.Forms.AnchorStyles.Right))); 64 | this._table.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.InsetDouble; 65 | this._table.ColumnCount = 2; 66 | this._table.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); 67 | this._table.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); 68 | this._table.Location = new System.Drawing.Point(12, 41); 69 | this._table.Name = "_table"; 70 | this._table.RowCount = 2; 71 | this._table.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); 72 | this._table.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); 73 | this._table.Size = new System.Drawing.Size(733, 427); 74 | this._table.TabIndex = 3; 75 | // 76 | // _directConnect 77 | // 78 | this._directConnect.Location = new System.Drawing.Point(93, 12); 79 | this._directConnect.Name = "_directConnect"; 80 | this._directConnect.Size = new System.Drawing.Size(119, 23); 81 | this._directConnect.TabIndex = 4; 82 | this._directConnect.Text = "Direct connection..."; 83 | this._directConnect.UseVisualStyleBackColor = true; 84 | this._directConnect.Click += new System.EventHandler(this.OnDirectConnectClick); 85 | // 86 | // MainForm 87 | // 88 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 89 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 90 | this.ClientSize = new System.Drawing.Size(757, 480); 91 | this.Controls.Add(this._directConnect); 92 | this.Controls.Add(this._table); 93 | this.Controls.Add(this._statusLabel); 94 | this.Controls.Add(this._refreshButton); 95 | this.Name = "MainForm"; 96 | this.Text = "TSD API 2 Sample Application"; 97 | this.ResumeLayout(false); 98 | this.PerformLayout(); 99 | 100 | } 101 | 102 | #endregion 103 | private System.Windows.Forms.Button _refreshButton; 104 | private System.Windows.Forms.Label _statusLabel; 105 | private System.Windows.Forms.TableLayoutPanel _table; 106 | private System.Windows.Forms.Button _directConnect; 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /Extracting1DElementData/MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | using TSD.API.Remoting; 7 | 8 | namespace Extracting1DElementData 9 | { 10 | public partial class MainForm : Form 11 | { 12 | #region Fields 13 | 14 | private List _pages = new List(); 15 | 16 | #endregion 17 | 18 | #region Constructors 19 | 20 | public MainForm() 21 | { 22 | InitializeComponent(); 23 | UpdateStatus(); 24 | } 25 | 26 | #endregion 27 | 28 | #region Overrides 29 | 30 | protected override void OnLoad( EventArgs e ) 31 | { 32 | Clear(); 33 | base.OnLoad( e ); 34 | } 35 | 36 | #endregion 37 | 38 | #region Methods 39 | 40 | private void Clear() 41 | { 42 | foreach( var page in _pages.ToArray() ) 43 | { 44 | RemovePage( page ); 45 | } 46 | 47 | _pages.Clear(); 48 | _table.RowCount = 0; 49 | _table.ColumnCount = 0; 50 | } 51 | 52 | private void UpdateStatus() 53 | { 54 | _statusLabel.Text = $"Found {_pages.Count} running TSD applications"; 55 | } 56 | 57 | /// 58 | /// Enumerates running TSD instances and for each one adds application page 59 | /// 60 | /// 61 | private async Task FindApplicationsAsync() 62 | { 63 | foreach( var page in (await ApplicationFactory.GetRunningApplicationsAsync()).Select( app => new ApplicationPage( app ) ) ) 64 | AddPage( page ); 65 | 66 | UpdateStatus(); 67 | } 68 | 69 | private void AddPage( ApplicationPage page ) 70 | { 71 | _pages.Add( page ); 72 | FillTable(); 73 | page.Show(); 74 | page.Disconnected += OnPageDisconnected; 75 | } 76 | 77 | private void RemovePage( ApplicationPage page ) 78 | { 79 | page.Disconnected -= OnPageDisconnected; 80 | page.Dispose(); 81 | _pages.Remove( page ); 82 | FillTable(); 83 | } 84 | 85 | private void FillTable() 86 | { 87 | _table.SuspendLayout(); 88 | _table.ResumeLayout(); 89 | 90 | int toPlace = Math.Min( 8, _pages.Count ); 91 | _table.RowCount = toPlace > 2 ? 2 : 1; 92 | _table.ColumnCount = (int) Math.Ceiling( (double) toPlace / _table.RowCount ); 93 | 94 | _table.Controls.Clear(); 95 | 96 | for( int i = 0; i < toPlace; i++ ) 97 | _table.Controls.Add( _pages[i] ); 98 | 99 | _table.PerformLayout(); 100 | } 101 | 102 | #endregion 103 | 104 | #region Event Handlers 105 | 106 | private async void OnRefreshButtonClick( object sender, EventArgs e ) 107 | { 108 | _refreshButton.Enabled = false; 109 | 110 | Clear(); 111 | await FindApplicationsAsync(); 112 | 113 | _refreshButton.Enabled = true; 114 | } 115 | 116 | private async void OnDirectConnectClick( object sender, EventArgs e ) 117 | { 118 | _directConnect.Enabled = false; 119 | 120 | using( var form = new ConnectionForm() ) 121 | { 122 | if( form.ShowDialog() == DialogResult.OK ) 123 | { 124 | var app = await ApplicationFactory.ConnectToRunningApplicationAsync( form.Host, form.Port ); 125 | 126 | if( app != null ) 127 | { 128 | AddPage( new ApplicationPage( app ) ); 129 | UpdateStatus(); 130 | } 131 | } 132 | } 133 | 134 | _directConnect.Enabled = true; 135 | } 136 | 137 | /// 138 | /// Removes disconnected page 139 | /// 140 | private void OnPageDisconnected( object sender, EventArgs e ) 141 | { 142 | RemovePage( (ApplicationPage) sender ); 143 | UpdateStatus(); 144 | } 145 | 146 | #endregion 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Extracting1DElementData/MainForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Extracting1DElementData/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace Extracting1DElementData 5 | { 6 | static class Program 7 | { 8 | /// 9 | /// The main entry point for the application. 10 | /// 11 | [STAThread] 12 | static void Main() 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault( false ); 16 | Application.Run( new MainForm() ); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Extracting1DElementData/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | [assembly: ComVisible( false )] 4 | -------------------------------------------------------------------------------- /Extracting1DElementData/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Extracting1DElementData.Properties { 12 | /// 13 | /// A strongly-typed resource class, for looking up localized strings, etc. 14 | /// 15 | // This class was auto-generated by the StronglyTypedResourceBuilder 16 | // class via a tool like ResGen or Visual Studio. 17 | // To add or remove a member, edit your .ResX file then rerun ResGen 18 | // with the /str option, or rebuild your VS project. 19 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 20 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 21 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 22 | internal class Resources { 23 | 24 | private static global::System.Resources.ResourceManager resourceMan; 25 | 26 | private static global::System.Globalization.CultureInfo resourceCulture; 27 | 28 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 29 | internal Resources() { 30 | } 31 | 32 | /// 33 | /// Returns the cached ResourceManager instance used by this class. 34 | /// 35 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 36 | internal static global::System.Resources.ResourceManager ResourceManager { 37 | get { 38 | if (object.ReferenceEquals(resourceMan, null)) { 39 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TsdApiRemotingSample.Properties.Resources", typeof(Resources).Assembly); 40 | resourceMan = temp; 41 | } 42 | return resourceMan; 43 | } 44 | } 45 | 46 | /// 47 | /// Overrides the current thread's CurrentUICulture property for all 48 | /// resource lookups using this strongly typed resource class. 49 | /// 50 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 51 | internal static global::System.Globalization.CultureInfo Culture { 52 | get { 53 | return resourceCulture; 54 | } 55 | set { 56 | resourceCulture = value; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Extracting1DElementData/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /Extracting1DElementData/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TsdApiRemotingSample.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Extracting1DElementData/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ExtractingModelData/DataOutputFileCreator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace ExtractingModelData 7 | { 8 | internal static class DataOutputFileCreator 9 | { 10 | #region Constants 11 | 12 | internal const string OutputFileName = "TsdRemotingApiModelDataOutput.csv"; 13 | 14 | #endregion 15 | 16 | #region Methods 17 | 18 | public static async Task OutputDataAsync( StringBuilder stringBuilder ) 19 | { 20 | // Write the .csv file with the output data 21 | await File.WriteAllTextAsync( Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.MyDocuments ), OutputFileName ), stringBuilder.ToString() ); 22 | 23 | Console.WriteLine( "Results output complete" ); 24 | } 25 | 26 | #endregion 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ExtractingModelData/ExtractingModelData.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 7.3 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ExtractingModelData/OutputConnectionData.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Text; 3 | using System.Threading.Tasks; 4 | using TSD.API.Remoting.Structure; 5 | 6 | namespace ExtractingModelData 7 | { 8 | internal class OutputConnectionData 9 | { 10 | #region Methods 11 | 12 | public static async Task CreateConnectionDataOutputAsync( IModel model, StringBuilder stringBuilder ) 13 | { 14 | stringBuilder.AppendLine( 15 | "Connection name," + 16 | "Connection type," + 17 | "X (mm)," + 18 | "Y (mm)," + 19 | "Z (mm)," + 20 | "Connected members," ); 21 | 22 | var constructionPoints = (await model.GetConstructionPointsAsync()).ToList(); 23 | var connections = await model.GetConnectionsAsync(); 24 | 25 | foreach( var connection in connections ) 26 | { 27 | var constructionPoint = constructionPoints.FirstOrDefault( c => c.Index == connection.ConstructionPointIndex.Value ); 28 | var connectedMembers = await connection.GetConnectedMembersAsync(); 29 | 30 | stringBuilder.AppendLine( 31 | $"{connection.Name}," + 32 | $"{connection.ConnectionType.Value}," + 33 | $"{constructionPoint?.Coordinates.Value.X}," + 34 | $"{constructionPoint?.Coordinates.Value.Y}," + 35 | $"{constructionPoint?.Coordinates.Value.Z}," + 36 | $"{string.Join( ", ", connectedMembers.Select( m => m.Name ) )}," ); 37 | } 38 | 39 | stringBuilder.AppendLine( "" ); 40 | } 41 | 42 | #endregion 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ExtractingModelData/OutputMemberData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using TSD.API.Remoting.Common; 6 | using TSD.API.Remoting.Materials; 7 | using TSD.API.Remoting.Sections; 8 | using TSD.API.Remoting.Structure; 9 | 10 | namespace ExtractingModelData 11 | { 12 | internal class OutputMemberData 13 | { 14 | #region Methods 15 | 16 | public static async Task CreateMemberDataOutputAsync( IModel model, StringBuilder stringBuilder ) 17 | { 18 | var members = (await model.GetMembersAsync()).ToList(); 19 | 20 | await OutputMemberDataForMaterialAsync( model, members, stringBuilder, MaterialType.Steel ); 21 | await OutputMemberDataForMaterialAsync( model, members, stringBuilder, MaterialType.Concrete ); 22 | await OutputMemberDataForMaterialAsync( model, members, stringBuilder, MaterialType.Timber ); 23 | } 24 | 25 | public static async Task OutputMemberDataForMaterialAsync( IModel model, IEnumerable members, StringBuilder stringBuilder, MaterialType materialType ) 26 | { 27 | stringBuilder.AppendLine( $"{materialType} members" ); 28 | 29 | stringBuilder.AppendLine( 30 | "Span name," + 31 | "Section," + 32 | "Material," + 33 | "Start X (mm)," + 34 | "Start Y (mm)," + 35 | "Start Z (mm)," + 36 | "End X (mm)," + 37 | "End Y (mm)," + 38 | "End Z (mm)," + 39 | "Ratio (Static)," + 40 | "Status (Static)," ); 41 | 42 | var constructionPoints = (await model.GetConstructionPointsAsync()).ToList(); 43 | 44 | var membersToReport = members.Where( m => m.Data.Value.MaterialType.Value == materialType && IsOutputMemberType( m.Data.Value.MemberType.Value ) ); 45 | 46 | foreach( var member in membersToReport ) 47 | { 48 | foreach( var span in await member.GetSpanAsync( new[] { 0, member.SpanCount.Value - 1 } ) ) 49 | { 50 | var section = span.ElementSection.Value as IMemberSection; 51 | var startPoint = constructionPoints.First( c => c.Index == span.StartMemberNode.ConstructionPointIndex.Value ); 52 | var endPoint = constructionPoints.First( c => c.Index == span.EndMemberNode.ConstructionPointIndex.Value ); 53 | 54 | stringBuilder.AppendLine( 55 | $"{span.Name}," + 56 | $"{section?.PhysicalSection.Value.LongName}," + 57 | $"{span.Material.Value.Name}," + 58 | $"{startPoint.Coordinates.Value.X}," + 59 | $"{startPoint.Coordinates.Value.Y}," + 60 | $"{startPoint.Coordinates.Value.Z}," + 61 | $"{endPoint.Coordinates.Value.X}," + 62 | $"{endPoint.Coordinates.Value.Y}," + 63 | $"{endPoint.Coordinates.Value.Z}," + 64 | $"{span.CheckResults[CheckResultType.Static].Value.UtilizationRatio.Value}," + 65 | $"{span.CheckResults[CheckResultType.Static].Value.CheckStatus.Value}," ); 66 | } 67 | } 68 | 69 | stringBuilder.AppendLine( string.Empty ); 70 | } 71 | 72 | public static bool IsOutputMemberType( MemberType memberType ) => memberType != MemberType.WallBeamElement 73 | && memberType != MemberType.WallColumnElement 74 | && memberType != MemberType.WallMeshBeamElement 75 | && memberType != MemberType.BearingWallBeam 76 | && memberType != MemberType.BearingWallColumn; 77 | 78 | #endregion 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /ExtractingModelData/OutputSlabData.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using System.Threading.Tasks; 3 | using TSD.API.Remoting.Structure; 4 | 5 | namespace ExtractingModelData 6 | { 7 | internal class OutputSlabData 8 | { 9 | #region Methods 10 | 11 | public static async Task CreateSlabDataOutputAsync( IModel model, StringBuilder stringBuilder ) 12 | { 13 | var slabs = await model.GetSlabsAsync(); 14 | var slabItems = await model.GetSlabItemsAsync(); 15 | 16 | stringBuilder.AppendLine( 17 | "Slab name," + 18 | "Slab type," + 19 | "Material," ); 20 | 21 | foreach( var slab in slabs ) 22 | { 23 | stringBuilder.AppendLine( 24 | $"{slab.Name}," + 25 | $"{slab.SlabData.Value.SlabType.Value}," + 26 | $"{slab.SlabData.Value.Material.Value.Name}," ); 27 | } 28 | 29 | stringBuilder.AppendLine(); 30 | 31 | stringBuilder.AppendLine( 32 | "Slab item name," + 33 | "Slab depth (mm)," ); 34 | 35 | foreach( var slabItem in slabItems ) 36 | { 37 | stringBuilder.AppendLine( 38 | $"{slabItem.Name}," + 39 | $"{slabItem.SlabItemData.Value.Depth.Value}," ); 40 | } 41 | 42 | stringBuilder.AppendLine(); 43 | } 44 | 45 | #endregion 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ExtractingModelData/OutputWallData.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using System.Threading.Tasks; 3 | using TSD.API.Remoting.Common; 4 | using TSD.API.Remoting.Structure; 5 | 6 | namespace ExtractingModelData 7 | { 8 | internal static class OutputWallData 9 | { 10 | #region Methods 11 | 12 | public static async Task CreateWallDataOutputAsync( IModel model, StringBuilder stringBuilder ) 13 | { 14 | var walls = await model.GetStructuralWallsAsync(); 15 | 16 | foreach( var wall in walls ) 17 | { 18 | stringBuilder.AppendLine( $"Wall name:, {wall.Name}," ); 19 | 20 | stringBuilder.AppendLine( 21 | "Panel number," + 22 | "Thickness (mm)," + 23 | "Material," + 24 | "Ratio (Static)," + 25 | "Status (Static)," ); 26 | 27 | var panels = await wall.GetSpanAsync(); 28 | 29 | foreach( var panel in panels ) 30 | { 31 | stringBuilder.AppendLine( 32 | $"{panel.Index + 1}," + 33 | $"{panel.WallPanelData.Value.Thickness.Value}," + 34 | $"{panel.WallPanelData.Value.Material.Value.Name}," + 35 | $"{panel.CheckResults[CheckResultType.Static].Value.UtilizationRatio.Value}," + 36 | $"{panel.CheckResults[CheckResultType.Static].Value.CheckStatus.Value}," ); 37 | } 38 | 39 | stringBuilder.AppendLine(); 40 | } 41 | } 42 | 43 | #endregion 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ExtractingModelData/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Threading.Tasks; 4 | using TSD.API.Remoting; 5 | 6 | namespace ExtractingModelData 7 | { 8 | internal static class Program 9 | { 10 | public static async Task Main() 11 | { 12 | using( var tsdInstance = await ApplicationFactory.GetFirstRunningApplicationAsync() ) 13 | { 14 | if( tsdInstance == null ) 15 | { 16 | Console.WriteLine( "No running instances of TSD found!" ); 17 | 18 | return; 19 | } 20 | 21 | Console.WriteLine( await tsdInstance.GetVersionStringAsync() ); 22 | 23 | var document = await tsdInstance.GetDocumentAsync(); 24 | 25 | if( document == null ) 26 | { 27 | Console.WriteLine( "No document was found in the TSD instance!" ); 28 | 29 | return; 30 | } 31 | 32 | var model = await document.GetModelAsync(); 33 | 34 | var stringBuilder = new StringBuilder(); 35 | 36 | await OutputMemberData.CreateMemberDataOutputAsync( model, stringBuilder ); 37 | await OutputWallData.CreateWallDataOutputAsync( model, stringBuilder ); 38 | await OutputSlabData.CreateSlabDataOutputAsync( model, stringBuilder ); 39 | await OutputConnectionData.CreateConnectionDataOutputAsync( model, stringBuilder ); 40 | await DataOutputFileCreator.OutputDataAsync( stringBuilder ); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ExtractingResultsTableItem/ExtractingResultsTableItem.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 7.3 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ExtractingResultsTableItem/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using TSD.API.Remoting; 5 | using TSD.API.Remoting.Structure; 6 | 7 | namespace ExtractingResultsTableItem 8 | { 9 | static class Program 10 | { 11 | [STAThread] 12 | public static async Task Main() 13 | { 14 | // Get the first running TSD instance found 15 | using( var tsdInstance = await ApplicationFactory.GetFirstRunningApplicationAsync() ) 16 | { 17 | if( tsdInstance == null ) 18 | { 19 | Console.WriteLine( "No running instances of TSD found!" ); 20 | 21 | return; 22 | } 23 | 24 | // Output the version number of TSD 25 | Console.WriteLine( await tsdInstance.GetVersionStringAsync() ); 26 | 27 | // Get the active document from the running instance of TSD 28 | var document = await tsdInstance.GetDocumentAsync(); 29 | 30 | if( document == null ) 31 | { 32 | Console.WriteLine( "No document was found in the TSD instance!" ); 33 | 34 | return; 35 | } 36 | 37 | // Get the model from the document 38 | var model = await document.GetModelAsync(); 39 | 40 | if( model == null ) 41 | { 42 | Console.WriteLine( "No model was found in the document!" ); 43 | 44 | return; 45 | } 46 | 47 | var member = await GetMemberForOutput( model ); 48 | 49 | if( member == null ) 50 | { 51 | Console.WriteLine( "No member found." ); 52 | 53 | return; 54 | } 55 | 56 | var lineItemString = GetLineItemStringFromUserInput(); 57 | 58 | var resultValuesOutputter = new ResultsValuesOutputter( member, lineItemString, tsdInstance ); 59 | await resultValuesOutputter.Output(); 60 | 61 | Console.ReadLine(); 62 | } 63 | } 64 | 65 | private static async Task GetMemberForOutput( IModel model ) 66 | { 67 | var members = await model.GetMembersAsync(); 68 | 69 | IMember member = null; 70 | 71 | do 72 | { 73 | Console.WriteLine( "Enter member reference:" ); 74 | 75 | string memberName = Console.ReadLine(); 76 | 77 | member = members.FirstOrDefault( m => m.Name == memberName ); 78 | 79 | if( member == null ) 80 | { 81 | Console.WriteLine( "Member named " + memberName + " not found" ); 82 | } 83 | } while( member == null ); 84 | 85 | return member; 86 | } 87 | 88 | private static string GetLineItemStringFromUserInput() 89 | { 90 | string lineItemString; 91 | 92 | do 93 | { 94 | Console.WriteLine( "Enter string to use for results table search:" ); 95 | lineItemString = Console.ReadLine(); 96 | } while( lineItemString.Length == 0 ); 97 | 98 | return lineItemString; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /ExtractingResultsTableItem/ResultsValuesOutputter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using TSD.API.Remoting; 6 | using TSD.API.Remoting.Common; 7 | using TSD.API.Remoting.Report; 8 | using TSD.API.Remoting.Structure; 9 | using TSD.API.Remoting.Units; 10 | 11 | namespace ExtractingResultsTableItem 12 | { 13 | public class ResultsValuesOutputter 14 | { 15 | #region Constructors 16 | 17 | public ResultsValuesOutputter( IMember member, string lineItemString, IApplication tsdInstance ) 18 | { 19 | LineItemString = lineItemString; 20 | Member = member; 21 | UnitConverter = tsdInstance.UnitConverter; 22 | } 23 | 24 | #endregion 25 | 26 | #region Properties 27 | 28 | private string LineItemString { get; } 29 | 30 | private IMember Member { get; } 31 | 32 | private IUnitConverter UnitConverter { get; } 33 | 34 | #endregion 35 | 36 | #region Methods 37 | 38 | public async Task Output() 39 | { 40 | var results = await Member.GetCalculationsAsync( CheckResultType.Static ); 41 | 42 | await ProcessCalculationsNodeList( results.Nodes, "" ); 43 | await ProcessItems( results.Items, "" ); 44 | } 45 | 46 | private async Task ProcessCalculationsNodeList( IReadOnlyList nodes, string hierarchyString ) 47 | { 48 | if( !nodes.Any() ) 49 | { 50 | return; 51 | } 52 | 53 | foreach( var node in nodes ) 54 | { 55 | string hierarchyStringNode = hierarchyString + " > " + node.Name; 56 | 57 | await ProcessCalculationsNodeList( node.Nodes, hierarchyStringNode ); 58 | await ProcessItems( node.Items, hierarchyStringNode ); 59 | } 60 | } 61 | 62 | private async Task ProcessItems( IReadOnlyList items, string hierarchyString ) 63 | { 64 | if( !items.Any() ) 65 | return; 66 | 67 | foreach( var item in items ) 68 | { 69 | await ProcessItem( item, hierarchyString ); 70 | } 71 | } 72 | 73 | private async Task ProcessItem( IReportItem item, string hierarchyString ) 74 | { 75 | if( item is IReportTable table ) 76 | { 77 | await ProcessTable( table, hierarchyString ); 78 | } 79 | } 80 | 81 | private async Task ProcessTable( IReportTable table, string hierarchyString ) 82 | { 83 | foreach( var line in table.Lines ) 84 | { 85 | await ProcessLine( line, hierarchyString ); 86 | } 87 | } 88 | 89 | private async Task ProcessLine( IReportTableLine line, string hierarchyString ) 90 | { 91 | if( line.Table != null ) 92 | { 93 | await ProcessTable( line.Table, hierarchyString ); 94 | } 95 | 96 | var item = line.Items.FirstOrDefault( i => i is IReportTableLineItemText || i is IReportTableLineItemCombined ); 97 | 98 | if( item != null ) 99 | { 100 | string text = ""; 101 | 102 | if( item is IReportTableLineItemText textItem ) 103 | text = textItem.Text; 104 | else if( item is IReportTableLineItemCombined combinedItem ) 105 | text = combinedItem.Text; 106 | 107 | if( !text.Contains( LineItemString ) ) 108 | { 109 | return; 110 | } 111 | 112 | // Text matches that being searched for! Output the result value. 113 | await OutputResultValue( line, hierarchyString ); 114 | } 115 | } 116 | 117 | private async Task OutputResultValue( IReportTableLine line, string hierarchyString ) 118 | { 119 | // Assume we are looking for a line that contains just one value and one quantity 120 | double value = 0.0; 121 | Quantity quantity = Quantity.Unknown; 122 | string text = ""; 123 | bool textFound, valueFound, quantityFound; 124 | textFound = valueFound = quantityFound = false; 125 | foreach( var item in line.Items ) 126 | { 127 | if( !textFound ) 128 | { 129 | if( item is IReportTableLineItemCombined combinedItem ) 130 | { 131 | text = combinedItem.Text; 132 | textFound = true; 133 | } 134 | else if( item is IReportTableLineItemText textItem ) 135 | { 136 | text = textItem.Text; 137 | textFound = true; 138 | } 139 | } 140 | 141 | if( !valueFound ) 142 | { 143 | if( item is IReportTableLineItemCombined combinedItem ) 144 | { 145 | value = combinedItem.Value; 146 | valueFound = true; 147 | } 148 | else if( item is IReportTableLineItemDoubleValue doubleItem ) 149 | { 150 | value = doubleItem.Value; 151 | valueFound = true; 152 | } 153 | else if( item is IReportTableLineItemLongValue longItem ) 154 | { 155 | value = longItem.Value; 156 | valueFound = true; 157 | } 158 | } 159 | 160 | if( !quantityFound ) 161 | { 162 | if( item is IReportTableLineItemCombined combinedItem ) 163 | { 164 | quantity = combinedItem.Quantity; 165 | quantityFound = true; 166 | } 167 | else if( item is IReportTableLineItemQuantity quantityItem ) 168 | { 169 | quantity = quantityItem.Quantity; 170 | quantityFound = true; 171 | } 172 | } 173 | } 174 | 175 | if( !valueFound || !quantityFound ) 176 | { 177 | // Not a valid value to output 178 | return; 179 | } 180 | 181 | var units = await UnitConverter.GetUnitsAsync( quantity, SystemType.Metric ); 182 | var unit = units.First(); 183 | 184 | if( unit != null ) 185 | { 186 | Console.WriteLine( hierarchyString ); 187 | 188 | Console.WriteLine( $"\t{text} {(await UnitConverter.FromBaseAsync( new[] { value }, unit )).First()} [{unit.Name}]" ); 189 | } 190 | } 191 | 192 | #endregion 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /ExtractingSteelBeamData/ExtractingSteelBeamData.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | 7.3 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Trimble Solutions Corporation 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /PythonNetExperiment/Program.cs: -------------------------------------------------------------------------------- 1 | Console.WriteLine( "Hello, from donor C# executable project!" ); 2 | Console.WriteLine( "This is here to provide resolution of nuget dependencies and obtain assemblies for the Python project." ); 3 | -------------------------------------------------------------------------------- /PythonNetExperiment/PythonNetExperiment.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | PythonNugetFetcher 9 | latestmajor 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /PythonNetExperiment/PythonNetExperiment.py: -------------------------------------------------------------------------------- 1 | from pythonnet import load 2 | load("coreclr") 3 | 4 | import clr 5 | import sys 6 | import time 7 | 8 | # Add the directory where your DLLs are located 9 | project_dir = r'.\bin\Debug\net8.0' # Adjust as needed 10 | sys.path.append(project_dir) 11 | 12 | # Load the .NET assembly 13 | clr.AddReference("System") 14 | clr.AddReference("TSD.API.Remoting") 15 | 16 | # Import the .NET namespace and types 17 | import TSD.API.Remoting as TSD 18 | from System.Collections.Generic import List 19 | 20 | # Connect to TSD instance and start interacting with API to get the model 21 | instance = TSD.ApplicationFactory.GetFirstRunningApplicationAsync().Result 22 | isConnected = instance.Connected 23 | document = instance.GetDocumentAsync().Result 24 | model = document.GetModelAsync().Result 25 | 26 | # Get the name of the entity based on the entity type and index 27 | def get_entity_name(entity_type, index): 28 | index_dotnet_list = List[int]() 29 | index_dotnet_list.Add(index) 30 | 31 | switcher = { 32 | TSD.Common.EntityType.Connection: model.GetConnectionsAsync(index_dotnet_list).Result, 33 | TSD.Common.EntityType.Member: model.GetMembersAsync(index_dotnet_list).Result, 34 | } 35 | 36 | response = switcher.get(entity_type, None) 37 | 38 | if response is None: 39 | return f"Entity type {entity_type} is not supported" 40 | 41 | return list(response)[0].Name 42 | 43 | # Define event handler for selection change event in TSD 44 | def selection_event_handler(sender, event_args): 45 | selection = model.GetSelectedEntitiesAsync().Result 46 | 47 | filtered = [] 48 | filtered.extend(filter( (lambda item: hasattr(item, 'Entity') ), selection )) 49 | 50 | for item in filtered: 51 | itemName = get_entity_name(item.Entity.Type, item.Entity.Index) 52 | print(f'Selected item: {item.Entity.Type}, Index: {item.Entity.Index}, Name: {itemName}') 53 | 54 | instance.SelectionChanged += selection_event_handler 55 | 56 | # Print the TSD data 57 | print('Is Connected: ', isConnected) 58 | print('TSD version: ', instance.GetVersionStringAsync().Result) 59 | print('Model Id: ', document.ModelId) 60 | 61 | while True: 62 | time.sleep(1) 63 | # read terminal input if "exit" then close 64 | if input() == "exit": 65 | break 66 | -------------------------------------------------------------------------------- /PythonNetExperiment/PythonNetExperiment.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.002.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PythonNetExperiment", "PythonNetExperiment.csproj", "{D1851BA4-212D-4D32-BCAB-BC2F81BB5777}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D1851BA4-212D-4D32-BCAB-BC2F81BB5777}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {D1851BA4-212D-4D32-BCAB-BC2F81BB5777}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {D1851BA4-212D-4D32-BCAB-BC2F81BB5777}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {D1851BA4-212D-4D32-BCAB-BC2F81BB5777}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {43A602FA-083F-43F5-B1A0-E90D51E49CC8} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /PythonNetExperiment/TsdApiPythonGuide.md: -------------------------------------------------------------------------------- 1 | # Tekla Structural Designer API from Python 2 | 3 | This is a short guide for an experiment using TSD API from Python. 4 | The goal is to connect to running TSD Application and demonstrate we can retrieve some data from it. 5 | The focus here is on all the path finding and dependencies needed in order to get this working. 6 | The author of this guide has a very limited knowledge of Python. 7 | 8 | ## Introduction 9 | 10 | Tekla Structural Designer (TSD) provides a nuget package TeklaStructuralDesigner.RemotingAPI which is intended to be used from a .NET environment. 11 | In order to use this from Python, we need to use a .NET bridge. This means we will need .NET SDK to download the TeklaStructuralDesigner.RemotingAPI nuget package 12 | and its dependencies and then use the bridge to access the API from Python. To demonstrate this is possible I've prepared a simple example this mixed PythonNetExample project. 13 | 14 | ## Prerequisites 15 | - Tekla Structural Designer installed 16 | - Visual Studio Code 17 | - .NET SDK 8.0 or later 18 | - Python 3 19 | 20 | ## Steps 21 | 22 | 1. Install .NET SDK 23 | 2. Install PythonNet 24 | 3. Build the C# donor project 25 | 4. Run TSD open a model and run the Python script 26 | 27 | ### Install .NET SDK 28 | This can be done in Visual Studio Code via the **.NET Install Tool** extension. Just search for it in the extensions and install it. 29 | 30 | ### Install PythonNet 31 | This can be done via pip: 32 | ```bash 33 | pip install pythonnet 34 | ``` 35 | 36 | ### Build the C# donor project 37 | This can be done from command line just navigate to the directory where the PythonNetExperiment project is extracted and run: 38 | 39 | ```bash 40 | dotnet build 41 | ``` 42 | This will download the TeklaStructuralDesigner.RemotingAPI nuget package and its dependencies. You will be able to find all the dlls in the project target subfolder. 43 | This is from where pythonnet will load the .NET assemblies. You can see that when the script sets `project_dir` variable. 44 | 45 | ```bash 46 | \PythonNetExperiment\bin\Debug\net8.0 47 | ``` 48 | 49 | ### Run TSD open a model and run the Python script 50 | Open Tekla Structural Designer and open any model. Then run the Python script from the extracted location. This will connect to the running TSD application and retrieve some data from it. 51 | 52 | ```bash 53 | python PythonNetExperiment.py 54 | ``` 55 | The expected output looks similar to this one, given some selection in the TSD 3D view was made by the user: 56 | 57 | ```bash 58 | $ python PythonNetExperiment.py 59 | 60 | Event listening start! 61 | Is Connected: True 62 | TSD version: 24.2.0.29 63 | Model Id: 890404f0-3646-4ddc-b8b9-3712ebc99997 64 | Selected item: Member, Index: 94, Name: SB Level 2/10/19-Level 2/10/20 65 | Selected item: Connection, Index: 48, Name: SCC 10/19 66 | Selected item: Member, Index: 77, Name: SGP 10/19 67 | Selected item: ConstructionHelper, Index: 16, Name: Entity type ConstructionHelper is not supported 68 | 69 | exit 70 | ``` 71 | 72 | ## Conclusion 73 | This proves that it is possible to access the TSD API from Python using PythonNet. This is a simple example and there are many more possibilities to explore. 74 | The current example blocks and waits synchronously for TSD API to finish its work. This example also does not build any conversions between .NET and Python collections it copies the values explicitly. 75 | 76 | It is important to take away that a C# project referencing the TeklaStructuralDesigner.RemotingAPI nuget package is needed to act as a donor for the Python script. 77 | The C# project can otherwise be left empty. 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TSDRemotingAPIExamples 2 | Tekla Structural Designer Remoting API Examples 3 | 4 | ## Examples 5 | 6 | * **ExtractingSteelBeamData** 7 | This project shows how to use TSD Remoting API from a command line application to export steel beam data to a .csv file. 8 | * **Extracting1DElementData** 9 | This project shows how to use TSD Remoting API from a WinForms application to export 1D element data to an excel file. 10 | * **CreatingAndAnalyzingModel** 11 | This project shows how to use TSD Remoting API from a command line application to create a multi-material model, add loading, run analysis, and extract analysis results to a .csv file. 12 | The example is designed to work with an empty model set to an EC regional code, as it sets materials in entities to EC materials. 13 | * **ExtractingDesignResults** 14 | This project shows how to use TSD Remoting API from a command line application to find values from the results tables for a given member by inputting text that will be used to search for lines in the results tables where that text appears. 15 | * **ExtractingModelData** 16 | This project shows how to use TSD Remoting API from a command line application to export data for members, walls, slabs and connections to a .csv file. 17 | * **ReactingToSelection** 18 | This project shows how to use TSD Remoting API from a WPF application that reacts to seletion in TSD displaying details about selected connections. 19 | * **PythonNetExperiment** 20 | This experimental project shows how to use TSD Remoting API from a Python application. It uses PythonNet to access the API. 21 | * **ExportingFireCheckDataToUDA** 22 | This project shows how to use TSD Remoting API from a command line application to export fire check data and set them as User Defined Attributes (UDA) for steel beams and columns. 23 | 24 | ## Compatibility 25 | 26 | These examples use TeklaStructuralDesigner.RemotingAPI version 25.0.1 and are compatible with Tekla Structural Designer 2025 Service Pack 1. 27 | -------------------------------------------------------------------------------- /ReactingToSelection/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | -------------------------------------------------------------------------------- /ReactingToSelection/App.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection; 2 | 3 | /// 4 | /// Represents the entry point of the application 5 | /// 6 | public partial class App; 7 | -------------------------------------------------------------------------------- /ReactingToSelection/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /ReactingToSelection/Helpers/ListWithNotify.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | using System.Windows.Threading; 3 | 4 | namespace ReactingToSelection.Helpers; 5 | 6 | /// 7 | /// Represents collection based on with rudimentary implementation 8 | /// 9 | /// The type of collection item 10 | public class ListWithNotify : List 11 | , INotifyCollectionChanged 12 | { 13 | #region Nested Types 14 | 15 | public enum NotificationType 16 | { 17 | None, 18 | Asynchronous, 19 | Synchronous, 20 | } 21 | 22 | #endregion 23 | 24 | #region Fields 25 | 26 | /// 27 | /// The dispatcher to use 28 | /// 29 | private readonly Dispatcher? _dispatcher = Dispatcher.FromThread( Thread.CurrentThread ); 30 | 31 | #endregion 32 | 33 | #region Constructors 34 | 35 | /// 36 | /// Creates a new instance of class 37 | /// 38 | public ListWithNotify() 39 | { 40 | // Intentionally left blank 41 | } 42 | 43 | /// 44 | /// Creates a new instance of class 45 | /// 46 | /// The items to fill the list with 47 | public ListWithNotify( IEnumerable items ) 48 | : base( items ) 49 | { 50 | // Intentionally left blank 51 | } 52 | 53 | #endregion 54 | 55 | #region Methods 56 | 57 | /// 58 | /// Raises the event 59 | /// 60 | /// Value indicating how the notification should be raised 61 | private void RaiseCollectionChanged( NotificationType notificationType ) 62 | { 63 | switch( notificationType ) 64 | { 65 | case NotificationType.Asynchronous: 66 | (_dispatcher ?? System.Windows.Application.Current.Dispatcher).InvokeAsync( () => RaiseCollectionChanged( NotificationType.Synchronous ) ); 67 | 68 | break; 69 | 70 | case NotificationType.Synchronous: 71 | CollectionChanged?.Invoke( this, new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ) ); 72 | 73 | break; 74 | 75 | case NotificationType.None: 76 | break; 77 | 78 | default: 79 | throw new InvalidOperationException( "Unsupported notification type" ); 80 | } 81 | } 82 | 83 | /// 84 | /// Replaces all items in collection with the provided items and raises event 85 | /// 86 | /// Collection of items to replace the content of this collection 87 | /// Value indicating how the notification should be raised 88 | public void ReplaceContentAndNotify( IEnumerable newContent, NotificationType notificationType = NotificationType.Asynchronous ) 89 | { 90 | Clear(); 91 | AddRange( newContent ); 92 | 93 | RaiseCollectionChanged( notificationType ); 94 | } 95 | 96 | #endregion 97 | 98 | #region INotifyCollectionChanged 99 | 100 | public event NotifyCollectionChangedEventHandler? CollectionChanged; 101 | 102 | #endregion 103 | } 104 | -------------------------------------------------------------------------------- /ReactingToSelection/Helpers/ReadOnlyPropertyExtensions.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Common.Properties; 2 | 3 | namespace ReactingToSelection.Helpers; 4 | 5 | /// 6 | /// Contains extension methods for the interface 7 | /// 8 | public static class ReadOnlyPropertyExtensions 9 | { 10 | #region Methods 11 | 12 | /// 13 | /// Returns the value of this property or the given default value in case the property is not applicable 14 | /// 15 | /// The property to get value of 16 | /// The default value to use in case the property is not applicable 17 | /// The type of value stored in the property 18 | public static TValue? GetValueOrDefault( this IReadOnlyProperty? property, TValue? defaultValue = default ) 19 | => property is { IsApplicable: true } ? property.Value : defaultValue; 20 | 21 | #endregion 22 | } 23 | -------------------------------------------------------------------------------- /ReactingToSelection/Helpers/RelayCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | 3 | namespace ReactingToSelection.Helpers; 4 | 5 | /// 6 | /// Represents a command 7 | /// 8 | /// The action to invoke 9 | internal class RelayCommand( Action action ) : ICommand 10 | { 11 | #region ICommand 12 | 13 | public bool CanExecute( object? parameter ) => true; 14 | 15 | public void Execute( object? parameter ) 16 | { 17 | action(); 18 | } 19 | 20 | event EventHandler? ICommand.CanExecuteChanged 21 | { 22 | add 23 | { 24 | // Intentionally left blank 25 | } 26 | remove 27 | { 28 | // Intentionally left blank 29 | } 30 | } 31 | 32 | #endregion 33 | } 34 | -------------------------------------------------------------------------------- /ReactingToSelection/Helpers/TaskExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Helpers; 2 | 3 | /// 4 | /// Contains extension methods for the class 5 | /// 6 | public static class TaskExtensions 7 | { 8 | #region Methods 9 | 10 | /// 11 | /// Provides a safe way to call asynchronous method without waiting for it's result 12 | /// 13 | /// The task to be run 14 | public static async void FireAndForgetSafeAsync( this Task task ) 15 | { 16 | try 17 | { 18 | await task; 19 | } 20 | catch( Exception ) 21 | { 22 | // Intentionally ignored 23 | } 24 | } 25 | 26 | #endregion 27 | } 28 | -------------------------------------------------------------------------------- /ReactingToSelection/Helpers/UiHelpers.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Common; 2 | using TSD.API.Remoting.Common.Properties; 3 | 4 | namespace ReactingToSelection.Helpers; 5 | 6 | /// 7 | /// Contains helper methods for UI 8 | /// 9 | internal static class UiHelpers 10 | { 11 | #region Methods 12 | 13 | /// 14 | /// Returns the display string for the given property 15 | /// 16 | /// The property to get display string of. 17 | /// The type of the property value 18 | /// The display string for the given property 19 | internal static string GetDisplayString( this IReadOnlyProperty? property ) 20 | { 21 | if( property is not { IsApplicable: true } ) 22 | return "-"; 23 | 24 | return property.Value switch 25 | { 26 | int integer => integer.ToString(), 27 | double number => GetDisplayString( number ), 28 | string text => text, 29 | IHaveName namedObject => namedObject.Name, 30 | _ => property.Value?.ToString() ?? "null" 31 | }; 32 | } 33 | 34 | /// 35 | /// Returns the display string for the given double value 36 | /// 37 | /// The value to get display string of 38 | /// The display string for the given double value 39 | public static string GetDisplayString( double? value ) => value?.ToString( "F2" ) ?? string.Empty; 40 | 41 | #endregion 42 | } 43 | -------------------------------------------------------------------------------- /ReactingToSelection/Helpers/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace ReactingToSelection.Helpers; 4 | 5 | /// 6 | /// Contains the base implementation of the interface 7 | /// 8 | public abstract class ViewModelBase : INotifyPropertyChanged 9 | { 10 | #region Methods 11 | 12 | /// 13 | /// Sets the property value and raises event (if the new value differs from the old one) 14 | /// 15 | /// The type of the property 16 | /// The name of the property to raise the notification event for 17 | /// The backing field for the property 18 | /// The new value to set 19 | /// An optional action to perform after raising the notification event 20 | /// when was different from the 21 | protected void SetProperty( string name, ref T field, T newValue, Action? action = null ) 22 | => SetPropertyInternal( name, ref field, newValue, OnPropertyChanged, action ); 23 | 24 | /// 25 | /// Sets the property value and raises event (if the new value differs from the old one) 26 | /// 27 | /// The type of the property 28 | /// The name of the property to raise the notification event for 29 | /// The backing field for the property 30 | /// The new value to set 31 | /// The action to use for raising the event 32 | /// An optional action to perform after raising the notification event 33 | /// when was different from the 34 | private static void SetPropertyInternal( string name, ref T field, T newValue, Action propertyChangedNotifier, Action? action = null ) 35 | { 36 | if( Equals( field, newValue ) ) 37 | return; 38 | 39 | field = newValue; 40 | 41 | propertyChangedNotifier.Invoke( name ); 42 | 43 | action?.Invoke(); 44 | } 45 | 46 | /// 47 | /// Reacts to change of given property 48 | /// 49 | /// The name of the property that was changed 50 | protected void OnPropertyChanged( string name ) 51 | { 52 | PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( name ) ); 53 | } 54 | 55 | #endregion 56 | 57 | #region INotifyPropertyChanged 58 | 59 | public event PropertyChangedEventHandler? PropertyChanged; 60 | 61 | #endregion 62 | } 63 | -------------------------------------------------------------------------------- /ReactingToSelection/Models/ConnectionFetcher.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Common; 2 | using TSD.API.Remoting.Common.Interfaces; 3 | using TSD.API.Remoting.Connections; 4 | using TSD.API.Remoting.Loading; 5 | using TSD.API.Remoting.Solver; 6 | using TSD.API.Remoting.Structure; 7 | 8 | namespace ReactingToSelection.Models; 9 | 10 | /// 11 | /// Represents a class that fetches connection details 12 | /// 13 | public static class ConnectionFetcher 14 | { 15 | #region Methods 16 | 17 | /// 18 | /// Returns the selected connections 19 | /// 20 | public static async Task> GetSelectedConnectionsAsync() 21 | { 22 | var selection = await Model.Instance.GetSelectedEntitiesAsync(); 23 | 24 | var connectionIndices = selection 25 | .OfType() 26 | .Where( x => x.Entity.Type == EntityType.Connection ) 27 | .Select( e => e.Entity.Index ) 28 | .ToList(); 29 | 30 | if( connectionIndices.Count == 0 ) 31 | return Enumerable.Empty(); 32 | 33 | return await Model.Instance.GetConnectionsAsync( connectionIndices ); 34 | } 35 | 36 | /// 37 | /// Returns the connected members of the connection 38 | /// 39 | /// The connection to fetch connected members of 40 | public static Task> GetConnectedMembersAsync( IConnection connection ) => connection.GetConnectedMembersAsync(); 41 | 42 | /// 43 | /// Returns the support reaction of the connection 44 | /// 45 | /// The connection to fetch support reaction of 46 | public static async Task GetSupportReactionAsync( IConnection connection ) 47 | { 48 | var combination = (await Model.Instance.GetCombinationsAsync()).First(); 49 | var constructionPoint = (await Model.Instance.GetConstructionPointsAsync( [connection.ConstructionPointIndex.Value] )).First(); 50 | int solverNodeIndex = (await Model.Instance.GetConstructionPointGroupsAsync( [constructionPoint.GroupIndex.Value] )).First().SolverNodeIndex.Value; 51 | var solverNode = (await (await Model.Instance.GetSolverModelsAsync( [AnalysisType.FirstOrderLinear] )).First().GetNodesAsync( [solverNodeIndex] )).First(); 52 | 53 | return await solverNode.GetSupportReactionAsync( combination.Id, reduceAxialLoad: false ); 54 | } 55 | 56 | #endregion 57 | } 58 | -------------------------------------------------------------------------------- /ReactingToSelection/Models/MemberSpanFetcher.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Connections; 2 | using TSD.API.Remoting.Loading; 3 | using TSD.API.Remoting.Solver; 4 | using TSD.API.Remoting.Structure; 5 | 6 | namespace ReactingToSelection.Models; 7 | 8 | /// 9 | /// Represents a class that fetches member span details 10 | /// 11 | public static class MemberSpanFetcher 12 | { 13 | #region Methods 14 | 15 | /// 16 | /// Returns the connected member details 17 | /// 18 | /// The connection to fetch connected member details of 19 | /// The member to fetch connected member details of 20 | /// The loading case to fetch connected member details of 21 | /// The analysis type to fetch connected member details of 22 | public static async Task<(ISpanReleases Releases, IForce3DLocal? EndForce)?> GetConnectedMemberDetailsAsync( IConnection connection, IMember member, 23 | ILoadingCase loadingCase, AnalysisType analysisType ) 24 | { 25 | int connectionConstructionPointIndex = connection.ConstructionPointIndex.Value; 26 | var spans = await member.GetSpanAsync(); 27 | 28 | foreach( var span in spans ) 29 | { 30 | int startConstructionPointIndex = span.StartMemberNode.ConstructionPointIndex.Value; 31 | int endConstructionPointIndex = span.EndMemberNode.ConstructionPointIndex.Value; 32 | 33 | if( connectionConstructionPointIndex == startConstructionPointIndex ) 34 | return (span.StartReleases.Value, await span.GetEndForceAsync( 0, analysisType, loadingCase.Id, LoadingResultType.Base )); 35 | 36 | if( connectionConstructionPointIndex == endConstructionPointIndex ) 37 | return (span.EndReleases.Value, await span.GetEndForceAsync( 1, analysisType, loadingCase.Id, LoadingResultType.Base )); 38 | 39 | var constructionPoints = await Model.Instance.GetConstructionPointsAsync( [connectionConstructionPointIndex, startConstructionPointIndex, endConstructionPointIndex] ); 40 | var groupIndices = constructionPoints.Select( cp => cp.GroupIndex ).ToList(); 41 | 42 | if( groupIndices[0].Value == groupIndices[1].Value ) 43 | return (span.StartReleases.Value, await span.GetEndForceAsync( 0, analysisType, loadingCase.Id, LoadingResultType.Base )); 44 | 45 | if( groupIndices[0].Value == groupIndices[2].Value ) 46 | return (span.EndReleases.Value, await span.GetEndForceAsync( 1, analysisType, loadingCase.Id, LoadingResultType.Base )); 47 | } 48 | 49 | return null; 50 | } 51 | 52 | #endregion 53 | } 54 | -------------------------------------------------------------------------------- /ReactingToSelection/Models/Model.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Structure; 2 | 3 | namespace ReactingToSelection.Models; 4 | 5 | /// 6 | /// Represents a class that holds reference to the currently active model 7 | /// 8 | public static class Model 9 | { 10 | #region Fields 11 | 12 | /// 13 | /// The currently active model 14 | /// 15 | private static IModel? _instance; 16 | 17 | #endregion 18 | 19 | #region Properties 20 | 21 | /// 22 | /// Gets the currently active model 23 | /// 24 | /// Throws in case the model is not fetched 25 | public static IModel Instance => _instance ?? throw new InvalidOperationException( "There is no active model!" ); 26 | 27 | #endregion 28 | 29 | #region Methods 30 | 31 | /// 32 | /// Fetches the currently opened model of given document 33 | /// 34 | /// The document to fetch currently opened model of 35 | public static async Task FetchModelAsync( TSD.API.Remoting.Document.IDocument document ) 36 | { 37 | var model = await document.GetModelAsync(); 38 | 39 | _instance = model; 40 | } 41 | 42 | #endregion 43 | } 44 | -------------------------------------------------------------------------------- /ReactingToSelection/ReactingToSelection.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net7.0-windows 6 | latest 7 | enable 8 | enable 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/AnchorPlate.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class AnchorPlate( IAnchorPlate? anchorPlate ) : ViewModelBase 7 | { 8 | #region Properties 9 | 10 | public string PlateType { get; } = (anchorPlate?.Type).GetDisplayString(); 11 | 12 | public string Width { get; } = (anchorPlate?.Width).GetDisplayString(); 13 | 14 | public string Thickness { get; } = (anchorPlate?.Thickness).GetDisplayString(); 15 | 16 | public string Length { get; } = (anchorPlate?.Length).GetDisplayString(); 17 | 18 | public string EdgeDistance { get; } = (anchorPlate?.EdgeDistance).GetDisplayString(); 19 | 20 | #endregion 21 | } 22 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BasePlate.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | using TSD.API.Remoting.Loading; 4 | 5 | namespace ReactingToSelection.ViewModels; 6 | 7 | public class BasePlate( IBasePlate basePlate, IForce3DGlobal supportReaction ) : ConnectionDetails 8 | { 9 | #region Properties 10 | 11 | public BasePlateProperties Properties { get; } = new( basePlate ); 12 | 13 | public BasePlateConcreteData ConcreteData { get; } = new( basePlate.ConcreteData.GetValueOrDefault() ); 14 | 15 | public BasePlateBoltData BoltData { get; } = new( basePlate.BoltData.GetValueOrDefault() ); 16 | 17 | public BasePlateBoltLayout? BoltLayout { get; } = BasePlateBoltLayout.Create( basePlate.BoltLayout.GetValueOrDefault() ); 18 | 19 | public BasePlateWelds Welds { get; } = new( basePlate.Welds.GetValueOrDefault() ); 20 | 21 | public WeldedWasher WeldedWasher { get; } = new( basePlate.WeldedWasher.GetValueOrDefault() ); 22 | 23 | public SupportReaction SupportReaction { get; } = new( supportReaction ); 24 | 25 | #endregion 26 | } 27 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BasePlateAsymmetricBoltLayout.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class BasePlateAsymmetricBoltLayout( IBasePlateAsymmetricBoltLayout layout ) : BasePlateBoltLayout 7 | { 8 | #region Properties 9 | 10 | public BasePlateBoltLayout? FlangeA { get; } = Create( layout.FlangeA.GetValueOrDefault() ); 11 | 12 | public BasePlateBoltLayout? FlangeC { get; } = Create( layout.FlangeC.GetValueOrDefault() ); 13 | 14 | #endregion 15 | } 16 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BasePlateBoltData.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class BasePlateBoltData( IBasePlateBoltData? data ) : ViewModelBase 7 | { 8 | #region Properties 9 | 10 | public Bolt? Bolt { get; } = Bolt.Create( data?.Bolt.GetValueOrDefault() ); 11 | 12 | public string BoltGrade { get; } = (data?.Grade).GetDisplayString(); 13 | 14 | public string Length { get; } = (data?.Length).GetDisplayString(); 15 | 16 | public string ProjectionAbovePlate { get; } = (data?.ProjectionAbovePlate).GetDisplayString(); 17 | 18 | public string EmbeddedDepth { get; } = (data?.EmbeddedDepth).GetDisplayString(); 19 | 20 | public AnchorPlate AnchorPlate { get; } = new( data?.AnchorPlate.GetValueOrDefault() ); 21 | 22 | #endregion 23 | } 24 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BasePlateBoltLayout.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public abstract class BasePlateBoltLayout : ViewModelBase 7 | { 8 | #region Methods 9 | 10 | public static BasePlateBoltLayout? Create( IBasePlateBoltLayout? layout ) => layout switch 11 | { 12 | IBasePlateFourBoltLayout fourBoltLayout => new BasePlateFourBoltLayout( fourBoltLayout ), 13 | IBasePlateSymmetricBoltLayout symmetricBoltLayout => new BasePlateSymmetricBoltLayout( symmetricBoltLayout ), 14 | IBasePlateAsymmetricBoltLayout asymmetricBoltLayout => new BasePlateAsymmetricBoltLayout( asymmetricBoltLayout ), 15 | null => null, 16 | _ => throw new InvalidOperationException( $"Unexpected type of base plate bolt layout {layout.GetType().Name} encountered!" ) 17 | }; 18 | 19 | #endregion 20 | } 21 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BasePlateConcreteData.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class BasePlateConcreteData( IBasePlateConcreteData? data ) : ViewModelBase 7 | { 8 | #region Properties 9 | 10 | public string Width { get; } = (data?.Width).GetDisplayString(); 11 | 12 | public string Length { get; } = (data?.Length).GetDisplayString(); 13 | 14 | public string Depth { get; } = (data?.Depth).GetDisplayString(); 15 | 16 | public string Material { get; } = (data?.Material).GetDisplayString(); 17 | 18 | public string GroutSpace { get; } = (data?.GroutSpace).GetDisplayString(); 19 | 20 | #endregion 21 | } 22 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BasePlateFourBoltLayout.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class BasePlateFourBoltLayout( IBasePlateFourBoltLayout layout ) : BasePlateBoltLayout 7 | { 8 | #region Properties 9 | 10 | public string EdgeDistance { get; } = layout.EdgeDistance.GetDisplayString(); 11 | 12 | public string EndDistance { get; } = layout.EndDistance.GetDisplayString(); 13 | 14 | #endregion 15 | } 16 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BasePlateProperties.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class BasePlateProperties( IBasePlate basePlate ) : ViewModelBase 7 | { 8 | #region Properties 9 | 10 | public string Length { get; } = basePlate.Length.GetDisplayString(); 11 | 12 | public string Width { get; } = basePlate.Width.GetDisplayString(); 13 | 14 | public string Thickness { get; } = basePlate.Thickness.GetDisplayString(); 15 | 16 | public string Steel { get; } = basePlate.Steel.GetDisplayString(); 17 | 18 | #endregion 19 | } 20 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BasePlateSymmetricBoltLayout.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class BasePlateSymmetricBoltLayout( IBasePlateSymmetricBoltLayout layout ) : BasePlateBoltLayout 7 | { 8 | #region Properties 9 | 10 | public bool Row2Enabled { get; } = layout.Row2Enabled.GetValueOrDefault(); 11 | 12 | public string BoltCountRow1 { get; } = layout.BoltCountRow1.GetDisplayString(); 13 | 14 | public string BoltCountRow2 { get; } = layout.BoltCountRow2.GetDisplayString(); 15 | 16 | public string EndDistance { get; } = layout.EndDistance.GetDisplayString(); 17 | 18 | public string FixedDistance { get; } = layout.FixedDistance.GetDisplayString(); 19 | 20 | public string EdgeDistance { get; } = layout.EdgeDistance.GetDisplayString(); 21 | 22 | public string EdgeDistanceRow1 { get; } = layout.EdgeDistanceRow1.GetDisplayString(); 23 | 24 | public string EdgeDistanceRow2 { get; } = layout.EdgeDistanceRow2.GetDisplayString(); 25 | 26 | public string Pitch { get; } = layout.Pitch.GetDisplayString(); 27 | 28 | public string PitchRow1 { get; } = layout.PitchRow1.GetDisplayString(); 29 | 30 | public string PitchRow2 { get; } = layout.PitchRow2.GetDisplayString(); 31 | 32 | public string Gauge { get; } = layout.Gauge.GetDisplayString(); 33 | 34 | #endregion 35 | } 36 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BasePlateWelds.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Common.Properties; 3 | using TSD.API.Remoting.Connections; 4 | 5 | namespace ReactingToSelection.ViewModels; 6 | 7 | public class BasePlateWelds : ViewModelBase 8 | { 9 | #region Nested Types 10 | 11 | public class WeldData( BasePlateWeldLocation location, IBasePlateWeldData? data ) : ViewModelBase 12 | { 13 | #region Properties 14 | 15 | public string Location { get; } = location.ToString(); 16 | 17 | public string WeldType { get; } = (data?.Type).GetDisplayString(); 18 | 19 | public string LegLength { get; } = (data?.LegLength).GetDisplayString(); 20 | 21 | public bool IsFullLength { get; } = (data?.IsFullLength).GetValueOrDefault(); 22 | 23 | public string PartialLength { get; } = (data?.PartialLength).GetDisplayString(); 24 | 25 | #endregion 26 | } 27 | 28 | #endregion 29 | 30 | #region Constructors 31 | 32 | public BasePlateWelds( IEnumerable>>? weldData ) 33 | { 34 | Data = new ListWithNotify( weldData?.Select( kvp => new WeldData( kvp.Key, kvp.Value.GetValueOrDefault() ) ) ?? [] ); 35 | } 36 | 37 | #endregion 38 | 39 | #region Properties 40 | 41 | public ListWithNotify Data { get; } 42 | 43 | #endregion 44 | } 45 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/Bolt.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | using static ReactingToSelection.Helpers.UiHelpers; 4 | 5 | namespace ReactingToSelection.ViewModels; 6 | 7 | public abstract class Bolt( IBolt bolt ) : ViewModelBase 8 | { 9 | #region Properties 10 | 11 | public string HeadCode { get; } = bolt.HeadCode.ToString(); 12 | 13 | public string SystemType { get; } = bolt.SystemType.ToString(); 14 | 15 | public string Grade { get; } = bolt.Grade; 16 | 17 | public string Diameter { get; } = GetDisplayString( bolt.Diameter ); 18 | 19 | public string TensileStrength { get; } = GetDisplayString( bolt.TensileStrength ); 20 | 21 | public string WidthAcrossNutFlats { get; } = GetDisplayString( bolt.WidthAcrossNutFlats ); 22 | 23 | public string WidthAcrossNutPoints { get; } = GetDisplayString( bolt.WidthAcrossNutPoints ); 24 | 25 | public string NutThickness { get; } = GetDisplayString( bolt.NutThickness ); 26 | 27 | public string WasherOutsideDiameter { get; } = GetDisplayString( bolt.WasherOutsideDiameter ); 28 | 29 | public string WasherThickness { get; } = GetDisplayString( bolt.WasherThickness ); 30 | 31 | #endregion 32 | 33 | #region Methods 34 | 35 | public static Bolt? Create( IBolt? bolt ) => bolt switch 36 | { 37 | IBoltEc ecBolt => new BoltEc( ecBolt ), 38 | IBoltUs usBolt => new BoltUs( usBolt ), 39 | null => null, 40 | _ => throw new InvalidOperationException( $"Unexpected type of bolt {bolt.GetType().Name} encountered!" ) 41 | }; 42 | 43 | #endregion 44 | } 45 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BoltEc.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Connections; 2 | using static ReactingToSelection.Helpers.UiHelpers; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class BoltEc( IBoltEc bolt ) : Bolt( bolt ) 7 | { 8 | #region Properties 9 | 10 | public string TensileStressArea { get; } = GetDisplayString( bolt.TensileStressArea ); 11 | 12 | public string YieldStrength { get; } = GetDisplayString( bolt.YieldStrength ); 13 | 14 | public string HeadThickness { get; } = GetDisplayString( bolt.HeadThickness ); 15 | 16 | #endregion 17 | } 18 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/BoltUs.cs: -------------------------------------------------------------------------------- 1 | using TSD.API.Remoting.Connections; 2 | using static ReactingToSelection.Helpers.UiHelpers; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class BoltUs( IBoltUs bolt ) : Bolt( bolt ) 7 | { 8 | #region Properties 9 | 10 | public string Area { get; } = GetDisplayString( bolt.Area ); 11 | 12 | public string BearingArea { get; } = GetDisplayString( bolt.BearingArea ); 13 | 14 | #endregion 15 | } 16 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/ConnectedMember.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using ReactingToSelection.Helpers; 3 | using ReactingToSelection.Models; 4 | using TSD.API.Remoting.Connections; 5 | using TSD.API.Remoting.Loading; 6 | using TSD.API.Remoting.Solver; 7 | using TSD.API.Remoting.Structure; 8 | 9 | namespace ReactingToSelection.ViewModels; 10 | 11 | public class ConnectedMember : ViewModelBase 12 | { 13 | #region Fields 14 | 15 | private IMember _member; 16 | private IConnection _connection; 17 | private SpanReleases? _spanReleases; 18 | private IForce3DLocal? _endForce; 19 | private AnalysisType _analysisType; 20 | private ICombination? _selectedCombination; 21 | 22 | #endregion 23 | 24 | #region Constructors 25 | 26 | public ConnectedMember( IMember member, IConnection connection ) 27 | { 28 | SetSelectedMember( member, connection ); 29 | 30 | AnalysisType = AnalysisTypes.First(); 31 | 32 | GetCombinationsAsync().FireAndForgetSafeAsync(); 33 | } 34 | 35 | #endregion 36 | 37 | #region Properties 38 | 39 | public string Name => _member.Name; 40 | 41 | public SpanReleases? SpanReleases 42 | { 43 | get => _spanReleases; 44 | set => SetProperty( nameof( SpanReleases ), ref _spanReleases, value ); 45 | } 46 | 47 | public IForce3DLocal? EndForce 48 | { 49 | get => _endForce; 50 | set => SetProperty( nameof( EndForce ), ref _endForce, value ); 51 | } 52 | 53 | public ICombination? SelectedCombination 54 | { 55 | get => _selectedCombination; 56 | set => SetProperty( nameof( SelectedCombination ), ref _selectedCombination, value, () => GetForceAndReleasesAsync().FireAndForgetSafeAsync() ); 57 | } 58 | 59 | public ListWithNotify Combinations { get; } = []; 60 | 61 | public AnalysisType AnalysisType 62 | { 63 | get => _analysisType; 64 | set => SetProperty( nameof( AnalysisType ), ref _analysisType, value, () => GetForceAndReleasesAsync().FireAndForgetSafeAsync() ); 65 | } 66 | 67 | public static AnalysisType[] AnalysisTypes => Enum.GetValues().Skip( 1 ).ToArray(); 68 | 69 | #endregion 70 | 71 | #region Methods 72 | 73 | [MemberNotNull( nameof( _member ))] 74 | [MemberNotNull( nameof( _connection ) )] 75 | public void SetSelectedMember( IMember member, IConnection connection ) 76 | { 77 | _member = member; 78 | _connection = connection; 79 | 80 | OnPropertyChanged( nameof( Name ) ); 81 | GetForceAndReleasesAsync().FireAndForgetSafeAsync(); 82 | } 83 | 84 | private async Task GetForceAndReleasesAsync() 85 | { 86 | if( SelectedCombination is null ) 87 | { 88 | EndForce = null; 89 | SpanReleases = null; 90 | 91 | return; 92 | } 93 | 94 | var details = await MemberSpanFetcher.GetConnectedMemberDetailsAsync( _connection, _member, SelectedCombination, AnalysisType ); 95 | 96 | if( details is null ) 97 | { 98 | EndForce = null; 99 | SpanReleases = null; 100 | 101 | return; 102 | } 103 | 104 | EndForce = details.Value.EndForce; 105 | SpanReleases = new SpanReleases( details.Value.Releases ); 106 | } 107 | 108 | private async Task GetCombinationsAsync() 109 | { 110 | var combinations = (await Model.Instance.GetCombinationsAsync()).ToList(); 111 | 112 | Combinations.ReplaceContentAndNotify( combinations ); 113 | 114 | SelectedCombination = combinations.FirstOrDefault(); 115 | } 116 | 117 | #endregion 118 | } 119 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/Connection.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using ReactingToSelection.Models; 3 | using TSD.API.Remoting.Common; 4 | using TSD.API.Remoting.Common.Properties; 5 | using TSD.API.Remoting.Connections; 6 | using TSD.API.Remoting.Structure; 7 | 8 | namespace ReactingToSelection.ViewModels; 9 | 10 | public class Connection : ViewModelBase 11 | { 12 | #region Fields 13 | 14 | private IConnection? _connection; 15 | private ConnectionDetails? _connectionDetails; 16 | private IMember? _selectedConnectedMember; 17 | private ConnectedMember? _connectedMember; 18 | 19 | #endregion 20 | 21 | #region Constructors 22 | 23 | public Connection( IConnection? connection ) 24 | { 25 | SetSelectedConnection( connection ); 26 | 27 | FetchConnectedMembersAsync().FireAndForgetSafeAsync(); 28 | FetchConnectionDetailsAsync().FireAndForgetSafeAsync(); 29 | } 30 | 31 | #endregion 32 | 33 | #region Properties 34 | 35 | public string Name => _connection?.Name ?? string.Empty; 36 | 37 | public string ConnectionType => _connection?.ConnectionType.Value.ToString() ?? string.Empty; 38 | 39 | public string ConstructionPointIndex => _connection?.ConstructionPointIndex.Value.ToString() ?? string.Empty; 40 | 41 | public IProperty? UtilizationRatio => _connection?.UtilizationRatio; 42 | 43 | public IPropertyWithValidValues? CheckStatus => _connection?.CheckStatus; 44 | 45 | public ListWithNotify ConnectedMembers { get; } = []; 46 | 47 | public ConnectionDetails? ConnectionDetails 48 | { 49 | get => _connectionDetails; 50 | private set => SetProperty( nameof( ConnectionDetails ), ref _connectionDetails, value ); 51 | } 52 | 53 | public IMember? SelectedConnectedMember 54 | { 55 | get => _selectedConnectedMember; 56 | set 57 | { 58 | if( _selectedConnectedMember?.Name == value?.Name ) 59 | return; 60 | 61 | SetProperty( nameof( SelectedConnectedMember ), ref _selectedConnectedMember, value ); 62 | 63 | if( _selectedConnectedMember is not { } selectedConnectedMember ) 64 | return; 65 | 66 | if( _connection is not { } connection ) 67 | return; 68 | 69 | ConnectedMember ??= new ConnectedMember( selectedConnectedMember, connection ); 70 | ConnectedMember.SetSelectedMember( selectedConnectedMember, connection ); 71 | } 72 | } 73 | 74 | public ConnectedMember? ConnectedMember 75 | { 76 | get => _connectedMember; 77 | private set => SetProperty( nameof( ConnectedMember ), ref _connectedMember, value ); 78 | } 79 | 80 | #endregion 81 | 82 | #region Methods 83 | 84 | private void SetSelectedConnection( IConnection? connection ) 85 | { 86 | if( connection == _connection ) 87 | return; 88 | 89 | _connection = connection; 90 | 91 | OnPropertyChanged( nameof( Name ) ); 92 | OnPropertyChanged( nameof( ConnectionType ) ); 93 | OnPropertyChanged( nameof( ConstructionPointIndex ) ); 94 | OnPropertyChanged( nameof( UtilizationRatio ) ); 95 | OnPropertyChanged( nameof( CheckStatus ) ); 96 | } 97 | 98 | private async Task FetchConnectedMembersAsync() 99 | { 100 | if( _connection is null ) 101 | return; 102 | 103 | var connectedMembers = (await ConnectionFetcher.GetConnectedMembersAsync( _connection )).ToList(); 104 | 105 | ConnectedMembers.ReplaceContentAndNotify( connectedMembers ); 106 | 107 | SelectedConnectedMember = connectedMembers.FirstOrDefault(); 108 | } 109 | 110 | private async Task FetchConnectionDetailsAsync() 111 | { 112 | if( _connection is null ) 113 | return; 114 | 115 | var supportReaction = await ConnectionFetcher.GetSupportReactionAsync( _connection ); 116 | 117 | ConnectionDetails = ConnectionDetails.Create( _connection, supportReaction ); 118 | } 119 | 120 | #endregion 121 | } 122 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/ConnectionDetails.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | using TSD.API.Remoting.Loading; 4 | 5 | namespace ReactingToSelection.ViewModels; 6 | 7 | public abstract class ConnectionDetails : ViewModelBase 8 | { 9 | #region Methods 10 | 11 | public static ConnectionDetails? Create( IConnection? connection, IForce3DGlobal supportReaction ) => connection switch 12 | { 13 | IBasePlate basePlate => new BasePlate( basePlate, supportReaction ), 14 | _ => null 15 | }; 16 | 17 | #endregion 18 | } 19 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/MainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | using ReactingToSelection.Helpers; 3 | using ReactingToSelection.Models; 4 | using TSD.API.Remoting; 5 | using TSD.API.Remoting.Connections; 6 | 7 | namespace ReactingToSelection.ViewModels; 8 | 9 | public class MainWindowViewModel : ViewModelBase 10 | { 11 | #region Fields 12 | 13 | private IApplication? _application; 14 | private Connection? _connection; 15 | private IConnection? _selectedConnection; 16 | 17 | #endregion 18 | 19 | #region Constructors 20 | 21 | public MainWindowViewModel() 22 | { 23 | RefreshCommand = new RelayCommand( RefreshAsync ); 24 | 25 | async void RefreshAsync() 26 | { 27 | if( _application is not null ) 28 | { 29 | _application.SelectionChanged -= OnSelectionChanged; 30 | } 31 | 32 | _application = (await ApplicationFactory.GetRunningApplicationsAsync()).FirstOrDefault(); 33 | 34 | if( _application is null ) 35 | return; 36 | 37 | _application.SelectionChanged += OnSelectionChanged; 38 | 39 | if( await _application.GetDocumentAsync() is not { } document ) 40 | return; 41 | 42 | await Model.FetchModelAsync( document ); 43 | 44 | OnSelectionChanged( null, EventArgs.Empty ); 45 | } 46 | } 47 | 48 | #endregion 49 | 50 | #region Properties 51 | 52 | public Connection? Connection 53 | { 54 | get => _connection; 55 | set => SetProperty( nameof( Connection ), ref _connection, value ); 56 | } 57 | 58 | public ListWithNotify Connections { get; } = []; 59 | 60 | public IConnection? SelectedConnection 61 | { 62 | get => _selectedConnection; 63 | set => SetProperty( nameof( SelectedConnection ), ref _selectedConnection, value, () => Connection = new Connection( value ?? Connections.FirstOrDefault() ) ); 64 | } 65 | 66 | public ICommand RefreshCommand { get; } 67 | 68 | #endregion 69 | 70 | #region Event Handlers 71 | 72 | private void OnSelectionChanged( object? sender, EventArgs e ) 73 | { 74 | GetConnectionDetailsForSelectionAsync().FireAndForgetSafeAsync(); 75 | 76 | async Task GetConnectionDetailsForSelectionAsync() 77 | { 78 | Connections.ReplaceContentAndNotify( await ConnectionFetcher.GetSelectedConnectionsAsync() ); 79 | 80 | SelectedConnection = Connections.FirstOrDefault(); 81 | } 82 | } 83 | 84 | #endregion 85 | } 86 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/SpanReleases.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Structure; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class SpanReleases( ISpanReleases? spanReleases ) : ViewModelBase 7 | { 8 | #region Properties 9 | 10 | public string DegreeOfFreedom => (spanReleases?.DegreeOfFreedom).GetDisplayString(); 11 | 12 | public string Cantilever => (spanReleases?.Cantilever).GetDisplayString(); 13 | 14 | public string AxialRelease => (spanReleases?.AxialRelease).GetDisplayString(); 15 | 16 | public string TorsionalRelease => (spanReleases?.TorsionalRelease).GetDisplayString(); 17 | 18 | #endregion 19 | } 20 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/SupportReaction.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Loading; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class SupportReaction( IForce3DGlobal? supportReaction ) : ViewModelBase 7 | { 8 | #region Properties 9 | 10 | public string Fx { get; } = UiHelpers.GetDisplayString( supportReaction?.Fx ); 11 | 12 | public string Fy { get; } = UiHelpers.GetDisplayString( supportReaction?.Fy ); 13 | 14 | public string Fz { get; } = UiHelpers.GetDisplayString( supportReaction?.Fz ); 15 | 16 | public string Mx { get; } = UiHelpers.GetDisplayString( supportReaction?.Mx ); 17 | 18 | public string My { get; } = UiHelpers.GetDisplayString( supportReaction?.My ); 19 | 20 | public string Mz { get; } = UiHelpers.GetDisplayString( supportReaction?.Mz ); 21 | 22 | #endregion 23 | } 24 | -------------------------------------------------------------------------------- /ReactingToSelection/ViewModels/WeldedWasher.cs: -------------------------------------------------------------------------------- 1 | using ReactingToSelection.Helpers; 2 | using TSD.API.Remoting.Connections; 3 | 4 | namespace ReactingToSelection.ViewModels; 5 | 6 | public class WeldedWasher( IWeldedWasher? weldedWasher ) : ViewModelBase 7 | { 8 | #region Properties 9 | 10 | public bool UseWeldedWashers { get; } = (weldedWasher?.UseWeldedWashers).GetValueOrDefault(); 11 | 12 | public string SideLength { get; } = (weldedWasher?.SideLength).GetDisplayString(); 13 | 14 | public string HoleDiameter { get; } = (weldedWasher?.HoleDiameter).GetDisplayString(); 15 | 16 | public string Thickness { get; } = (weldedWasher?.Thickness).GetDisplayString(); 17 | 18 | public string Steel { get; } = weldedWasher?.Steel.GetValueOrDefault()?.Name ?? string.Empty; 19 | 20 | #endregion 21 | } 22 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/AnchorPlate.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 63 | 64 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/AnchorPlate.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class AnchorPlate 4 | { 5 | #region Constructors 6 | 7 | public AnchorPlate() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlate.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlate.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BasePlate 4 | { 5 | #region Constructors 6 | 7 | public BasePlate() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateAsymmetricBoltLayout.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateAsymmetricBoltLayout.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BasePlateAsymmetricBoltLayout 4 | { 5 | #region Constructors 6 | 7 | public BasePlateAsymmetricBoltLayout() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateBoltData.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateBoltData.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BasePlateBoltData 4 | { 5 | #region Constructors 6 | 7 | public BasePlateBoltData() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateBoltLayout.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateBoltLayout.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BasePlateBoltLayout 4 | { 5 | #region Constructors 6 | 7 | public BasePlateBoltLayout() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateConcreteData.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateConcreteData.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BasePlateConcreteData 4 | { 5 | #region Constructors 6 | 7 | public BasePlateConcreteData() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateFourBoltLayout.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 36 | 37 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateFourBoltLayout.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BasePlateFourBoltLayout 4 | { 5 | #region Constructors 6 | 7 | public BasePlateFourBoltLayout() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateProperties.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateProperties.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BasePlateProperties 4 | { 5 | #region Constructors 6 | 7 | public BasePlateProperties() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateSymmetricBoltLayout.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 127 | 128 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateSymmetricBoltLayout.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BasePlateSymmetricBoltLayout 4 | { 5 | #region Constructors 6 | 7 | public BasePlateSymmetricBoltLayout() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateWelds.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BasePlateWelds.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BasePlateWelds 4 | { 5 | #region Constructors 6 | 7 | public BasePlateWelds() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/Bolt.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/Bolt.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class Bolt 4 | { 5 | #region Constructors 6 | 7 | public Bolt() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BoltEc.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 135 | 136 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BoltEc.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BoltEc 4 | { 5 | #region Constructors 6 | 7 | public BoltEc() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BoltUs.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 126 | 127 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/BoltUs.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class BoltUs 4 | { 5 | #region Constructors 6 | 7 | public BoltUs() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/ConnectedMember.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/ConnectedMember.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class ConnectedMember 4 | { 5 | #region Constructors 6 | 7 | public ConnectedMember() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/Connection.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 29 | 30 | 31 | 34 | 35 | 38 | 39 | 42 | 43 | 44 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 61 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/Connection.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class Connection 4 | { 5 | #region Constructors 6 | 7 | public Connection() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/ConnectionDetails.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/ConnectionDetails.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class ConnectionDetails 4 | { 5 | #region Constructors 6 | 7 | public ConnectionDetails() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 31 | 38 | 46 | 47 | 48 | 49 | 50 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using ReactingToSelection.ViewModels; 3 | 4 | namespace ReactingToSelection.Views; 5 | 6 | public partial class MainWindow 7 | { 8 | #region Constructors 9 | 10 | public MainWindow() 11 | { 12 | InitializeComponent(); 13 | 14 | DataContext = new MainWindowViewModel(); 15 | } 16 | 17 | #endregion 18 | 19 | #region Event Handlers 20 | 21 | private void OnDataGridAutoGeneratingColumn( object sender, DataGridAutoGeneratingColumnEventArgs e ) 22 | { 23 | e.Column = new DataGridTextColumn 24 | { 25 | Header = ConvertPropertyNameToHeader( e.PropertyName ), 26 | Binding = new System.Windows.Data.Binding( $"{e.PropertyName}.Value" ) 27 | }; 28 | 29 | static string ConvertPropertyNameToHeader( string propertyName ) => System.Text.RegularExpressions.Regex.Replace( propertyName, "([a-z])([A-Z])", "$1 $2" ); 30 | } 31 | 32 | #endregion 33 | } 34 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/SpanReleases.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 54 | 55 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/SpanReleases.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class SpanReleases 4 | { 5 | #region Constructors 6 | 7 | public SpanReleases() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/SupportReaction.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 71 | 72 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/SupportReaction.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class SupportReaction 4 | { 5 | #region Constructors 6 | 7 | public SupportReaction() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/WeldedWasher.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 64 | 65 | -------------------------------------------------------------------------------- /ReactingToSelection/Views/WeldedWasher.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ReactingToSelection.Views; 2 | 3 | public partial class WeldedWasher 4 | { 5 | #region Constructors 6 | 7 | public WeldedWasher() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | #endregion 13 | } 14 | -------------------------------------------------------------------------------- /ReleaseNotes/2023.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | This document contains the notes for individual releases of the _TeklaStructuralDesigner.RemotingAPI_ NuGet package for major version 23. 4 | 5 | ## Version 23.4.0 6 | 7 | * A bug preventing connection to the API when using trial version of TSD has been fixed. 8 | 9 | ## Version 23.3.0 10 | 11 | * The ability to access connections via `Structure.IModel` interface has been added. 12 | * The ability to access floor analysis models via `Structure.IModel` interface has been added. 13 | * The floor analysis results (vibration modes and mode shapes by node) can be now accessed via solver model of floor analysis model (`GetVibrationModesAsync` and `GetModeShapesByNodeAsync` respectively). 14 | * The ability to access base plate data via `IBasePlate` interface has been added. 15 | * The property `GlobalRotationAngle` has been added to `IMemberSpan`. 16 | * The property `CombinationSpeciality` has been added to `ICombination`. 17 | * There is now an option to close an instance of Tekla Structural Designer application by calling `IApplication.StopAsync()`. This is only allowed for instances that were started via the API and the stop action can only be done from the client that started the instance. 18 | * A bug preventing access to concrete sections with circular holes has been fixed. 19 | * A bug preventing access to user-defined attributes has been fixed. 20 | 21 | ## Version 23.2.0 22 | 23 | * There is now a new way to peek at running instances of Tekla Structural Designer at the local machine instead of having to connect to them right away (`ApplicationFactory.GetRunningApplicationInfosAsync`). The provided `IApplicationInfo` then can be used to connect to the associated instance of Tekla Structural Designer using a new overload of method (`ApplicationFactory.ConnectToRunningApplicationAsync`). 24 | * The ability to access calculations of an object has been added (see `IHaveCalculations`). 25 | * A bug causing crash when accessing `DepthToThicknessRatio`, `BucklingParameter` and/or `TorsionalIndex` properties of `IPlatedISection` has been fixed. The properties now return `double.NaN` instead and a new interface `IPlatedISectionV2` has been added that has these properties as nullable (with `null` value instead of `double.NaN`). The old interface (`IPlatedISection`) has been made obsolete. 26 | * The ability to query units and convert values has been added (`IUnitConverter` in `IApplication`). 27 | * The ability to access current selection has been added (see `ISelectionItem`). 28 | 29 | ## Version 23.1.0 30 | 31 | * The ability to run the _"Analyze All"_ and _"Design All"_ commands has been added. 32 | * Westok web openings have been exposed via API. 33 | * The following properties of `IWebOpening` interface can now be accessed via the `Stiffener` property and were therefore made obsolete: 34 | * `Stiffening` 35 | * `StiffenerDepth` 36 | * `StiffenerThickness` 37 | * `StiffenerLength` 38 | * `EdgeToStiffenerCenter` 39 | * All these obsolete properties will be removed in version 25.0.0. 40 | * The stiffeners of web openings can be now added (resp. removed) via dedicated `Add` and `Remove` methods. 41 | * Property `IsStiffened` can therefore no longer have its value set and will be changed to `IReadOnlyProperty` in version 25.0.0. 42 | * The property `FilletWeldLegLength` of simple web opening stiffener has been exposed. 43 | * The following properties related to splices have been added to `ISteelColumnStackData` 44 | * `HasSplice` 45 | * `SpliceOffset` 46 | * The settings related to export of continuous objects have been exposed via API (under `IModelSettings.BimSettings`). 47 | 48 | ## Version 23.0.0 49 | 50 | This is the first public version of the NuGet package. 51 | 52 | The aim of the API is to allow its users to interact with the Tekla Structural Designer from within code. The following functionality is provided by the API: 53 | * Control of Tekla Structural Designer instances 54 | * Start a new instance of Tekla Structural Designer 55 | * Get currently running instances of Tekla Structural Designer 56 | * Connect to/disconnect from an instance of Tekla Structural Designer 57 | * Control of document within Tekla Structural Designer 58 | * Create a new document 59 | * Open existing document (from file or stream) 60 | * Save current document 61 | * Close current document 62 | * Access to information about sessions 63 | * Access to project details 64 | * Access to the structure model 65 | * Access to model entities and the ability to create/modify them 66 | * Architectural grid 67 | * Architectural grid lines 68 | * Construction points 69 | * Construction point groups 70 | * Construction planes (horizontal, vertical, sloped) 71 | * Foundations 72 | * Pad bases 73 | * Pile caps 74 | * Piles 75 | * Members 76 | * Beams 77 | * Braces 78 | * Columns 79 | * Portal frames 80 | * Members 81 | * Member spans 82 | * Rafters 83 | * Supports 84 | * Valleys 85 | * Roofs 86 | * Slabs 87 | * Slab items 88 | * Slab openings 89 | * Slab patches 90 | * Strips 91 | * Structural walls 92 | * Structural wall openings 93 | * Supports 94 | * Web openings 95 | * Wind walls 96 | * Access to loading and the ability to create/modify it 97 | * Loads 98 | * Load cases 99 | * Combinations 100 | * Envelopes 101 | * Access to material properties of model entities 102 | * Sections 103 | * Materials 104 | * Reinforcement 105 | * Profiles 106 | * Gauges 107 | * Access to solver model 108 | * Analysis results 109 | * Displacements 110 | * Forces 111 | * Nodal forces 112 | * Nodal mesh forces 113 | * Element end forces 114 | * Mesh forces 115 | * Result line forces 116 | * Wall line forces 117 | * Wall line station forces 118 | * Objects 119 | * Nodes 120 | * Supports 121 | * 1D elements 122 | * 2D elements 123 | * Panels 124 | * Diaphragms 125 | * Result lines 126 | * Stations 127 | * Wall lines 128 | * Access to user-defined attributes 129 | * Simple attributes 130 | * Embedded files 131 | * Access to information about embodied carbon in model entities 132 | * Control of validation 133 | * Access to the latest validation status 134 | * Means to run validation 135 | * Control of design 136 | * Access to the latest design status 137 | * Means to run design 138 | -------------------------------------------------------------------------------- /ReleaseNotes/2024.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | This document contains the notes for individual releases of the _TeklaStructuralDesigner.RemotingAPI_ NuGet package for major version 24. 4 | 5 | ## Version 24.4.0 6 | * A new interface `IHaveUserName` has been added and implemented by most model entities 7 | * The property `Ec3FormulaType` has been added to `ICombination`. 8 | * The ability to access calculations of a structural wall (`IStructuralWall`) has been added (see `IHaveCalculations`). 9 | 10 | ## Version 24.3.0 11 | 12 | * A new value `SquareBar` has been added to the `SectionType` enumeration 13 | * A new interface `IBar` has been added which represents both square and flat bars 14 | * The interface `IFlatBar` has been made obsolete and will be removed in version 26.0.0 15 | * New `ColumnBrace`, `BeamBrace` and `XBrace` connection types have been added. 16 | * A new reinforcement geometry `Wire` and associated `IReinforcementWireSize` interface has been added. 17 | 18 | ## Version 24.2.0 19 | 20 | * The property `MinorAxisElasticSectionModulus` of `IColdRolledSectionBase` has been made optional. It will return `double.NaN` in case it is not available and its type will change to `double?` in version 26.0.0. 21 | * A new value `Mexico` has been added to the `Country` enumeration. 22 | 23 | ## Version 24.1.0 24 | 25 | * A new overload for `IModel.CreateMemberAttributeSetAsync` method has been added that allows users to specify the type of created member. 26 | * This change also allows users to set the section of created members. 27 | * The original overload is therefore redundant, has been marked obsolete and will be removed in version 26.0.0. 28 | * The property `IsWindward` has been added to `ISnowLoadDataDrift`. 29 | * The property `DistanceToRidge` has been added to `ISnowLoadDataRainOnSnow`. 30 | 31 | ## Version 24.0.0 32 | 33 | * A dedicated combination class for staged construction has been added. 34 | * A dedicated set of staged construction analysis types has been added. 35 | * The ability to access analysis types used in element design has been added (see `GetAnalysisTypesForElementDesignAsync` in `Structure.IModel`). 36 | * A new masonry material type has been added (see `IMasonry`). 37 | * Unfortunately, this _breaks the backwards compatibility_ so in order to work with TSD of version 24.0 and later, the API of at least version 24.0 needs to be used. 38 | -------------------------------------------------------------------------------- /ReleaseNotes/2025.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | This document contains the notes for individual releases of the _TeklaStructuralDesigner.RemotingAPI_ NuGet package for major version 25. 4 | 5 | ## Version 25.1.0 6 | 7 | * A new interface `IForce3d` has been extracted. The existing `IForce3DLocal` and `IForce3DGlobal` interfaces are now extending it. 8 | * A new interface `IErrorFamily` has been added. 9 | * A new method `Structure.IModel.GetSolverErrorsAsync` has been added that allows users to obtain solver errors for the given analysis types. 10 | * A new namespace `TSD.API.Remoting.Filtering` has been added that provides objects for filtering entities. 11 | * A new property `TabularResultsAccessor` has been added to the `Structure.IModel` interface. It allows the access to various tabular results. 12 | * A new property `BimSource` has been added to the `IBimData` interface. 13 | * A new method `Structure.IModel.GetSelectedAnalysisTypeAsync` has been added that allows users to obtain the currently selected analysis type. 14 | * A new method `GetResult` has been added to the `IDesignCondition` interface that allows users to obtain the overall design result. 15 | * A new property `MasonryReinforcement` has been added to the `IStructuralWallPanel` interface. 16 | * A new method `Structure.IModel.GetStructuralWallPatchesAsync` has been added that allows users to obtain the patches in structural walls. 17 | 18 | ## Version 25.0.1 19 | 20 | * The following obsolete properties of `IWebOpening` interface have been removed: 21 | * `Stiffening` 22 | * `StiffenerDepth` 23 | * `StiffenerThickness` 24 | * `StiffenerLength` 25 | * `EdgeToStiffenerCenter` 26 | * The type of the property `IWebOpening.IsStiffened` has been changed to `IReadOnlyProperty`. 27 | * The obsolete `IPlatedISection` interface has been removed. 28 | * A new set of properties related to floor vibration has been added to `ISteelBeamSpanData` interface. 29 | * A new method `ISectionFactory.GetSectionGroupsAsync` has been added that allows users to obtain section groups compatible with the given head code and geometry. 30 | * New properties `GaugeFactory`, `ProfileFactory` and `MaterialFactory` have been added to `IModel` interface. 31 | * A new property `UnitSettings` has been added to `IModelSettings` interface. 32 | -------------------------------------------------------------------------------- /RemotingAPIExamples.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32516.85 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExtractingSteelBeamData", "ExtractingSteelBeamData\ExtractingSteelBeamData.csproj", "{38984DD1-D052-4B17-B2E0-8C96E04EF353}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Extracting1DElementData", "Extracting1DElementData\Extracting1DElementData.csproj", "{642C6C7B-DBDF-4865-91FD-56609D661E71}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CreatingAndAnalyzingModel", "CreatingAndAnalyzingModel\CreatingAndAnalyzingModel.csproj", "{3EC3F9B8-94DF-4BD5-8074-7B39A6834DA4}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtractingResultsTableItem", "ExtractingResultsTableItem\ExtractingResultsTableItem.csproj", "{36DA71E5-9802-4A27-91C7-0B484DB33790}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtractingModelData", "ExtractingModelData\ExtractingModelData.csproj", "{372E7664-E1DE-4002-A9C5-B9EAE50B6ACC}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactingToSelection", "ReactingToSelection\ReactingToSelection.csproj", "{3EA249F1-12C3-45EB-813F-C18DFBEECE6A}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExportingFireCheckDataToUDA", "ExportingFireCheckDataToUDA\ExportingFireCheckDataToUDA.csproj", "{B8D97D9C-45A5-4ABE-ABAC-B36320E48DCF}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {38984DD1-D052-4B17-B2E0-8C96E04EF353}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {38984DD1-D052-4B17-B2E0-8C96E04EF353}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {38984DD1-D052-4B17-B2E0-8C96E04EF353}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {38984DD1-D052-4B17-B2E0-8C96E04EF353}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {642C6C7B-DBDF-4865-91FD-56609D661E71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {642C6C7B-DBDF-4865-91FD-56609D661E71}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {642C6C7B-DBDF-4865-91FD-56609D661E71}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {642C6C7B-DBDF-4865-91FD-56609D661E71}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {3EC3F9B8-94DF-4BD5-8074-7B39A6834DA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {3EC3F9B8-94DF-4BD5-8074-7B39A6834DA4}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {3EC3F9B8-94DF-4BD5-8074-7B39A6834DA4}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {3EC3F9B8-94DF-4BD5-8074-7B39A6834DA4}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {36DA71E5-9802-4A27-91C7-0B484DB33790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {36DA71E5-9802-4A27-91C7-0B484DB33790}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {36DA71E5-9802-4A27-91C7-0B484DB33790}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {36DA71E5-9802-4A27-91C7-0B484DB33790}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {372E7664-E1DE-4002-A9C5-B9EAE50B6ACC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {372E7664-E1DE-4002-A9C5-B9EAE50B6ACC}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {372E7664-E1DE-4002-A9C5-B9EAE50B6ACC}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {372E7664-E1DE-4002-A9C5-B9EAE50B6ACC}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {3EA249F1-12C3-45EB-813F-C18DFBEECE6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {3EA249F1-12C3-45EB-813F-C18DFBEECE6A}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {3EA249F1-12C3-45EB-813F-C18DFBEECE6A}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {3EA249F1-12C3-45EB-813F-C18DFBEECE6A}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {B8D97D9C-45A5-4ABE-ABAC-B36320E48DCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {B8D97D9C-45A5-4ABE-ABAC-B36320E48DCF}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {B8D97D9C-45A5-4ABE-ABAC-B36320E48DCF}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {B8D97D9C-45A5-4ABE-ABAC-B36320E48DCF}.Release|Any CPU.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(ExtensibilityGlobals) = postSolution 59 | SolutionGuid = {E88C85FC-48A6-4805-A86B-CD7F7F2B1934} 60 | EndGlobalSection 61 | EndGlobal 62 | --------------------------------------------------------------------------------