From 871355e07b506052ab5b9d85877de45eff0e51c4 Mon Sep 17 00:00:00 2001 From: Evgeny Redikultsev Date: Fri, 10 May 2024 20:27:57 +0500 Subject: [PATCH] Tuple crack calculator was changed --- .../Libraries/LoaderCalculator.dll | Bin 86016 -> 88064 bytes .../Models/Materials/ICrackedMaterial.cs | 14 ++ .../Models/Materials/IConcreteLibMaterial.cs | 7 +- .../Analyses/ByForces/ForceCalculator.cs | 37 ++--- .../Cracking/AverageDiameterLogic.cs | 12 +- .../Cracking/CrackWidthLogicSP63.cs | 28 +++- .../CrackedSectionTriangulationLogic.cs | 82 ++++++++++++ .../Cracking/IAverageDiameterLogic.cs | 3 +- .../Cracking/ICrackWidthLogic.cs | 5 +- .../ICrackedSectionTriangulationLogic.cs | 37 +++++ .../Cracking/ITensileAreaLogic.cs | 3 +- .../Cracking/LengthBetweenCracksLogicSP63.cs | 37 ++++- .../Cracking/TensileAreaLogicSP63.cs | 29 +++- .../Cracking/TupleCrackCalculator.cs | 75 ++++++----- .../Primitives/INdmPrimitive.cs | 24 ++++ .../Primitives/IVisualProperty.cs | 12 ++ .../Primitives/RebarPrimitive.cs | 24 +++- .../Triangulations/RebarTriangulationLogic.cs | 51 +++++-- .../RebarTriangulationLogicOptions.cs | 5 +- .../CheckPrimitivesForMeshingLogic.cs | 47 +++++++ .../ICheckPrimitivesForMeshingLogic.cs | 16 +++ .../NdmPrimitives/IMeshHasDivisionLogic.cs | 18 +++ .../NdmPrimitives/IMeshPrimitiveLogic.cs | 19 +++ .../ITriangulatePrimitiveLogic.cs | 1 - .../NdmPrimitives/MeshCrackedConcreteLogic.cs | 98 ++++++++++++++ .../NdmPrimitives/MeshHasDivisionLogic.cs | 41 ++++++ .../NdmPrimitives/MeshPrimitiveLogic.cs | 34 +++++ .../TriangulatePrimitiveLogic.cs | 126 ++++++++++-------- .../ForceCalculatorTests/RCSectionsTest.cs | 8 +- 29 files changed, 745 insertions(+), 148 deletions(-) create mode 100644 StructureHelperCommon/Models/Materials/ICrackedMaterial.cs create mode 100644 StructureHelperLogics/NdmCalculations/Cracking/CrackedSectionTriangulationLogic.cs create mode 100644 StructureHelperLogics/NdmCalculations/Cracking/ICrackedSectionTriangulationLogic.cs create mode 100644 StructureHelperLogics/Services/NdmPrimitives/CheckPrimitivesForMeshingLogic.cs create mode 100644 StructureHelperLogics/Services/NdmPrimitives/ICheckPrimitivesForMeshingLogic.cs create mode 100644 StructureHelperLogics/Services/NdmPrimitives/IMeshHasDivisionLogic.cs create mode 100644 StructureHelperLogics/Services/NdmPrimitives/IMeshPrimitiveLogic.cs create mode 100644 StructureHelperLogics/Services/NdmPrimitives/MeshCrackedConcreteLogic.cs create mode 100644 StructureHelperLogics/Services/NdmPrimitives/MeshHasDivisionLogic.cs create mode 100644 StructureHelperLogics/Services/NdmPrimitives/MeshPrimitiveLogic.cs diff --git a/StructureHelper/Libraries/LoaderCalculator.dll b/StructureHelper/Libraries/LoaderCalculator.dll index d31e226236a3209d011d20cd6764ff1ddb6852f7..53f5bf2d4c9c35e3dd03816dee9a5fced6df7b6a 100644 GIT binary patch literal 88064 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%0A&9a`+EJO8G>*#pS6oMBN*3J$ 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 /// Humidity of concrete /// diff --git a/StructureHelperLogics/NdmCalculations/Analyses/ByForces/ForceCalculator.cs b/StructureHelperLogics/NdmCalculations/Analyses/ByForces/ForceCalculator.cs index 6d4803d..1101562 100644 --- a/StructureHelperLogics/NdmCalculations/Analyses/ByForces/ForceCalculator.cs +++ b/StructureHelperLogics/NdmCalculations/Analyses/ByForces/ForceCalculator.cs @@ -40,7 +40,7 @@ namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces { TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); var checkResult = CheckInputData(); - if (checkResult != "") + if (checkResult != string.Empty) { Result = new ForcesResults() { @@ -49,11 +49,8 @@ namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces }; return; } - else - { - GetCombinations(); - CalculateResult(); - } + GetCombinations(); + CalculateResult(); } private void CalculateResult() @@ -199,18 +196,10 @@ namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces private string CheckInputData() { - string result = ""; - try + string result = string.Empty; + if (! Primitives.Any()) { - triangulateLogic = new TriangulatePrimitiveLogic() - { - Primitives = Primitives - }; - triangulateLogic.CheckPrimitives(Primitives); - } - catch (Exception ex) - { - result += ex; + result += "Calculator does not contain any primitives \n"; } if (ForceActions.Count == 0) { @@ -222,8 +211,20 @@ namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces } if (CalcTermsList.Count == 0) { - result += "Calculator does not contain any duration \n"; + result += "Calculator does not contain any calc term \n"; } + //try + //{ + // triangulateLogic = new TriangulatePrimitiveLogic() + // { + // Primitives = Primitives + // }; + // triangulateLogic.CheckPrimitives(Primitives); + //} + //catch (Exception ex) + //{ + // result += ex; + //} return result; } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/AverageDiameterLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/AverageDiameterLogic.cs index 23cde59..5cade83 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/AverageDiameterLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/AverageDiameterLogic.cs @@ -1,5 +1,7 @@ using LoaderCalculator.Data.Ndms; using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models.Loggers; +using StructureHelperCommon.Models; using System; using System.Collections.Generic; using System.Linq; @@ -11,22 +13,30 @@ namespace StructureHelperLogics.NdmCalculations.Cracking public class AverageDiameterLogic : IAverageDiameterLogic { public IEnumerable Rebars { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } public double GetAverageDiameter() { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); Check(); var rebarArea = Rebars .Sum(x => x.Area); + TraceLogger?.AddMessage($"Summary rebar area As = {rebarArea}"); var rebarCount = Rebars.Count(); + TraceLogger?.AddMessage($"Rebar count n = {rebarCount}"); var averageArea = rebarArea / rebarCount; + TraceLogger?.AddMessage($"Average rebar area As = {averageArea}"); var diameter = Math.Sqrt(averageArea / Math.PI); + TraceLogger?.AddMessage($"Average rebar diameter ds = {diameter}"); return diameter; } private void Check() { if (!Rebars.Any()) { - throw new StructureHelperException(ErrorStrings.DataIsInCorrect + $": rebars count must be greater then zero"); + string errorString = ErrorStrings.DataIsInCorrect + $": rebars count must be greater then zero"; + TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error); + throw new StructureHelperException(errorString); } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/CrackWidthLogicSP63.cs b/StructureHelperLogics/NdmCalculations/Cracking/CrackWidthLogicSP63.cs index 3a9637f..371cf48 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/CrackWidthLogicSP63.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/CrackWidthLogicSP63.cs @@ -1,4 +1,6 @@ using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Loggers; using System; using System.Collections.Generic; using System.Linq; @@ -11,9 +13,12 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { CrackWidthLogicInputDataSP63 inputData; public ICrackWidthLogicInputData InputData {get;set;} + public IShiftTraceLogger? TraceLogger { get; set; } public double GetCrackWidth() { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + TraceLogger?.AddMessage("Method of crack width calculation based on SP 63.13330.2018"); CheckOptions(); //check if strain of concrete greater than strain of rebar if (inputData.ConcreteStrain > inputData.RebarStrain) { return 0d; } @@ -24,31 +29,42 @@ namespace StructureHelperLogics.NdmCalculations.Cracking private void CheckOptions() { + string errorString = string.Empty; if (InputData is not CrackWidthLogicInputDataSP63) { - throw new StructureHelperException(ErrorStrings.ExpectedWas(typeof(CrackWidthLogicInputDataSP63), InputData.GetType())); + errorString = ErrorStrings.ExpectedWas(typeof(CrackWidthLogicInputDataSP63), InputData.GetType()); } inputData = InputData as CrackWidthLogicInputDataSP63; if (inputData.Length <=0d) { - throw new StructureHelperException(ErrorStrings.DataIsInCorrect + $": length between cracks L={inputData.Length} must be greate than zero"); + errorString = ErrorStrings.DataIsInCorrect + $": length between cracks L={inputData.Length} must be greate than zero"; } if (inputData.TermFactor <= 0d) { - throw new StructureHelperException(ErrorStrings.DataIsInCorrect + $": Term factor {inputData.TermFactor} must be greate than zero"); + errorString = ErrorStrings.DataIsInCorrect + $": Term factor {inputData.TermFactor} must be greate than zero"; + } if (inputData.BondFactor <= 0d) { - throw new StructureHelperException(ErrorStrings.DataIsInCorrect + $": Bond factor {inputData.BondFactor} must be greate than zero"); + errorString = ErrorStrings.DataIsInCorrect + $": Bond factor {inputData.BondFactor} must be greate than zero"; + } if (inputData.StressStateFactor <= 0d) { - throw new StructureHelperException(ErrorStrings.DataIsInCorrect + $": Bond factor {inputData.StressStateFactor} must be greate than zero"); + errorString = ErrorStrings.DataIsInCorrect + $": Bond factor {inputData.StressStateFactor} must be greate than zero"; + } if (inputData.PsiSFactor <= 0d) { - throw new StructureHelperException(ErrorStrings.DataIsInCorrect + $": PsiS factor {inputData.PsiSFactor} must be greate than zero"); + errorString = ErrorStrings.DataIsInCorrect + $": PsiS factor {inputData.PsiSFactor} must be greate than zero"; + } + if (errorString != string.Empty) + { + TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error); + throw new StructureHelperException(errorString); + } + } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/CrackedSectionTriangulationLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/CrackedSectionTriangulationLogic.cs new file mode 100644 index 0000000..b4dd4c5 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/CrackedSectionTriangulationLogic.cs @@ -0,0 +1,82 @@ +using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Enums; +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Loggers; +using StructureHelperLogics.Models.Primitives; +using StructureHelperLogics.NdmCalculations.Primitives; +using StructureHelperLogics.Services.NdmPrimitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class CrackedSectionTriangulationLogic : ICrackedSectionTriangulationLogic + { + const LimitStates limitState = LimitStates.SLS; + const CalcTerms shortTerm = CalcTerms.ShortTerm; + + private ITriangulatePrimitiveLogic triangulateLogic; + private string ndmPrimitiveCountMessage; + + public IEnumerable NdmPrimitives { get; private set; } + public IShiftTraceLogger? TraceLogger { get; set; } + public CrackedSectionTriangulationLogic(IEnumerable ndmPrimitives) + { + NdmPrimitives = ndmPrimitives; + ndmPrimitiveCountMessage = $"Source collection containes {NdmPrimitives.Count()} primitives"; + triangulateLogic = new TriangulatePrimitiveLogic + { + Primitives = NdmPrimitives, + LimitState = limitState, + CalcTerm = shortTerm, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + } + public List GetNdmCollection() + { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + TraceLogger?.AddMessage(ndmPrimitiveCountMessage, TraceLogStatuses.Debug); + triangulateLogic = new TriangulatePrimitiveLogic() + { + LimitState = limitState, + CalcTerm = shortTerm, + Primitives = NdmPrimitives, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + return triangulateLogic.GetNdms(); + } + public List GetCrackedNdmCollection() + { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + TraceLogger?.AddMessage(ndmPrimitiveCountMessage, TraceLogStatuses.Debug); + triangulateLogic = new TriangulatePrimitiveLogic(new MeshCrackedConcreteLogic()) + { + LimitState = limitState, + CalcTerm = shortTerm, + Primitives = NdmPrimitives, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + return triangulateLogic.GetNdms(); + } + + public List GetRebarPrimitives() + { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + TraceLogger?.AddMessage(ndmPrimitiveCountMessage, TraceLogStatuses.Debug); + List rebarPrimitives = new(); + foreach (var item in NdmPrimitives) + { + if (item is RebarPrimitive rebar) + { + TraceLogger?.AddMessage($"Primitive {rebar.Name} is rebar primitive", TraceLogStatuses.Service); + rebarPrimitives.Add(rebar); + } + } + TraceLogger?.AddMessage($"Obtained {rebarPrimitives.Count} rebar primitives"); + return rebarPrimitives; + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/IAverageDiameterLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/IAverageDiameterLogic.cs index 8ff8be3..573d15e 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/IAverageDiameterLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/IAverageDiameterLogic.cs @@ -1,4 +1,5 @@ using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Interfaces; using System; using System.Collections.Generic; using System.Linq; @@ -7,7 +8,7 @@ using System.Threading.Tasks; namespace StructureHelperLogics.NdmCalculations.Cracking { - public interface IAverageDiameterLogic + public interface IAverageDiameterLogic : ILogic { IEnumerable Rebars { get; set; } double GetAverageDiameter(); diff --git a/StructureHelperLogics/NdmCalculations/Cracking/ICrackWidthLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/ICrackWidthLogic.cs index 532995f..df024c5 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/ICrackWidthLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/ICrackWidthLogic.cs @@ -1,4 +1,5 @@ -using System; +using StructureHelperCommon.Infrastructures.Interfaces; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,7 +10,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking /// /// Logic for calculating width of crack /// - public interface ICrackWidthLogic + public interface ICrackWidthLogic : ILogic { ICrackWidthLogicInputData InputData { get; set; } /// diff --git a/StructureHelperLogics/NdmCalculations/Cracking/ICrackedSectionTriangulationLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/ICrackedSectionTriangulationLogic.cs new file mode 100644 index 0000000..2dd8afb --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/ICrackedSectionTriangulationLogic.cs @@ -0,0 +1,37 @@ +using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperLogics.NdmCalculations.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + /// + /// Logic for obtaining of collection of nms elementary part for regular and fully cracked section + /// + public interface ICrackedSectionTriangulationLogic : ILogic + { + /// + /// Source collection of ndm primitives + /// + IEnumerable NdmPrimitives { get; } + /// + /// Returns collection of ndm elementary parts + /// + /// + List GetNdmCollection(); + /// + /// Returns collection of ndm elementary parts where concrete doesn't work in tension + /// + /// + List GetCrackedNdmCollection(); + /// + /// Return collection of primitives which contain only rebars + /// + /// + List GetRebarPrimitives(); + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/ITensileAreaLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/ITensileAreaLogic.cs index 47eab43..fc422aa 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/ITensileAreaLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/ITensileAreaLogic.cs @@ -1,5 +1,6 @@ using LoaderCalculator.Data.Matrix; using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Interfaces; using StructureHelperCommon.Models.Forces; using System; using System.Collections.Generic; @@ -12,7 +13,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking /// /// Logic fo calculating of tensile area of RC crosssection /// - public interface ITensileAreaLogic + public interface ITensileAreaLogic : ILogic { IEnumerable NdmCollection { get; set; } IStrainMatrix StrainMatrix { get; set; } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/LengthBetweenCracksLogicSP63.cs b/StructureHelperLogics/NdmCalculations/Cracking/LengthBetweenCracksLogicSP63.cs index 59376ef..bd6487e 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/LengthBetweenCracksLogicSP63.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/LengthBetweenCracksLogicSP63.cs @@ -1,6 +1,10 @@ using LoaderCalculator.Data.Matrix; using LoaderCalculator.Data.Ndms; +using LoaderCalculator.Logics; +using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Loggers; +using StructureHelperLogics.Services; using System; using System.Collections.Generic; using System.Linq; @@ -18,6 +22,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking readonly IAverageDiameterLogic diameterLogic; readonly ITensileAreaLogic tensileAreaLogic; + IStressLogic stressLogic; public IEnumerable NdmCollection { get; set; } public IStrainMatrix StrainMatrix { get; set; } public IShiftTraceLogger? TraceLogger { get; set; } @@ -26,6 +31,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { this.diameterLogic = diameterLogic; this.tensileAreaLogic = tensileAreaLogic; + stressLogic = new StressLogic(); } public LengthBetweenCracksLogicSP63() : this @@ -34,18 +40,43 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { } public double GetLength() { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); var rebars = NdmCollection - .Where(x => x is RebarNdm) + .Where(x => x is RebarNdm & stressLogic.GetTotalStrain(StrainMatrix, x) > 0d) .Select(x => x as RebarNdm); + if (! rebars.Any()) + { + string errorString = ErrorStrings.DataIsInCorrect + ": Collection of rebars does not contain any tensile rebars"; + TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error); + throw new StructureHelperException(errorString); + } + if (TraceLogger is not null) + { + TraceService.TraceNdmCollection(TraceLogger, rebars); + } var rebarArea = rebars.Sum(x => x.Area * x.StressScale); + TraceLogger?.AddMessage($"Summary rebar area As = {rebarArea}"); + diameterLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); diameterLogic.Rebars = rebars; var rebarDiameter = diameterLogic.GetAverageDiameter(); + TraceLogger?.AddMessage($"Average rebar diameter ds = {rebarDiameter}"); + tensileAreaLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); tensileAreaLogic.NdmCollection = NdmCollection; tensileAreaLogic.StrainMatrix = StrainMatrix; var concreteArea = tensileAreaLogic.GetTensileArea(); + TraceLogger?.AddMessage($"Concrete effective area Ac,eff = {concreteArea}(m^2)"); var length = concreteArea / rebarArea * rebarDiameter; - length = new List { length, minDiameterFactor * rebarDiameter, minLength }.Max(); - length = new List { length, maxDiameterFactor * rebarDiameter, maxLength }.Min(); + TraceLogger?.AddMessage($"Base length between cracks Lcrc = {concreteArea} / {rebarArea} * {rebarDiameter} = {length}(m)"); + double minLengthByDiameter = minDiameterFactor * rebarDiameter; + TraceLogger?.AddMessage($"Minimum length by diameter Lcrc = {minDiameterFactor} * {rebarDiameter} = {minLengthByDiameter}(m)"); + TraceLogger?.AddMessage($"Minimum length Lcrc = {minLength}"); + length = new List { length, minLengthByDiameter, minLength }.Max(); + TraceLogger?.AddMessage($"Minimum length Lcrc = max({length}, {minLengthByDiameter}, {minLength}) = {length}(m)"); + double maxLengthByDiameter = maxDiameterFactor * rebarDiameter; + TraceLogger?.AddMessage($"Maximum length by diameter Lcrc = {maxDiameterFactor} * {rebarDiameter} = {maxLengthByDiameter}(m)"); + TraceLogger?.AddMessage($"Maximum length Lcrc = {maxLength}"); + length = new List { length, maxLengthByDiameter, maxLength }.Min(); + TraceLogger?.AddMessage($"Maximun length Lcrc = min({length}, {maxLengthByDiameter}, {maxLength}) = {length}(m)"); return length; } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/TensileAreaLogicSP63.cs b/StructureHelperLogics/NdmCalculations/Cracking/TensileAreaLogicSP63.cs index 3c7324c..d9dc76e 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/TensileAreaLogicSP63.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/TensileAreaLogicSP63.cs @@ -2,7 +2,9 @@ using LoaderCalculator.Data.Matrix; using LoaderCalculator.Data.Ndms; using LoaderCalculator.Logics; +using StructureHelperCommon.Models; using StructureHelperCommon.Models.Forces; +using StructureHelperCommon.Models.Loggers; using StructureHelperCommon.Services.Forces; using System; using System.Collections.Generic; @@ -16,29 +18,44 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { const double maxConcreteFactor = 0.5d; const double minConcreteFactor = 0.1d; - const double minRebarFactor = 3d; + const double minRebarFactor = 9d; private static IStressLogic stressLogic => new StressLogic(); public IEnumerable NdmCollection { get; set; } public IStrainMatrix StrainMatrix { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } public double GetTensileArea() { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + var rebarCollection = NdmCollection - .Where(x => x is RebarNdm); + .Where(x => x is RebarNdm & stressLogic.GetTotalStrain(StrainMatrix, x) > 0d); var rebarArea = rebarCollection. Sum(x => x.Area * x.StressScale); + TraceLogger?.AddMessage($"Summary rebar area As = {rebarArea}"); var concreteCollection = NdmCollection .Where(x => x.Material is ConcreteMaterial); var concreteArea = concreteCollection .Sum(x => x.Area * x.StressScale); + TraceLogger?.AddMessage($"Concrete area Ac = {concreteArea}"); var concreteTensileArea = concreteCollection .Where(x => stressLogic.GetTotalStrainWithPrestrain(StrainMatrix, x) > 0d) .Sum(x => x.Area * x.StressScale); - - concreteTensileArea = Math.Max(concreteTensileArea, rebarArea * minRebarFactor); - concreteTensileArea = Math.Max(concreteTensileArea, concreteArea * minConcreteFactor); - concreteTensileArea = Math.Min(concreteTensileArea, concreteArea * maxConcreteFactor); + TraceLogger?.AddMessage($"Concrete tensile area Ac,t = {concreteTensileArea}"); + double areaByRebar = rebarArea * minRebarFactor; + TraceLogger?.AddMessage($"Concrete area is considered not less than {minRebarFactor} of area of rebars"); + TraceLogger?.AddMessage($"Minimum concrete effective area from area of rebar Ac,eff = {rebarArea} * {minRebarFactor} = {areaByRebar}"); + concreteTensileArea = Math.Max(concreteTensileArea, areaByRebar); + double areaByMinConcreteFactor = concreteArea * minConcreteFactor; + TraceLogger?.AddMessage($"Concrete area is considered not less than {minConcreteFactor} of area of rebars"); + TraceLogger?.AddMessage($"Minimum concrete effective area Ac,eff = {concreteArea} * {minConcreteFactor} = {areaByMinConcreteFactor}"); + concreteTensileArea = Math.Max(concreteTensileArea, areaByMinConcreteFactor); + double areaByMaxConcreteFactor = concreteArea * maxConcreteFactor; + TraceLogger?.AddMessage($"Concrete area is considered not greater than {maxConcreteFactor} of area of rebars"); + TraceLogger?.AddMessage($"Maximum concrete effective area Ac,eff = {concreteArea} * {maxConcreteFactor} = {areaByMaxConcreteFactor}"); + concreteTensileArea = Math.Min(concreteTensileArea, areaByMaxConcreteFactor); + TraceLogger?.AddMessage($"Concrete effective area Ac,eff = {concreteTensileArea}"); return concreteTensileArea; } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs b/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs index 43ecc4f..0ad489b 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs @@ -17,11 +17,13 @@ namespace StructureHelperLogics.NdmCalculations.Cracking private static readonly ILengthBetweenCracksLogic lengthLogic = new LengthBetweenCracksLogicSP63(); private TupleCrackResult result; private IEnumerable ndmPrimitives; + private ICrackedSectionTriangulationLogic triangulationLogic; private List? rebarPrimitives; - private IEnumerable defaultNdm; - private IEnumerable fulyCrackedNdm; + private IEnumerable defaultNdms; + private IEnumerable fulyCrackedNdms; private CrackForceResult crackForceResult; - private StrainTuple strainTuple; + private StrainTuple longDefaultStrainTuple; + private StrainTuple shortDefaultStrainTuple; private ITriangulatePrimitiveLogic triangulateLogic; public string Name { get; set; } @@ -37,6 +39,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking try { + TraceLogger?.AddMessage($"Calculation of crack width by force combination"); ProcessCalculations(); TraceLogger?.AddMessage(LoggerStrings.CalculationHasDone); @@ -46,7 +49,6 @@ namespace StructureHelperLogics.NdmCalculations.Cracking result.IsValid = false; result.Description += ex; TraceLogger?.AddMessage(LoggerStrings.CalculationError + ex, TraceLogStatuses.Error); - } } @@ -64,7 +66,10 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { CheckInputData(); Triangulate(); - CalcStrainMatrix(); + longDefaultStrainTuple = CalcStrainMatrix(InputData.LongTermTuple, defaultNdms); + shortDefaultStrainTuple = CalcStrainMatrix(InputData.LongTermTuple, defaultNdms); + var longLength = GetLengthBetweenCracks(longDefaultStrainTuple); + var shortLength = GetLengthBetweenCracks(shortDefaultStrainTuple); CalcCrackForce(); var crackInputData = GetCrackInputData(); var calculator = new RebarCrackCalculator @@ -77,63 +82,69 @@ namespace StructureHelperLogics.NdmCalculations.Cracking crackInputData.RebarPrimitive = item; calculator.Run(); var rebarResult = calculator.Result as RebarCrackResult; - //if (crackForceResult.IsSectionCracked == false) - //{ - // rebarResult.CrackWidth = 0d; - //} result.RebarResults.Add(rebarResult); } } - private void CalcStrainMatrix() + private StrainTuple CalcStrainMatrix(IForceTuple forceTuple, IEnumerable ndms) { - IForceTupleInputData inputData = new ForceTupleInputData() { NdmCollection = defaultNdm, Tuple = InputData.LongTermTuple}; - IForceTupleCalculator calculator = new ForceTupleCalculator() { InputData = inputData }; + IForceTupleInputData inputData = new ForceTupleInputData() + { + NdmCollection = ndms, + Tuple = forceTuple + }; + IForceTupleCalculator calculator = new ForceTupleCalculator() + { + InputData = inputData, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; calculator.Run(); var forceResult = calculator.Result as IForcesTupleResult; - strainTuple = TupleConverter.ConvertToStrainTuple(forceResult.LoaderResults.StrainMatrix); + var strain = TupleConverter.ConvertToStrainTuple(forceResult.LoaderResults.StrainMatrix); + return strain; } private RebarCrackInputData GetCrackInputData() { - lengthLogic.NdmCollection = defaultNdm; - lengthLogic.StrainMatrix = TupleConverter.ConvertToLoaderStrainMatrix(strainTuple); + lengthLogic.NdmCollection = defaultNdms; + lengthLogic.StrainMatrix = TupleConverter.ConvertToLoaderStrainMatrix(longDefaultStrainTuple); var length = lengthLogic.GetLength(); var crackInputData = new RebarCrackInputData { PsiSFactor = crackForceResult.PsiS, Length = length, - StrainTuple = strainTuple + StrainTuple = longDefaultStrainTuple }; return crackInputData; } + private double GetLengthBetweenCracks(StrainTuple strainTuple) + { + var logic = new LengthBetweenCracksLogicSP63() + { + NdmCollection = defaultNdms, + TraceLogger = TraceLogger + }; + logic.StrainMatrix = TupleConverter.ConvertToLoaderStrainMatrix(strainTuple); + return logic.GetLength(); + } + private void Triangulate() { - ndmPrimitives = InputData.NdmPrimitives; - rebarPrimitives = new List(); - foreach (var item in ndmPrimitives) + triangulationLogic = new CrackedSectionTriangulationLogic(InputData.NdmPrimitives) { - if (item is RebarPrimitive) - { - rebarPrimitives.Add(item as RebarPrimitive); - } - } - triangulateLogic = new TriangulatePrimitiveLogic() - { - Primitives = ndmPrimitives, - LimitState = LimitStates.SLS, - CalcTerm = CalcTerms.ShortTerm, TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) - }; - defaultNdm = triangulateLogic.GetNdms(); + }; + rebarPrimitives = triangulationLogic.GetRebarPrimitives(); + defaultNdms = triangulationLogic.GetNdmCollection(); + fulyCrackedNdms = triangulationLogic.GetCrackedNdmCollection(); } private void CalcCrackForce() { var calculator = new CrackForceCalculator(); calculator.EndTuple = InputData.LongTermTuple; - calculator.NdmCollection = defaultNdm; + calculator.NdmCollection = defaultNdms; calculator.Run(); crackForceResult = calculator.Result as CrackForceResult; } diff --git a/StructureHelperLogics/NdmCalculations/Primitives/INdmPrimitive.cs b/StructureHelperLogics/NdmCalculations/Primitives/INdmPrimitive.cs index ad6de4f..e3621b3 100644 --- a/StructureHelperLogics/NdmCalculations/Primitives/INdmPrimitive.cs +++ b/StructureHelperLogics/NdmCalculations/Primitives/INdmPrimitive.cs @@ -14,18 +14,42 @@ using StructureHelperCommon.Models.Parameters; namespace StructureHelperLogics.NdmCalculations.Primitives { + /// + /// Geometrical primitive which generates ndm elemtntary part + /// public interface INdmPrimitive : ISaveable, ICloneable { + /// + /// Name of primitive + /// string? Name { get; set; } + /// + /// Base point of primitive + /// IPoint2D Center { get; } + /// + /// Host cross-section for primitive + /// ICrossSection? CrossSection { get; set; } + /// + /// Material of primitive + /// IHeadMaterial? HeadMaterial { get; set; } /// /// Flag of triangulation /// bool Triangulate { get; set; } + /// + /// Prestrain assigned from user + /// StrainTuple UsersPrestrain { get; } + /// + /// Prestrain assigned from calculations + /// StrainTuple AutoPrestrain { get; } + /// + /// Visual settings + /// IVisualProperty VisualProperty {get; } IEnumerable GetNdms(ITriangulationOptions triangulationOptions); diff --git a/StructureHelperLogics/NdmCalculations/Primitives/IVisualProperty.cs b/StructureHelperLogics/NdmCalculations/Primitives/IVisualProperty.cs index c93eda5..b0727f1 100644 --- a/StructureHelperLogics/NdmCalculations/Primitives/IVisualProperty.cs +++ b/StructureHelperLogics/NdmCalculations/Primitives/IVisualProperty.cs @@ -9,10 +9,22 @@ namespace StructureHelperLogics.NdmCalculations.Primitives { public interface IVisualProperty { + /// + /// Flag of visibility + /// bool IsVisible { get; set; } Color Color { get; set; } + /// + /// Flag of assigning of color from material or from primitive's settings + /// bool SetMaterialColor { get; set; } + /// + /// Index by z-coordinate + /// int ZIndex { get; set; } + /// + /// Opacity of filling + /// double Opacity { get; set; } } } diff --git a/StructureHelperLogics/NdmCalculations/Primitives/RebarPrimitive.cs b/StructureHelperLogics/NdmCalculations/Primitives/RebarPrimitive.cs index 7a0690f..b0e40a1 100644 --- a/StructureHelperLogics/NdmCalculations/Primitives/RebarPrimitive.cs +++ b/StructureHelperLogics/NdmCalculations/Primitives/RebarPrimitive.cs @@ -68,13 +68,35 @@ namespace StructureHelperLogics.NdmCalculations.Primitives } public IEnumerable GetNdms(ITriangulationOptions triangulationOptions) + { + List ndms = new() + { + GetConcreteNdm(triangulationOptions), + GetRebarNdm(triangulationOptions) + }; + return ndms; + } + + public RebarNdm GetRebarNdm(ITriangulationOptions triangulationOptions) { var options = new RebarTriangulationLogicOptions(this) { triangulationOptions = triangulationOptions }; var logic = new RebarTriangulationLogic(options); - return logic.GetNdmCollection(); + var rebar = logic.GetRebarNdm(); + return rebar; + } + + public Ndm GetConcreteNdm(ITriangulationOptions triangulationOptions) + { + var options = new RebarTriangulationLogicOptions(this) + { + triangulationOptions = triangulationOptions + }; + var logic = new RebarTriangulationLogic(options); + var concrete = logic.GetConcreteNdm(); + return concrete; } public List GetValuePoints() diff --git a/StructureHelperLogics/NdmCalculations/Triangulations/RebarTriangulationLogic.cs b/StructureHelperLogics/NdmCalculations/Triangulations/RebarTriangulationLogic.cs index b63607c..53e4380 100644 --- a/StructureHelperLogics/NdmCalculations/Triangulations/RebarTriangulationLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Triangulations/RebarTriangulationLogic.cs @@ -3,8 +3,10 @@ using LoaderCalculator.Data.Matrix; using LoaderCalculator.Data.Ndms; using LoaderCalculator.Data.Ndms.Transformations; using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models.Forces; using StructureHelperCommon.Models.Shapes; using StructureHelperCommon.Services.Forces; +using StructureHelperLogics.Models.Primitives; using System; using System.Collections.Generic; using System.Linq; @@ -23,14 +25,20 @@ namespace StructureHelperLogics.NdmCalculations.Triangulations } public IEnumerable GetNdmCollection() { - var concreteNdm = new Ndm + List ndmCollection = new(); + if (options.HostPrimitive is not null) { - CenterX = options.Center.X, - CenterY = options.Center.Y, - Area = options.Area, - Material = options.HostMaterial.GetLoaderMaterial(options.triangulationOptions.LimiteState, options.triangulationOptions.CalcTerm), - StressScale = -1d - }; + var concreteNdm = GetConcreteNdm(); + ndmCollection.Add(concreteNdm); + } + + var rebarNdm = GetRebarNdm(); + ndmCollection.Add(rebarNdm); + return ndmCollection; + } + + public RebarNdm GetRebarNdm() + { var rebarNdm = new RebarNdm { CenterX = options.Center.X, @@ -38,9 +46,32 @@ namespace StructureHelperLogics.NdmCalculations.Triangulations Area = options.Area, Material = options.HeadMaterial.GetLoaderMaterial(options.triangulationOptions.LimiteState, options.triangulationOptions.CalcTerm) }; - List ndmCollection = new() { concreteNdm, rebarNdm}; - NdmTransform.SetPrestrain(ndmCollection, TupleConverter.ConvertToLoaderStrainMatrix(options.Prestrain)); - return ndmCollection; + ; + NdmTransform.SetPrestrain(rebarNdm, TupleConverter.ConvertToLoaderStrainMatrix(options.Prestrain)); + return rebarNdm; + } + + public Ndm GetConcreteNdm() + { + var hostPrimitive = options.HostPrimitive; + var material = hostPrimitive + .HeadMaterial + .GetLoaderMaterial(options.triangulationOptions.LimiteState, options.triangulationOptions.CalcTerm); + + var prestrain = ForceTupleService.SumTuples(hostPrimitive.UsersPrestrain, + hostPrimitive.AutoPrestrain) + as StrainTuple; + + var concreteNdm = new Ndm + { + CenterX = options.Center.X, + CenterY = options.Center.Y, + Area = options.Area, + Material = material, + StressScale = -1d + }; + NdmTransform.SetPrestrain(concreteNdm, TupleConverter.ConvertToLoaderStrainMatrix(prestrain)); + return concreteNdm; } public void ValidateOptions(ITriangulationLogicOptions options) diff --git a/StructureHelperLogics/NdmCalculations/Triangulations/RebarTriangulationLogicOptions.cs b/StructureHelperLogics/NdmCalculations/Triangulations/RebarTriangulationLogicOptions.cs index e3d13d6..685b7b0 100644 --- a/StructureHelperLogics/NdmCalculations/Triangulations/RebarTriangulationLogicOptions.cs +++ b/StructureHelperLogics/NdmCalculations/Triangulations/RebarTriangulationLogicOptions.cs @@ -22,7 +22,8 @@ namespace StructureHelperLogics.NdmCalculations.Triangulations public double Area { get; } public StrainTuple Prestrain { get; set; } public IHeadMaterial HeadMaterial { get; set; } - public IHeadMaterial HostMaterial { get; set; } + public INdmPrimitive HostPrimitive { get; set; } + /// public RebarTriangulationLogicOptions(RebarPrimitive primitive) @@ -30,7 +31,7 @@ namespace StructureHelperLogics.NdmCalculations.Triangulations Center = primitive.Center.Clone() as Point2D; Area = primitive.Area; HeadMaterial = primitive.HeadMaterial; - HostMaterial = primitive.HostPrimitive.HeadMaterial; + HostPrimitive = primitive.HostPrimitive; Prestrain = ForceTupleService.SumTuples(primitive.UsersPrestrain, primitive.AutoPrestrain) as StrainTuple; } } diff --git a/StructureHelperLogics/Services/NdmPrimitives/CheckPrimitivesForMeshingLogic.cs b/StructureHelperLogics/Services/NdmPrimitives/CheckPrimitivesForMeshingLogic.cs new file mode 100644 index 0000000..b1901da --- /dev/null +++ b/StructureHelperLogics/Services/NdmPrimitives/CheckPrimitivesForMeshingLogic.cs @@ -0,0 +1,47 @@ +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Loggers; +using StructureHelperLogics.NdmCalculations.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.Services.NdmPrimitives +{ + public class CheckPrimitivesForMeshingLogic : ICheckPrimitivesForMeshingLogic + { + public IEnumerable Primitives { get; set; } + + public IShiftTraceLogger? TraceLogger { get; set; } + + public bool Check() + { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + if (!Primitives.Any()) + { + string errorMessage = string.Intern(ErrorStrings.DataIsInCorrect + $": Count of primitive must be greater than zero"); + TraceLogger?.AddMessage(errorMessage, TraceLogStatuses.Error); + throw new StructureHelperException(errorMessage); + } + if (!Primitives.Any(x => x.Triangulate == true)) + { + string errorMessage = string.Intern(ErrorStrings.DataIsInCorrect + $": There are not primitives to triangulate"); + TraceLogger?.AddMessage(errorMessage, TraceLogStatuses.Error); + throw new StructureHelperException(errorMessage); + } + foreach (var item in Primitives) + { + if (item.Triangulate == true & + item.HeadMaterial is null) + { + string errorMessage = string.Intern(ErrorStrings.DataIsInCorrect + $": Primitive: {item.Name} can't be triangulated since material is null"); + TraceLogger?.AddMessage(errorMessage, TraceLogStatuses.Error); + throw new StructureHelperException(errorMessage); + } + } + return true; + } + } +} diff --git a/StructureHelperLogics/Services/NdmPrimitives/ICheckPrimitivesForMeshingLogic.cs b/StructureHelperLogics/Services/NdmPrimitives/ICheckPrimitivesForMeshingLogic.cs new file mode 100644 index 0000000..4a2bb3f --- /dev/null +++ b/StructureHelperLogics/Services/NdmPrimitives/ICheckPrimitivesForMeshingLogic.cs @@ -0,0 +1,16 @@ +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperLogics.NdmCalculations.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.Services.NdmPrimitives +{ + public interface ICheckPrimitivesForMeshingLogic : ILogic + { + IEnumerable Primitives { get; set; } + bool Check(); + } +} diff --git a/StructureHelperLogics/Services/NdmPrimitives/IMeshHasDivisionLogic.cs b/StructureHelperLogics/Services/NdmPrimitives/IMeshHasDivisionLogic.cs new file mode 100644 index 0000000..e8094a7 --- /dev/null +++ b/StructureHelperLogics/Services/NdmPrimitives/IMeshHasDivisionLogic.cs @@ -0,0 +1,18 @@ +using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperLogics.NdmCalculations.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.Services.NdmPrimitives +{ + public interface IMeshHasDivisionLogic : ILogic + { + List NdmCollection { get; set; } + IHasDivisionSize Primitive { get; set; } + void MeshHasDivision(); + } +} diff --git a/StructureHelperLogics/Services/NdmPrimitives/IMeshPrimitiveLogic.cs b/StructureHelperLogics/Services/NdmPrimitives/IMeshPrimitiveLogic.cs new file mode 100644 index 0000000..47e61cd --- /dev/null +++ b/StructureHelperLogics/Services/NdmPrimitives/IMeshPrimitiveLogic.cs @@ -0,0 +1,19 @@ +using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperLogics.NdmCalculations.Primitives; +using StructureHelperLogics.NdmCalculations.Triangulations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.Services.NdmPrimitives +{ + public interface IMeshPrimitiveLogic : ILogic + { + INdmPrimitive Primitive { get; set; } + ITriangulationOptions TriangulationOptions { get; set; } + List MeshPrimitive(); + } +} diff --git a/StructureHelperLogics/Services/NdmPrimitives/ITriangulatePrimitiveLogic.cs b/StructureHelperLogics/Services/NdmPrimitives/ITriangulatePrimitiveLogic.cs index 43c6ecd..acc8bf8 100644 --- a/StructureHelperLogics/Services/NdmPrimitives/ITriangulatePrimitiveLogic.cs +++ b/StructureHelperLogics/Services/NdmPrimitives/ITriangulatePrimitiveLogic.cs @@ -11,6 +11,5 @@ namespace StructureHelperLogics.Services.NdmPrimitives LimitStates LimitState { get; set; } CalcTerms CalcTerm { get; set; } List GetNdms(); - bool CheckPrimitives(IEnumerable primitives); } } \ No newline at end of file diff --git a/StructureHelperLogics/Services/NdmPrimitives/MeshCrackedConcreteLogic.cs b/StructureHelperLogics/Services/NdmPrimitives/MeshCrackedConcreteLogic.cs new file mode 100644 index 0000000..157f089 --- /dev/null +++ b/StructureHelperLogics/Services/NdmPrimitives/MeshCrackedConcreteLogic.cs @@ -0,0 +1,98 @@ +using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Enums; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Loggers; +using StructureHelperCommon.Models.Materials; +using StructureHelperLogics.Models.Materials; +using StructureHelperLogics.Models.Primitives; +using StructureHelperLogics.NdmCalculations.Primitives; +using StructureHelperLogics.NdmCalculations.Triangulations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.Services.NdmPrimitives +{ + internal class MeshCrackedConcreteLogic : IMeshPrimitiveLogic + { + private IMeshPrimitiveLogic regularMeshLogic; + public List NdmCollection { get; set; } + public INdmPrimitive Primitive { get; set; } + public ITriangulationOptions TriangulationOptions { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } + + List IMeshPrimitiveLogic.MeshPrimitive() + { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + CheckPrimitive(); + List ndmCollection = new(); + if (Primitive.HeadMaterial.HelperMaterial is ICrackedMaterial) + { + TraceLogger?.AddMessage($"Primitive {Primitive.Name} is crackable primitive", TraceLogStatuses.Service); + var newPrimititve = Primitive.Clone() as INdmPrimitive; + SetNewMaterial(newPrimititve); + List ndms = GetNdms(newPrimititve); + ndmCollection.AddRange(ndms); + } + else if (Primitive is RebarPrimitive rebar) + { + TraceLogger?.AddMessage($"Primitive {Primitive.Name} is rebar primitive", TraceLogStatuses.Service); + var newPrimititve = rebar.Clone() as RebarPrimitive; + var newHostPrimitive = rebar.HostPrimitive.Clone() as INdmPrimitive; + SetNewMaterial(newHostPrimitive); + newPrimititve.HostPrimitive = newHostPrimitive; + List ndms = GetNdms(newPrimititve); + ndmCollection.AddRange(ndms); + } + else + { + TraceLogger?.AddMessage($"Primitive {Primitive.Name} is non-crackable primitive", TraceLogStatuses.Service); + List ndms = GetNdms(Primitive); + ndmCollection.AddRange(ndms); + } + return ndmCollection; + } + + private void SetNewMaterial(INdmPrimitive? newPrimititve) + { + TraceLogger?.AddMessage($"Process material {newPrimititve.HeadMaterial.Name} has started"); + var newMaterial = newPrimititve.HeadMaterial.HelperMaterial.Clone() as ICrackedMaterial; + TraceLogger?.AddMessage($"Set work in tension zone for material {newPrimititve.HeadMaterial.Name}"); + newMaterial.TensionForSLS = false; + newPrimititve.HeadMaterial.HelperMaterial = newMaterial as IHelperMaterial; + } + + private List GetNdms(INdmPrimitive primitive) + { + TraceLogger?.AddMessage($"Triangulation primitive has started"); + regularMeshLogic = new MeshPrimitiveLogic() + { + Primitive = primitive, + TriangulationOptions = TriangulationOptions, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + List ndms = regularMeshLogic.MeshPrimitive(); + return ndms; + } + + private void CheckPrimitive() + { + if (TriangulationOptions.LimiteState is not LimitStates.SLS) + { + string errorMessage = string.Intern(ErrorStrings.DataIsInCorrect + $": Limit state for cracking must correspondent limit state of serviceability"); + TraceLogger?.AddMessage(errorMessage, TraceLogStatuses.Error); + throw new StructureHelperException(errorMessage); + } + if (TriangulationOptions.CalcTerm is not CalcTerms.ShortTerm) + { + string errorMessage = string.Intern(ErrorStrings.DataIsInCorrect + $": Calc term for cracked concrete must correspondent short term"); + TraceLogger?.AddMessage(errorMessage, TraceLogStatuses.Error); + throw new StructureHelperException(errorMessage); + } + TraceLogger?.AddMessage($"Primitive check is ok"); + } + } +} diff --git a/StructureHelperLogics/Services/NdmPrimitives/MeshHasDivisionLogic.cs b/StructureHelperLogics/Services/NdmPrimitives/MeshHasDivisionLogic.cs new file mode 100644 index 0000000..c2d9bf0 --- /dev/null +++ b/StructureHelperLogics/Services/NdmPrimitives/MeshHasDivisionLogic.cs @@ -0,0 +1,41 @@ +using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Loggers; +using StructureHelperCommon.Models.Shapes; +using StructureHelperLogics.Models.Primitives; +using StructureHelperLogics.NdmCalculations.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.Services.NdmPrimitives +{ + public class MeshHasDivisionLogic : IMeshHasDivisionLogic + { + public List NdmCollection { get; set; } + public IHasDivisionSize Primitive { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } + + public void MeshHasDivision() + { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + if (Primitive is IHasDivisionSize hasDivision) + { + if (hasDivision.ClearUnderlying == true) + { + TraceLogger?.AddMessage("Removing of background part has started", TraceLogStatuses.Service); + NdmCollection + .RemoveAll(x => + hasDivision + .IsPointInside(new Point2D() + { + X = x.CenterX, + Y = x.CenterY + }) == true); + } + } + } + } +} diff --git a/StructureHelperLogics/Services/NdmPrimitives/MeshPrimitiveLogic.cs b/StructureHelperLogics/Services/NdmPrimitives/MeshPrimitiveLogic.cs new file mode 100644 index 0000000..7790dc0 --- /dev/null +++ b/StructureHelperLogics/Services/NdmPrimitives/MeshPrimitiveLogic.cs @@ -0,0 +1,34 @@ +using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Enums; +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Loggers; +using StructureHelperCommon.Models.Materials; +using StructureHelperLogics.Models.Materials; +using StructureHelperLogics.Models.Primitives; +using StructureHelperLogics.NdmCalculations.Primitives; +using StructureHelperLogics.NdmCalculations.Triangulations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.Services.NdmPrimitives +{ + public class MeshPrimitiveLogic : IMeshPrimitiveLogic + { + public INdmPrimitive Primitive { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } + public ITriangulationOptions TriangulationOptions { get; set; } + + public List MeshPrimitive() + { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + List ndmCollection = new(); + var itemNdms = Primitive.GetNdms(TriangulationOptions); + ndmCollection.AddRange(itemNdms); + TraceLogger?.AddMessage($"Triangulation of primitive {Primitive.Name} has finished, {itemNdms.Count()} part(s) were obtained", TraceLogStatuses.Service); + return ndmCollection; + } + } +} diff --git a/StructureHelperLogics/Services/NdmPrimitives/TriangulatePrimitiveLogic.cs b/StructureHelperLogics/Services/NdmPrimitives/TriangulatePrimitiveLogic.cs index be98af4..4b24777 100644 --- a/StructureHelperLogics/Services/NdmPrimitives/TriangulatePrimitiveLogic.cs +++ b/StructureHelperLogics/Services/NdmPrimitives/TriangulatePrimitiveLogic.cs @@ -2,7 +2,10 @@ using StructureHelperCommon.Infrastructures.Enums; using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Loggers; +using StructureHelperCommon.Models.Materials; using StructureHelperCommon.Models.Shapes; +using StructureHelperLogics.Models.Materials; using StructureHelperLogics.NdmCalculations.Primitives; using StructureHelperLogics.NdmCalculations.Triangulations; @@ -10,49 +13,85 @@ namespace StructureHelperLogics.Services.NdmPrimitives { public class TriangulatePrimitiveLogic : ITriangulatePrimitiveLogic { + private IMeshHasDivisionLogic divisionLogic; + private IMeshPrimitiveLogic meshLogic; private List ndmCollection; + private ICheckPrimitivesForMeshingLogic checkLogic; public IEnumerable Primitives { get; set; } public LimitStates LimitState { get; set; } public CalcTerms CalcTerm { get; set; } - public bool ConsiderCracking { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } - public TriangulatePrimitiveLogic() + + public TriangulatePrimitiveLogic(IMeshPrimitiveLogic meshPrimitiveLogic) { - ConsiderCracking = false; + meshLogic = meshPrimitiveLogic; } + + public TriangulatePrimitiveLogic() : this (new MeshPrimitiveLogic()) { } + public List GetNdms() { - TraceLogger?.AddMessage($"Total count of primitives n = {Primitives.Count()}", TraceLogStatuses.Service); - TraceLogger?.AddMessage($"Limit state is {LimitState}", TraceLogStatuses.Service); - TraceLogger?.AddMessage($"Calc term is {CalcTerm}", TraceLogStatuses.Service); - var orderedNdmPrimitives = Primitives.OrderBy(x => x.VisualProperty.ZIndex); + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + CheckPrimitives(); ndmCollection = new List(); - foreach (var item in orderedNdmPrimitives) + SetLogics(); + TraceInitialSettings(); + TriangulatePrimitives(); + return ndmCollection; + } + + private void TriangulatePrimitives() + { + var orderedNdmPrimitives = Primitives.OrderBy(x => x.VisualProperty.ZIndex); + foreach (var primitive in orderedNdmPrimitives) { - TraceLogger?.AddMessage($"Triangulation of primitive {item.Name} has started", TraceLogStatuses.Service); - ProcessHasDivision(item); - TriangulatePrimitive(item); + TriangulatePrimitive(primitive); } if (TraceLogger is not null) { TraceService.TraceNdmCollection(TraceLogger, ndmCollection); } - return ndmCollection; + TraceLogger?.AddMessage($"Triangulation of primitives has finished, {ndmCollection.Count} part(s) were obtained", TraceLogStatuses.Service); } - private void TriangulatePrimitive(INdmPrimitive item) + private void TraceInitialSettings() { - if (item.Triangulate == true) + TraceLogger?.AddMessage($"Total count of primitives n = {Primitives.Count()}", TraceLogStatuses.Service); + TraceLogger?.AddMessage($"Limit state is {LimitState}", TraceLogStatuses.Service); + TraceLogger?.AddMessage($"Calc term is {CalcTerm}", TraceLogStatuses.Service); + } + + private void SetLogics() + { + divisionLogic = new MeshHasDivisionLogic() { - var triangulationOptions = new TriangulationOptions() - { - LimiteState = LimitState, - CalcTerm = CalcTerm - }; - var itemNdms = item.GetNdms(triangulationOptions); - ndmCollection.AddRange(itemNdms); - TraceLogger?.AddMessage($"Triangulation of primitive {item.Name} was finished, {itemNdms.Count()} part(s) were obtained", TraceLogStatuses.Service); + NdmCollection = ndmCollection, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + var triangulationOptions = new TriangulationOptions() + { + LimiteState = LimitState, + CalcTerm = CalcTerm + }; + meshLogic.TriangulationOptions = triangulationOptions; + meshLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); + } + + private void TriangulatePrimitive(INdmPrimitive primitive) + { + TraceLogger?.AddMessage($"Triangulation of primitive {primitive.Name} has started", TraceLogStatuses.Service); + if (primitive is IHasDivisionSize hasDivision) + { + divisionLogic.Primitive = hasDivision; + divisionLogic.MeshHasDivision(); + } + if (primitive.Triangulate == true) + { + meshLogic.Primitive = primitive; + var ndms = meshLogic.MeshPrimitive(); + ndmCollection.AddRange(ndms); } else { @@ -60,45 +99,14 @@ namespace StructureHelperLogics.Services.NdmPrimitives } } - private void ProcessHasDivision(INdmPrimitive? item) + private bool CheckPrimitives() { - if (item is IHasDivisionSize hasDivision) + checkLogic = new CheckPrimitivesForMeshingLogic() { - if (hasDivision.ClearUnderlying == true) - { - TraceLogger?.AddMessage("Removing of background part has started", TraceLogStatuses.Service); - ndmCollection - .RemoveAll(x => - hasDivision - .IsPointInside(new Point2D() { X = x.CenterX, Y = x.CenterY }) == true); - } - } - } - - public bool CheckPrimitives(IEnumerable primitives) - { - if (!primitives.Any()) - { - string errorMessage = string.Intern(ErrorStrings.DataIsInCorrect + $": Count of primitive must be greater than zero"); - TraceLogger?.AddMessage(errorMessage, TraceLogStatuses.Error); - throw new StructureHelperException(errorMessage); - } - if (!primitives.Any(x => x.Triangulate == true)) - { - string errorMessage = string.Intern(ErrorStrings.DataIsInCorrect + $": There are not primitives to triangulate"); - TraceLogger?.AddMessage(errorMessage, TraceLogStatuses.Error); - throw new StructureHelperException(errorMessage); - } - foreach (var item in primitives) - { - if (item.Triangulate == true & - item.HeadMaterial is null) - { - string errorMessage = string.Intern(ErrorStrings.DataIsInCorrect + $": Primitive: {item.Name} can't be triangulated since material is null"); - TraceLogger?.AddMessage(errorMessage, TraceLogStatuses.Error); - throw new StructureHelperException(errorMessage); - } - } + Primitives = Primitives, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + checkLogic.Check(); return true; } } diff --git a/StructureHelperTests/FunctionalTests/Ndms/Calculators/ForceCalculatorTests/RCSectionsTest.cs b/StructureHelperTests/FunctionalTests/Ndms/Calculators/ForceCalculatorTests/RCSectionsTest.cs index 24f06db..98eb362 100644 --- a/StructureHelperTests/FunctionalTests/Ndms/Calculators/ForceCalculatorTests/RCSectionsTest.cs +++ b/StructureHelperTests/FunctionalTests/Ndms/Calculators/ForceCalculatorTests/RCSectionsTest.cs @@ -15,7 +15,13 @@ namespace StructureHelperTests.FunctionalTests.Ndms.Calculators.ForceCalculatorT public void Run_ShouldPass(double width, double height, double topDiametr, double bottomDiametr, int widthCount, int heightCount, bool isBuckling, double expectedKx, double expectedKy, double expectedEpsZ) { //Arrange - var template = new RectangleBeamTemplate(width, height) { TopDiameter = topDiametr, BottomDiameter = bottomDiametr, WidthCount = widthCount, HeightCount = heightCount}; + var template = new RectangleBeamTemplate(width, height) + { + TopDiameter = topDiametr, + BottomDiameter = bottomDiametr, + WidthCount = widthCount, + HeightCount = heightCount + }; var newSection = new SectionTemplate(new RectGeometryLogic(template)).GetCrossSection(); var calculator = newSection.SectionRepository.CalculatorsList[0] as IForceCalculator; calculator.CompressedMember.Buckling = isBuckling;