From 541f23c0a843b3d9f6f8aaf2ff97cadbb82d7492 Mon Sep 17 00:00:00 2001 From: Evgeny Redikultsev Date: Sat, 24 Feb 2024 17:59:37 +0500 Subject: [PATCH] IsoFieldViewer was changed --- .../ColorMaps/Factories/ColorMapFactory.cs | 45 +++++- .../Entities/ColorMaps/IValueColorRange.cs | 28 +++- .../Entities/ColorMaps/ValueColorRange.cs | 14 +- FieldVisualizer/FieldVisualizer.csproj | 8 + .../InfraStructures/Enums/ColorMapsTypes.cs | 14 -- .../Services/ColorServices/ColorOperations.cs | 146 +++++++++++++----- .../FieldViewerViewModel.cs | 17 +- .../Windows/UserControls/FieldViewer.xaml.cs | 29 +--- StructureHelper.sln | 3 + .../Libraries/LoaderCalculator.dll | Bin 84992 -> 86016 bytes .../Models/Materials/ConcreteLogicOptions.cs | 1 + .../Materials/ConcreteMaterialOptionLogic.cs | 1 + .../Models/Materials/ConcreteLibMaterial.cs | 31 +++- .../Models/Materials/IConcreteLibMaterial.cs | 5 + .../GetColorByValueTest.cs | 2 - .../WindowTests/ViewerTest.cs | 9 +- 16 files changed, 224 insertions(+), 129 deletions(-) delete mode 100644 FieldVisualizer/InfraStructures/Enums/ColorMapsTypes.cs diff --git a/FieldVisualizer/Entities/ColorMaps/Factories/ColorMapFactory.cs b/FieldVisualizer/Entities/ColorMaps/Factories/ColorMapFactory.cs index b5c0010..e259a79 100644 --- a/FieldVisualizer/Entities/ColorMaps/Factories/ColorMapFactory.cs +++ b/FieldVisualizer/Entities/ColorMaps/Factories/ColorMapFactory.cs @@ -1,12 +1,18 @@ -using FieldVisualizer.InfraStructures.Enums; -using FieldVisualizer.InfraStructures.Exceptions; +using FieldVisualizer.InfraStructures.Exceptions; using FieldVisualizer.InfraStructures.Strings; -using System; using System.Collections.Generic; using System.Windows.Media; namespace FieldVisualizer.Entities.ColorMaps.Factories { + public enum ColorMapsTypes + { + LiraSpectrum = 0, //Lira + FullSpectrum = 1, //StaDiCon + RedToWhite = 2, + RedToBlue = 3, + BlueToWhite = 4, + } /// /// Factory for creating of different color maps /// @@ -18,13 +24,39 @@ namespace FieldVisualizer.Entities.ColorMaps.Factories if (mapsTypes == ColorMapsTypes.RedToWhite) { return GetRedToWhite(); } if (mapsTypes == ColorMapsTypes.RedToBlue) { return GetRedToBlue(); } if (mapsTypes == ColorMapsTypes.BlueToWhite) { return GetBlueToWhite(); } + if (mapsTypes == ColorMapsTypes.LiraSpectrum) { return GetLiraSpectrum(); } else { throw new FieldVisulizerException(ErrorStrings.ColorMapTypeIsUnknown); } } + private static IColorMap GetLiraSpectrum() + { + ColorMap colorMap = new() + { + Name = "LiraSpectrumColorMap" + }; + List colors = new(); + byte Alpha = 0xff; + colors.AddRange(new Color[]{ + Color.FromArgb(Alpha, 0, 0, 128) ,//Dark Blue + Color.FromArgb(Alpha, 0, 0, 255) ,//Blue + Color.FromArgb(Alpha, 0, 128, 255) ,//Blue + Color.FromArgb(Alpha, 0, 200, 255) ,//Blue + Color.FromArgb(Alpha, 60, 255, 255) ,//Light Blue + Color.FromArgb(Alpha, 255, 255, 128) ,//Light Yellow + Color.FromArgb(Alpha, 255, 255, 0) ,//Yellow + Color.FromArgb(Alpha, 255, 215, 0) ,//Gold + Color.FromArgb(Alpha, 255, 128, 0) ,//Orange Red + Color.FromArgb(Alpha, 255, 0, 0) ,//Red + }); + colorMap.Colors = colors; + return colorMap; + } private static IColorMap GetFullSpectrum() { - ColorMap colorMap = new ColorMap(); - colorMap.Name = "FullSpectrumColorMap"; + ColorMap colorMap = new() + { + Name = "FullSpectrumColorMap" + }; List colors = new List(); byte Alpha = 0xff; colors.AddRange(new Color[]{ @@ -43,7 +75,6 @@ namespace FieldVisualizer.Entities.ColorMaps.Factories colorMap.Colors = colors; return colorMap; } - private static IColorMap GetRedToWhite() { ColorMap colorMap = new ColorMap(); @@ -57,7 +88,6 @@ namespace FieldVisualizer.Entities.ColorMaps.Factories colorMap.Colors = colors; return colorMap; } - private static IColorMap GetRedToBlue() { ColorMap colorMap = new ColorMap(); @@ -71,7 +101,6 @@ namespace FieldVisualizer.Entities.ColorMaps.Factories colorMap.Colors = colors; return colorMap; } - private static IColorMap GetBlueToWhite() { ColorMap colorMap = new ColorMap(); diff --git a/FieldVisualizer/Entities/ColorMaps/IValueColorRange.cs b/FieldVisualizer/Entities/ColorMaps/IValueColorRange.cs index d4da2bc..395993c 100644 --- a/FieldVisualizer/Entities/ColorMaps/IValueColorRange.cs +++ b/FieldVisualizer/Entities/ColorMaps/IValueColorRange.cs @@ -1,19 +1,35 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Media; +using System.Windows.Media; namespace FieldVisualizer.Entities.ColorMaps { + /// + /// Colored range for building color legend + /// public interface IValueColorRange { + /// + /// Flag of activity + /// bool IsActive { get; set; } + /// + /// Minimum value of range + /// double BottomValue { get; set; } + /// + /// Average value of range + /// double AverageValue { get; set; } + /// + /// Maximum value of range + /// double TopValue {get;set;} + /// + /// Color correspondent to minimum value + /// Color BottomColor { get; set; } + /// + /// Color correspondent to maximum value + /// Color TopColor { get; set; } } } diff --git a/FieldVisualizer/Entities/ColorMaps/ValueColorRange.cs b/FieldVisualizer/Entities/ColorMaps/ValueColorRange.cs index 92eaff5..695cca3 100644 --- a/FieldVisualizer/Entities/ColorMaps/ValueColorRange.cs +++ b/FieldVisualizer/Entities/ColorMaps/ValueColorRange.cs @@ -1,19 +1,21 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Media; +using System.Windows.Media; namespace FieldVisualizer.Entities.ColorMaps { + /// public class ValueColorRange : IValueColorRange { + /// public bool IsActive { get; set; } + /// public double BottomValue { get; set; } + /// public double AverageValue { get; set; } + /// public double TopValue { get; set; } + /// public Color BottomColor { get; set; } + /// public Color TopColor { get; set; } } } diff --git a/FieldVisualizer/FieldVisualizer.csproj b/FieldVisualizer/FieldVisualizer.csproj index 0a3b622..dc9183b 100644 --- a/FieldVisualizer/FieldVisualizer.csproj +++ b/FieldVisualizer/FieldVisualizer.csproj @@ -8,4 +8,12 @@ 7.0 + + + + + + + + diff --git a/FieldVisualizer/InfraStructures/Enums/ColorMapsTypes.cs b/FieldVisualizer/InfraStructures/Enums/ColorMapsTypes.cs deleted file mode 100644 index 5be9d8c..0000000 --- a/FieldVisualizer/InfraStructures/Enums/ColorMapsTypes.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace FieldVisualizer.InfraStructures.Enums -{ - public enum ColorMapsTypes - { - FullSpectrum = 0, - RedToWhite = 1, - RedToBlue = 2, - BlueToWhite = 3 - } -} diff --git a/FieldVisualizer/Services/ColorServices/ColorOperations.cs b/FieldVisualizer/Services/ColorServices/ColorOperations.cs index dd4c7c7..9b3148d 100644 --- a/FieldVisualizer/Services/ColorServices/ColorOperations.cs +++ b/FieldVisualizer/Services/ColorServices/ColorOperations.cs @@ -1,5 +1,6 @@ using FieldVisualizer.Entities.ColorMaps; using FieldVisualizer.Entities.Values; +using StructureHelperCommon.Infrastructures.Exceptions; using System; using System.Collections.Generic; using System.Text; @@ -10,54 +11,123 @@ namespace FieldVisualizer.Services.ColorServices public static class ColorOperations { const byte Alpha = 0xff; - public static Color GetColorByValue(IValueRange range, IColorMap map, double val) - { - if (range.TopValue == range.BottomValue || map.Colors.Count == 0) { return map.Colors[0]; } - double minVal = range.BottomValue - 1e-15d*(Math.Abs(range.BottomValue)); - double maxVal = range.TopValue + 1e-15d * (Math.Abs(range.TopValue)); - if (val > maxVal || val < minVal) { return Colors.Gray; } - if (val == minVal) { return map.Colors[0]; } - if (val == maxVal) { return map.Colors[map.Colors.Count - 1]; } - - double valPerc = (val - minVal) / (maxVal - minVal);// value% - if (valPerc >= 1d) - { return map.Colors[map.Colors.Count - 1]; } - double colorPerc = 1d / (map.Colors.Count - 1d); // % of each block of color. the last is the "100% Color" - double blockOfColor = valPerc / colorPerc;// the integer part repersents how many block to skip - int blockIdx = (int)Math.Truncate(blockOfColor);// Idx of - double valPercResidual = valPerc - (blockIdx * colorPerc);//remove the part represented of block - double percOfColor = valPercResidual / colorPerc;// % of color of this block that will be filled - - Color cTarget = map.Colors[blockIdx]; - Color cNext = map.Colors[blockIdx + 1]; - - var deltaR = cNext.R - cTarget.R; - var deltaG = cNext.G - cTarget.G; - var deltaB = cNext.B - cTarget.B; - - var R = cTarget.R + (deltaR * percOfColor); - var G = cTarget.G + (deltaG * percOfColor); - var B = cTarget.B + (deltaB * percOfColor); - - Color c = map.Colors[0]; - c = Color.FromArgb(Alpha, (byte)R, (byte)G, (byte)B); - return c; - } + /// + /// + /// + /// + /// + /// + /// public static IEnumerable GetValueColorRanges(IValueRange fullRange, IEnumerable valueRanges, IColorMap colorMap) { var colorRanges = new List(); foreach (var valueRange in valueRanges) { - IValueColorRange valueColorRange = new ValueColorRange(); - valueColorRange.IsActive = true; - valueColorRange.BottomValue = valueRange.BottomValue; - valueColorRange.AverageValue = (valueRange.BottomValue + valueRange.TopValue) / 2; - valueColorRange.TopValue = valueRange.TopValue; + IValueColorRange valueColorRange = new ValueColorRange + { + IsActive = true, + BottomValue = valueRange.BottomValue, + AverageValue = (valueRange.BottomValue + valueRange.TopValue) / 2, + TopValue = valueRange.TopValue + }; valueColorRange.BottomColor = GetColorByValue(fullRange, colorMap, valueColorRange.BottomValue); valueColorRange.TopColor = GetColorByValue(fullRange, colorMap, valueColorRange.TopValue); colorRanges.Add(valueColorRange); } return colorRanges; } + /// + /// Returns color by value, range of value an color map + /// + /// Range of valoue + /// Color map + /// Value + /// + public static Color GetColorByValue(IValueRange range, IColorMap map, double val) + { + CheckColorMap(map); + if (range.TopValue == range.BottomValue || map.Colors.Count == 1) //if range width is zero or map contain just 1 color + { + return map.Colors[0]; + } + var valueRange = GetExtendedRange(range); + if (val >= valueRange.TopValue || val <= valueRange.BottomValue) + { + return GetColorValueIsOutOfRange(valueRange, map, val); + } + return GetColorValueIsInRange(valueRange, map, val); + } + + private static Color GetColorValueIsOutOfRange(IValueRange range, IColorMap map, double val) + { + if (val > range.TopValue || val < range.BottomValue) + { + return Colors.Gray; + } + if (val == range.BottomValue) + { + return map.Colors[0]; + } + if (val == range.TopValue) + { + return map.Colors[^1]; + } + throw new StructureHelperException(ErrorStrings.DataIsInCorrect); + } + + private static Color GetColorValueIsInRange(IValueRange range, IColorMap map, double val) + { + var deltaVal = val - range.BottomValue; + var rangeWidth = range.TopValue - range.BottomValue; + var valPerc = deltaVal / rangeWidth; // percent of value on the distance from minValue to maxValue + if (valPerc >= 1d) + { + return map.Colors[^1]; + } + double colorPerc = 1d / (map.Colors.Count - 1d); // % of each block of color. the last is the "100% Color" + double blockOfColor = valPerc / colorPerc;// the integer part repersents how many block to skip + int blockIdx = (int)Math.Truncate(blockOfColor);// Idx of + double valPercResidual = valPerc - (blockIdx * colorPerc);//remove the part represented of block + double percOfColor = valPercResidual / colorPerc;// % of color of this block that will be filled + + Color c = GetColorByColorMap(map, blockIdx, percOfColor); + return c; + } + + private static IValueRange GetExtendedRange(IValueRange range) + { + var minVal = range.BottomValue - 1e-15d * Math.Abs(range.BottomValue); + var maxVal = range.TopValue + 1e-15d * Math.Abs(range.TopValue); + return new ValueRange() + { + BottomValue = minVal, + TopValue = maxVal + }; + } + + private static Color GetColorByColorMap(IColorMap map, int blockIdx, double percOfColor) + { + Color cTarget = map.Colors[blockIdx]; + Color cNext = map.Colors[blockIdx + 1]; + + var deltaRed = cNext.R - cTarget.R; + var deltaGreen = cNext.G - cTarget.G; + var deltaBlue = cNext.B - cTarget.B; + + var Red = cTarget.R + (deltaRed * percOfColor); + var Green = cTarget.G + (deltaGreen * percOfColor); + var Blue = cTarget.B + (deltaBlue * percOfColor); + + Color c = Color.FromArgb(Alpha, (byte)Red, (byte)Green, (byte)Blue); + return c; + } + + private static void CheckColorMap(IColorMap map) + { + if (map.Colors.Count == 0) + { + throw new StructureHelperException(ErrorStrings.DataIsInCorrect + ": Color map is empty"); + } + } } } diff --git a/FieldVisualizer/ViewModels/FieldViewerViewModels/FieldViewerViewModel.cs b/FieldVisualizer/ViewModels/FieldViewerViewModels/FieldViewerViewModel.cs index 4f16ce6..540abf1 100644 --- a/FieldVisualizer/ViewModels/FieldViewerViewModels/FieldViewerViewModel.cs +++ b/FieldVisualizer/ViewModels/FieldViewerViewModels/FieldViewerViewModel.cs @@ -1,27 +1,22 @@ -using FieldVisualizer.Entities.ColorMaps.Factories; -using FieldVisualizer.Entities.ColorMaps; -using FieldVisualizer.Entities.Values.Primitives; +using FieldVisualizer.Entities.ColorMaps; +using FieldVisualizer.Entities.ColorMaps.Factories; using FieldVisualizer.Entities.Values; +using FieldVisualizer.Entities.Values.Primitives; using FieldVisualizer.Infrastructure.Commands; -using FieldVisualizer.InfraStructures.Enums; using FieldVisualizer.InfraStructures.Exceptions; using FieldVisualizer.InfraStructures.Strings; using FieldVisualizer.Services.ColorServices; using FieldVisualizer.Services.PrimitiveServices; using FieldVisualizer.Services.ValueRanges; +using FieldVisualizer.Windows.UserControls; using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; -using FieldVisualizer.Windows.UserControls; -using System.ComponentModel; -using System.Xml.Serialization; namespace FieldVisualizer.ViewModels.FieldViewerViewModels { @@ -177,7 +172,7 @@ namespace FieldVisualizer.ViewModels.FieldViewerViewModels public FieldViewerViewModel() { - _ColorMapType = ColorMapsTypes.FullSpectrum; + _ColorMapType = ColorMapsTypes.LiraSpectrum; RebuildCommand = new RelayCommand(o => ProcessPrimitives(), o => PrimitiveValidation()); ZoomInCommand = new RelayCommand(o => Zoom(1.2), o => PrimitiveValidation()); ZoomOutCommand = new RelayCommand(o => Zoom(0.8), o => PrimitiveValidation()); diff --git a/FieldVisualizer/Windows/UserControls/FieldViewer.xaml.cs b/FieldVisualizer/Windows/UserControls/FieldViewer.xaml.cs index 1166be2..96e6753 100644 --- a/FieldVisualizer/Windows/UserControls/FieldViewer.xaml.cs +++ b/FieldVisualizer/Windows/UserControls/FieldViewer.xaml.cs @@ -1,23 +1,7 @@ -using FieldVisualizer.Entities.ColorMaps; -using FieldVisualizer.Entities.ColorMaps.Factories; -using FieldVisualizer.Entities.Values; -using FieldVisualizer.Entities.Values.Primitives; -using FieldVisualizer.Infrastructure.Commands; -using FieldVisualizer.InfraStructures.Enums; -using FieldVisualizer.InfraStructures.Exceptions; -using FieldVisualizer.InfraStructures.Strings; -using FieldVisualizer.Services.ColorServices; -using FieldVisualizer.Services.PrimitiveServices; -using FieldVisualizer.Services.ValueRanges; +using FieldVisualizer.Entities.Values.Primitives; using FieldVisualizer.ViewModels.FieldViewerViewModels; -using System; -using System.Collections.Generic; -using System.Linq; using System.Windows; using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Shapes; namespace FieldVisualizer.Windows.UserControls { @@ -39,17 +23,6 @@ namespace FieldVisualizer.Windows.UserControls viewModel.Legend = LegendViewer; } - //public FieldViewer(FieldViewerViewModel vm) - //{ - // InitializeComponent(); - // viewModel = vm; - // this.DataContext = viewModel; - // PrimitiveSet = viewModel.PrimitiveSet; - // viewModel.WorkPlaneBox = WorkPlaneBox; - // viewModel.WorkPlaneCanvas = WorkPlaneCanvas; - // viewModel.Legend = LegendViewer; - //} - public IPrimitiveSet PrimitiveSet { get => viewModel.PrimitiveSet; set { viewModel.PrimitiveSet = value; } } internal void Refresh() diff --git a/StructureHelper.sln b/StructureHelper.sln index 10d38cf..7bf9930 100644 --- a/StructureHelper.sln +++ b/StructureHelper.sln @@ -14,6 +14,9 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StructureHelperLogics", "StructureHelperLogics\StructureHelperLogics.csproj", "{C9192AE7-EE6D-409C-A05C-3549D78CBB34}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FieldVisualizer", "FieldVisualizer\FieldVisualizer.csproj", "{6CAC5B83-81F3-47C2-92A1-0F94A58491C2}" + ProjectSection(ProjectDependencies) = postProject + {F1548BD2-7FE8-46C2-9BC4-9BA813A5C59A} = {F1548BD2-7FE8-46C2-9BC4-9BA813A5C59A} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/StructureHelper/Libraries/LoaderCalculator.dll b/StructureHelper/Libraries/LoaderCalculator.dll index f2db256b381741f2e45667f6f13b7f1511ef5d78..7a3289fa0f054162f36e6b065bb2fb231ec10756 100644 GIT binary patch delta 36135 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 Y93o%Zj(@`YUk-I~;r7^}@(20<0T;m9zW@LL diff --git a/StructureHelperCommon/Models/Materials/ConcreteLogicOptions.cs b/StructureHelperCommon/Models/Materials/ConcreteLogicOptions.cs index cb9af68..cae9321 100644 --- a/StructureHelperCommon/Models/Materials/ConcreteLogicOptions.cs +++ b/StructureHelperCommon/Models/Materials/ConcreteLogicOptions.cs @@ -13,6 +13,7 @@ namespace StructureHelperCommon.Models.Materials public List SafetyFactors { get; set; } public LimitStates LimitState { get; set; } public CalcTerms CalcTerm { get; set; } + public double Age { get; set; } public ILibMaterialEntity MaterialEntity { get; set; } public bool WorkInCompression { get; set; } public bool WorkInTension { get; set; } diff --git a/StructureHelperCommon/Models/Materials/ConcreteMaterialOptionLogic.cs b/StructureHelperCommon/Models/Materials/ConcreteMaterialOptionLogic.cs index c8e0b67..69016d0 100644 --- a/StructureHelperCommon/Models/Materials/ConcreteMaterialOptionLogic.cs +++ b/StructureHelperCommon/Models/Materials/ConcreteMaterialOptionLogic.cs @@ -38,6 +38,7 @@ namespace StructureHelperCommon.Models.Materials concreteOptions.ExternalFactor.Tensile = strength.Tensile; concreteOptions.WorkInTension = options.WorkInTension; concreteOptions.RelativeHumidity = options.RelativeHumidity; + concreteOptions.Age = options.Age; } } } diff --git a/StructureHelperLogics/Models/Materials/ConcreteLibMaterial.cs b/StructureHelperLogics/Models/Materials/ConcreteLibMaterial.cs index 352e9c6..c10926e 100644 --- a/StructureHelperLogics/Models/Materials/ConcreteLibMaterial.cs +++ b/StructureHelperLogics/Models/Materials/ConcreteLibMaterial.cs @@ -1,17 +1,17 @@ -using StructureHelperCommon.Infrastructures.Enums; +using LoaderCalculator.Data.Materials; +using StructureHelperCommon.Infrastructures.Enums; +using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Infrastructures.Settings; +using StructureHelperCommon.Models.Materials; using StructureHelperCommon.Models.Materials.Libraries; using LMBuilders = LoaderCalculator.Data.Materials.MaterialBuilders; using LMLogic = LoaderCalculator.Data.Materials.MaterialBuilders.MaterialLogics; -using LM = LoaderCalculator.Data.Materials; -using LoaderCalculator.Data.Materials; -using StructureHelperCommon.Infrastructures.Exceptions; -using StructureHelperCommon.Models.Materials; namespace StructureHelperLogics.Models.Materials { public class ConcreteLibMaterial : IConcreteLibMaterial { + const double maxAge = 70d * 365 * 24 * 60 * 60; const MaterialTypes materialType = MaterialTypes.Concrete; private readonly List materialLogics; private LMBuilders.ConcreteOptions lmOptions; @@ -26,14 +26,18 @@ namespace StructureHelperLogics.Models.Materials public bool TensionForULS { get ; set; } /// public bool TensionForSLS { get; set; } - /// - /// Humidity of concrete - /// + /// public double RelativeHumidity { get; set; } /// public IMaterialLogic MaterialLogic { get; set; } /// + public double MinAge { get; set; } + /// + public double MaxAge { get; set; } + /// public List MaterialLogics => materialLogics; + + public ConcreteLibMaterial() { materialLogics = ProgramSetting.MaterialLogics.Where(x => x.MaterialType == materialType).ToList(); @@ -44,6 +48,8 @@ namespace StructureHelperLogics.Models.Materials TensionForULS = false; TensionForSLS = true; RelativeHumidity = 0.55d; + MinAge = 0d; + MaxAge = maxAge; } public object Clone() @@ -107,6 +113,7 @@ namespace StructureHelperLogics.Models.Materials { options.WorkInTension = false; } + options.Age = MinAge; } else if (limitState == LimitStates.SLS) { @@ -118,6 +125,14 @@ namespace StructureHelperLogics.Models.Materials { options.WorkInTension = false; } + if (calcTerm == CalcTerms.LongTerm) + { + options.Age = MaxAge; + } + else + { + options.Age = MinAge; + } } else { diff --git a/StructureHelperLogics/Models/Materials/IConcreteLibMaterial.cs b/StructureHelperLogics/Models/Materials/IConcreteLibMaterial.cs index 21a35c8..ee1fd73 100644 --- a/StructureHelperLogics/Models/Materials/IConcreteLibMaterial.cs +++ b/StructureHelperLogics/Models/Materials/IConcreteLibMaterial.cs @@ -11,6 +11,11 @@ namespace StructureHelperLogics.Models.Materials { bool TensionForULS { get; set; } bool TensionForSLS { get; set; } + /// + /// Humidity of concrete + /// double RelativeHumidity { get; set; } + double MinAge { get; set; } + double MaxAge { get; set; } } } diff --git a/StructureHelperTests/FieldsVisualizerTests/ColorOperationTests/GetColorByValueTest.cs b/StructureHelperTests/FieldsVisualizerTests/ColorOperationTests/GetColorByValueTest.cs index fa883b0..a3e5ef9 100644 --- a/StructureHelperTests/FieldsVisualizerTests/ColorOperationTests/GetColorByValueTest.cs +++ b/StructureHelperTests/FieldsVisualizerTests/ColorOperationTests/GetColorByValueTest.cs @@ -1,10 +1,8 @@ using FieldVisualizer.Entities.ColorMaps; using FieldVisualizer.Entities.ColorMaps.Factories; using FieldVisualizer.Entities.Values; -using FieldVisualizer.InfraStructures.Enums; using FieldVisualizer.Services.ColorServices; using NUnit.Framework; -using System.Windows.Media; namespace StructureHelperTests.FieldsVisualizerTests.ColorOperationTests { diff --git a/StructureHelperTests/FieldsVisualizerTests/WindowTests/ViewerTest.cs b/StructureHelperTests/FieldsVisualizerTests/WindowTests/ViewerTest.cs index 460ddb9..79002d6 100644 --- a/StructureHelperTests/FieldsVisualizerTests/WindowTests/ViewerTest.cs +++ b/StructureHelperTests/FieldsVisualizerTests/WindowTests/ViewerTest.cs @@ -1,14 +1,7 @@ -using FieldVisualizer.Entities.ColorMaps; -using FieldVisualizer.Entities.ColorMaps.Factories; -using FieldVisualizer.Entities.Values; -using FieldVisualizer.Entities.Values.Primitives; -using FieldVisualizer.InfraStructures.Enums; -using FieldVisualizer.Services.ColorServices; +using FieldVisualizer.Entities.Values.Primitives; using FieldVisualizer.Services.PrimitiveServices; using FieldVisualizer.Windows; using NUnit.Framework; -using System.Collections.Generic; -using System.Windows.Media; namespace StructureHelperTests.FieldsVisualizerTests.WindowTests {