diff --git a/DataAccess/DTOs/DTOEntities/NdmCrossSections/CrossSectionRepositoryDTO.cs b/DataAccess/DTOs/DTOEntities/NdmCrossSections/CrossSectionRepositoryDTO.cs index 1b92eef..b9364b6 100644 --- a/DataAccess/DTOs/DTOEntities/NdmCrossSections/CrossSectionRepositoryDTO.cs +++ b/DataAccess/DTOs/DTOEntities/NdmCrossSections/CrossSectionRepositoryDTO.cs @@ -4,26 +4,24 @@ using StructureHelperCommon.Models.Calculators; using StructureHelperCommon.Models.Forces; using StructureHelperLogics.Models.CrossSections; using StructureHelperLogics.NdmCalculations.Primitives; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace DataAccess.DTOs { public class CrossSectionRepositoryDTO : ICrossSectionRepository { + private IRepositoryOperationsLogic operations; + [JsonProperty("Id")] public Guid Id { get; set; } [JsonProperty("HeadMaterials")] - public List HeadMaterials { get; } = new(); + public List HeadMaterials { get; } = []; [JsonProperty("ForceActions")] - public List ForceActions { get; } = new(); + public List ForceActions { get; } = []; [JsonProperty("Primitives")] - public List Primitives { get; } = new(); + public List Primitives { get; } = []; [JsonProperty("Calculators")] - public List Calculators { get; } = new(); - + public List Calculators { get; } = []; + [JsonIgnore] + public IRepositoryOperationsLogic Operations => operations ??= new RepositoryOperationsLogic(this); } } diff --git a/FieldVisualizer/Entities/Values/IValueLabel.cs b/FieldVisualizer/Entities/Values/IValueLabel.cs new file mode 100644 index 0000000..33cdeb9 --- /dev/null +++ b/FieldVisualizer/Entities/Values/IValueLabel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FieldVisualizer.Entities.Values +{ + public interface IValueLabel + { + bool IsActive { get; set; } + string Value { get; set; } + double X { get; set; } + double Y { get; set; } + } +} diff --git a/FieldVisualizer/Entities/Values/Primitives/AddPrimitivesToCanvasLogic.cs b/FieldVisualizer/Entities/Values/Primitives/AddPrimitivesToCanvasLogic.cs new file mode 100644 index 0000000..c212ff9 --- /dev/null +++ b/FieldVisualizer/Entities/Values/Primitives/AddPrimitivesToCanvasLogic.cs @@ -0,0 +1,184 @@ +using FieldVisualizer.Entities.ColorMaps; +using FieldVisualizer.InfraStructures.Exceptions; +using FieldVisualizer.InfraStructures.Strings; +using FieldVisualizer.Services.ColorServices; +using FieldVisualizer.Windows.UserControls; +using StructureHelperCommon.Services; +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Shapes; + +namespace FieldVisualizer.Entities.Values.Primitives +{ + internal class AddPrimitivesToCanvasLogic + { + private const int zoomFactor = 1000; + private IMathRoundLogic roundLogic = new SmartRoundLogic() { DigitQuant = 3 }; + public Canvas WorkPlaneCanvas { get; set; } + public IValueRange ValueRange { get; set; } + public IColorMap ColorMap { get; set; } + public IEnumerable ValueColorRanges { get; set; } + public double DX { get; set; } + public double DY { get; set; } + + public void ProcessPrimitives(IEnumerable valuePrimitives) + { + foreach (var primitive in valuePrimitives) + { + if (primitive is IRectanglePrimitive rectanglePrimitive) + { + Rectangle rectangle = ProcessRectanglePrimitive(rectanglePrimitive); + WorkPlaneCanvas.Children.Add(rectangle); + } + else if (primitive is ICirclePrimitive circlePrimitive) + { + Ellipse ellipse = ProcessCirclePrimitive(circlePrimitive); + WorkPlaneCanvas.Children.Add(ellipse); + } + else if (primitive is ITrianglePrimitive triangle) + { + Path path = ProcessTrianglePrimitive(triangle); + WorkPlaneCanvas.Children.Add(path); + } + else { throw new FieldVisulizerException(ErrorStrings.PrimitiveTypeIsUnknown); } + } + } + + private Path ProcessTrianglePrimitive(ITrianglePrimitive triangle) + { + // Create the PathFigure using triangle vertices. + var figure = new PathFigure + { + StartPoint = new Point(triangle.Point1.X * zoomFactor, -triangle.Point1.Y * zoomFactor), + IsClosed = true, + IsFilled = true + }; + + // Add the remaining vertices as LineSegments + var segments = new PathSegmentCollection + { + new LineSegment(new Point(triangle.Point2.X * zoomFactor, - triangle.Point2.Y * zoomFactor), true), + new LineSegment(new Point(triangle.Point3.X * zoomFactor, - triangle.Point3.Y * zoomFactor), true) + // Closing is handled by IsClosed = true, so we don't need to add a segment back to Point1 + }; + figure.Segments = segments; + + // Create geometry and path + var geometry = new PathGeometry(); + geometry.Figures.Add(figure); + + var path = new Path + { + Data = geometry, + }; + ProcessShape(path, triangle, 0, 0, false); + path.MouseLeftButtonDown += OnPathClicked; + return path; + } + private Rectangle ProcessRectanglePrimitive(IRectanglePrimitive rectanglePrimitive) + { + Rectangle rectangle = new Rectangle + { + Height = rectanglePrimitive.Height * zoomFactor, + Width = rectanglePrimitive.Width * zoomFactor + }; + double addX = rectanglePrimitive.Width / 2 * zoomFactor; + double addY = rectanglePrimitive.Height / 2 * zoomFactor; + ProcessShape(rectangle, rectanglePrimitive, addX, addY, true); + rectangle.MouseLeftButtonDown += OnRectangleClicked; + return rectangle; + } + private Ellipse ProcessCirclePrimitive(ICirclePrimitive circlePrimitive) + { + Ellipse ellipse = new Ellipse + { + Height = circlePrimitive.Diameter * zoomFactor, + Width = circlePrimitive.Diameter * zoomFactor + }; + double addX = circlePrimitive.Diameter / 2 * zoomFactor; + double addY = circlePrimitive.Diameter / 2 * zoomFactor; + + ProcessShape(ellipse, circlePrimitive, addX, addY, true); + ellipse.MouseLeftButtonDown += OnEllipseClicked; + return ellipse; + } + private void ProcessShape(Shape shape, IValuePrimitive valuePrimitive, double addX, double addY, bool addCenter) + { + SolidColorBrush brush = new SolidColorBrush(); + brush.Color = ColorOperations.GetColorByValue(ValueRange, ColorMap, valuePrimitive.Value); + foreach (var valueRange in ValueColorRanges) + { + if (valuePrimitive.Value >= valueRange.ExactValues.BottomValue & valuePrimitive.Value <= valueRange.ExactValues.TopValue & (!valueRange.IsActive)) + { + brush.Color = Colors.Gray; + } + } + shape.ToolTip = roundLogic.RoundValue(valuePrimitive.Value); + shape.Tag = valuePrimitive; + shape.Fill = brush; + shape.StrokeThickness = 0.0; + double addLeft = -addX - DX * zoomFactor; + double addTop = -addY + DY * zoomFactor; + if (addCenter == true) + { + addLeft += valuePrimitive.CenterX * zoomFactor; + addTop -= valuePrimitive.CenterY * zoomFactor; + } + Canvas.SetLeft(shape, addLeft); + Canvas.SetTop(shape, addTop); + } + + private void OnRectangleClicked(object sender, MouseButtonEventArgs e) + { + if (sender is not Rectangle rectangle) + return; + + if (rectangle.Tag is not IRectanglePrimitive primitive) + return; + AddLabel(primitive); + e.Handled = true; + } + + private void OnEllipseClicked(object sender, MouseButtonEventArgs e) + { + if (sender is not Ellipse ellipse) + return; + + if (ellipse.Tag is not ICirclePrimitive primitive) + return; + AddLabel(primitive); + e.Handled = true; + } + + private void AddLabel(IValuePrimitive primitive) + { + var value = roundLogic.RoundValue(primitive.Value); + + var label = new ValueLabelControl() + { + Value = Convert.ToString(value), + Scale = WorkPlaneCanvas.Height / 600, + X = (primitive.CenterX - DX) * zoomFactor, + Y = (- primitive.CenterY + DY) * zoomFactor, + }; + + WorkPlaneCanvas.Children.Add(label); + } + + private void OnPathClicked(object sender, MouseButtonEventArgs e) + { + if (sender is not Path path) + return; + + if (path.Tag is not ITrianglePrimitive primitive) + return; + + AddLabel(primitive); + e.Handled = true; + } + } +} diff --git a/FieldVisualizer/Entities/Values/Primitives/IPrimitiveSet.cs b/FieldVisualizer/Entities/Values/Primitives/IPrimitiveSet.cs index 8cefb5f..97d6e04 100644 --- a/FieldVisualizer/Entities/Values/Primitives/IPrimitiveSet.cs +++ b/FieldVisualizer/Entities/Values/Primitives/IPrimitiveSet.cs @@ -1,14 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; namespace FieldVisualizer.Entities.Values.Primitives { public interface IPrimitiveSet { - string Name { get; } + string Name { get; set; } + string SubTitle { get; set; } IEnumerable ValuePrimitives { get; } } diff --git a/FieldVisualizer/Entities/Values/Primitives/PrimitiveSet.cs b/FieldVisualizer/Entities/Values/Primitives/PrimitiveSet.cs index 732a515..08df8fa 100644 --- a/FieldVisualizer/Entities/Values/Primitives/PrimitiveSet.cs +++ b/FieldVisualizer/Entities/Values/Primitives/PrimitiveSet.cs @@ -8,12 +8,13 @@ namespace FieldVisualizer.Entities.Values.Primitives { public class PrimitiveSet : IPrimitiveSet { - public string Name { get; set; } + public string Name { get; set; } = string.Empty; + public string SubTitle { get; set; } = string.Empty; public IEnumerable ValuePrimitives { get; set;} public PrimitiveSet() { - Name = "New set of primitives"; + ValuePrimitives = new List(); } } diff --git a/FieldVisualizer/Entities/Values/Primitives/TrianglePrimitive.cs b/FieldVisualizer/Entities/Values/Primitives/TrianglePrimitive.cs index a59baa3..115adfb 100644 --- a/FieldVisualizer/Entities/Values/Primitives/TrianglePrimitive.cs +++ b/FieldVisualizer/Entities/Values/Primitives/TrianglePrimitive.cs @@ -14,8 +14,8 @@ namespace FieldVisualizer.Entities.Values.Primitives // --- Computed properties --- // Centroid (geometric center) - public double CenterX => (Point1.X + Point2.X + Point3.X) / 3.0; - public double CenterY => (Point1.Y + Point2.Y + Point3.Y) / 3.0; + public double CenterX => (Point1.X + Point2.X + Point3.X) / 3d; + public double CenterY => (Point1.Y + Point2.Y + Point3.Y) / 3d; // Triangle area using determinant formula public double Area => diff --git a/FieldVisualizer/Entities/Values/ValueLabel.cs b/FieldVisualizer/Entities/Values/ValueLabel.cs new file mode 100644 index 0000000..14f639e --- /dev/null +++ b/FieldVisualizer/Entities/Values/ValueLabel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FieldVisualizer.Entities.Values +{ + public class ValueLabel : IValueLabel + { + public bool IsActive { get; set; } = true; + public string Value { get; set; } = string.Empty; + public double X { get; set; } + public double Y { get; set; } + } +} diff --git a/FieldVisualizer/FieldVisualizer.csproj.user b/FieldVisualizer/FieldVisualizer.csproj.user index 88a5509..8aba6bd 100644 --- a/FieldVisualizer/FieldVisualizer.csproj.user +++ b/FieldVisualizer/FieldVisualizer.csproj.user @@ -1,4 +1,9 @@  + + + Code + + \ No newline at end of file diff --git a/FieldVisualizer/ViewModels/FieldViewerViewModels/FieldViewerViewModel.cs b/FieldVisualizer/ViewModels/FieldViewerViewModels/FieldViewerViewModel.cs index 5df04a1..c54a8de 100644 --- a/FieldVisualizer/ViewModels/FieldViewerViewModels/FieldViewerViewModel.cs +++ b/FieldVisualizer/ViewModels/FieldViewerViewModels/FieldViewerViewModel.cs @@ -3,20 +3,16 @@ using FieldVisualizer.Entities.ColorMaps.Factories; using FieldVisualizer.Entities.Values; using FieldVisualizer.Entities.Values.Primitives; using FieldVisualizer.Infrastructure.Commands; -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 StructureHelperCommon.Services; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; -using System.Windows; using System.Windows.Controls; -using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; @@ -25,8 +21,26 @@ namespace FieldVisualizer.ViewModels.FieldViewerViewModels { public class FieldViewerViewModel : ViewModelBase, IDataErrorInfo { - private IMathRoundLogic roundLogic = new SmartRoundLogic() { DigitQuant = 3 }; - public ICommand RebuildCommand { get; } + private ICommand setCrossLineCommand; + private IPrimitiveSet primitiveSet; + private double dX, dY; + private ColorMapsTypes _ColorMapType = ColorMapsTypes.LiraSpectrum; + private IColorMap _ColorMap; + private IValueRange valueRange; + private IEnumerable valueRanges; + private IEnumerable valueColorRanges; + private bool setMinValue; + private bool setMaxValue; + private double crossLineX; + private double crossLineY; + private double sumAboveLine; + private double sumUnderLine; + private Line previosLine; + const int RangeNumber = 16; + private const int zoomFactor = 1000; + private RelayCommand rebuildCommand; + + public ICommand RebuildCommand => rebuildCommand ??= new RelayCommand(o => ProcessPrimitives(), o => PrimitiveValidation()); public ICommand ZoomInCommand { get; } public ICommand ZoomOutCommand { get; } public ICommand ChangeColorMapCommand { get; } @@ -148,6 +162,9 @@ namespace FieldVisualizer.ViewModels.FieldViewerViewModels public double SumUnderLine { get => sumUnderLine; set => SetProperty(ref sumUnderLine, value); } public string Error { get; } + public string Title { get; set; } + public string SubTitle { get; set; } + public string this[string columnName] { get @@ -157,27 +174,10 @@ namespace FieldVisualizer.ViewModels.FieldViewerViewModels } } - private ICommand setCrossLineCommand; - private IPrimitiveSet primitiveSet; - private double dX, dY; - private ColorMapsTypes _ColorMapType; - private IColorMap _ColorMap; - private IValueRange valueRange; - private IEnumerable valueRanges; - private IEnumerable valueColorRanges; - private bool setMinValue; - private bool setMaxValue; - private double crossLineX; - private double crossLineY; - private double sumAboveLine; - private double sumUnderLine; - private Line previosLine; - const int RangeNumber = 16; + public FieldViewerViewModel() { - _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()); ChangeColorMapCommand = new RelayCommand(o => ChangeColorMap(), o => PrimitiveValidation()); @@ -207,114 +207,29 @@ namespace FieldVisualizer.ViewModels.FieldViewerViewModels private void ProcessPrimitives() { WorkPlaneCanvas.Children.Clear(); - double sizeX = PrimitiveOperations.GetSizeX(PrimitiveSet.ValuePrimitives); - double sizeY = PrimitiveOperations.GetSizeY(PrimitiveSet.ValuePrimitives); + Title = PrimitiveSet.Name; + OnPropertyChanged(nameof(Title)); + SubTitle = PrimitiveSet.SubTitle; + OnPropertyChanged(nameof(SubTitle)); + double sizeX = PrimitiveOperations.GetSizeX(PrimitiveSet.ValuePrimitives) * zoomFactor; + double sizeY = PrimitiveOperations.GetSizeY(PrimitiveSet.ValuePrimitives) * zoomFactor; dX = PrimitiveOperations.GetMinMaxX(PrimitiveSet.ValuePrimitives)[0]; dY = PrimitiveOperations.GetMinMaxY(PrimitiveSet.ValuePrimitives)[1]; WorkPlaneCanvas.Width = Math.Abs(sizeX); WorkPlaneCanvas.Height = Math.Abs(sizeY); - WorkPlaneBox.Width = ScrolWidth - 50; - WorkPlaneBox.Height = ScrolHeight - 50; - foreach (var primitive in PrimitiveSet.ValuePrimitives) + WorkPlaneBox.Width = (ScrolWidth - 50); + WorkPlaneBox.Height = (ScrolHeight - 50); + var logic = new AddPrimitivesToCanvasLogic() { - if (primitive is IRectanglePrimitive rectanglePrimitive) - { - Rectangle rectangle = ProcessRectanglePrimitive(rectanglePrimitive); - WorkPlaneCanvas.Children.Add(rectangle); - } - else if (primitive is ICirclePrimitive circlePrimitive) - { - Ellipse ellipse = ProcessCirclePrimitive(circlePrimitive); - WorkPlaneCanvas.Children.Add(ellipse); - } - else if (primitive is ITrianglePrimitive triangle) - { - Path path = ProcessTrianglePrimitive(triangle); - WorkPlaneCanvas.Children.Add(path); - } - else { throw new FieldVisulizerException(ErrorStrings.PrimitiveTypeIsUnknown); } - } - } + WorkPlaneCanvas = WorkPlaneCanvas, + DX = dX, + DY = dY, + ValueRange = valueRange, + ColorMap = _ColorMap, + ValueColorRanges = valueColorRanges, + }; + logic.ProcessPrimitives(PrimitiveSet.ValuePrimitives); - private Path ProcessTrianglePrimitive(ITrianglePrimitive triangle) - { - // Create the PathFigure using triangle vertices. - var figure = new PathFigure - { - StartPoint = new Point(triangle.Point1.X, - triangle.Point1.Y), - IsClosed = true, - IsFilled = true - }; - - // Add the remaining vertices as LineSegments - var segments = new PathSegmentCollection - { - new LineSegment(new Point(triangle.Point2.X, - triangle.Point2.Y), true), - new LineSegment(new Point(triangle.Point3.X, - triangle.Point3.Y), true) - // Closing is handled by IsClosed = true, so we don't need to add a segment back to Point1 - }; - figure.Segments = segments; - - // Create geometry and path - var geometry = new PathGeometry(); - geometry.Figures.Add(figure); - - var path = new Path - { - Data = geometry, - }; - ProcessShape(path, triangle, 0, 0, false); - return path; - } - - private Rectangle ProcessRectanglePrimitive(IRectanglePrimitive rectanglePrimitive) - { - Rectangle rectangle = new Rectangle - { - Height = rectanglePrimitive.Height, - Width = rectanglePrimitive.Width - }; - double addX = rectanglePrimitive.Width / 2; - double addY = rectanglePrimitive.Height / 2; - ProcessShape(rectangle, rectanglePrimitive, addX, addY, true); - return rectangle; - } - private Ellipse ProcessCirclePrimitive(ICirclePrimitive circlePrimitive) - { - Ellipse ellipse = new Ellipse - { - Height = circlePrimitive.Diameter, - Width = circlePrimitive.Diameter - }; - double addX = circlePrimitive.Diameter / 2; - double addY = circlePrimitive.Diameter / 2; - - ProcessShape(ellipse, circlePrimitive, addX, addY, true); - return ellipse; - } - private void ProcessShape(Shape shape, IValuePrimitive valuePrimitive, double addX, double addY, bool addCenter) - { - SolidColorBrush brush = new SolidColorBrush(); - brush.Color = ColorOperations.GetColorByValue(valueRange, _ColorMap, valuePrimitive.Value); - foreach (var valueRange in valueColorRanges) - { - if (valuePrimitive.Value >= valueRange.ExactValues.BottomValue & valuePrimitive.Value <= valueRange.ExactValues.TopValue & (!valueRange.IsActive)) - { - brush.Color = Colors.Gray; - } - } - shape.ToolTip = roundLogic.RoundValue(valuePrimitive.Value); - shape.Tag = valuePrimitive; - shape.Fill = brush; - double addLeft = - addX - dX; - double addTop = - addY + dY; - if (addCenter == true) - { - addLeft += valuePrimitive.CenterX; - addTop -= valuePrimitive.CenterY; - } - Canvas.SetLeft(shape, addLeft); - Canvas.SetTop(shape, addTop); } private void Zoom(double coefficient) { diff --git a/FieldVisualizer/Windows/UserControls/FieldViewer.xaml b/FieldVisualizer/Windows/UserControls/FieldViewer.xaml index 0fbb914..960e698 100644 --- a/FieldVisualizer/Windows/UserControls/FieldViewer.xaml +++ b/FieldVisualizer/Windows/UserControls/FieldViewer.xaml @@ -24,19 +24,29 @@