From ba0d3e580b287246745caa11293da8648897628f Mon Sep 17 00:00:00 2001 From: Evgeny Redikultsev Date: Sat, 1 Nov 2025 21:56:47 +0500 Subject: [PATCH] Add import of polygon from dxf --- .../Services/Exports/ExportToFileInputData.cs | 16 ---- .../Services/Exports/ExportToFileService.cs | 33 +++---- .../Services/Exports/IExportService.cs | 14 --- .../Exports/IExportToFileInputData.cs | 16 ---- .../Services/Exports/ImportFromFileService.cs | 77 ++++++++++++++++ .../BeamShears/BeamShearResultViewModel.cs | 9 +- .../Cracks/CrackResultViewModel.cs | 7 +- .../ForcesResultsViewModel.cs | 9 +- .../Graphs/FrameWorkElementServiseLogic.cs | 14 +-- .../Windows/Graphs/GraphViewModel.cs | 8 +- .../Windows/Shapes/PolygonShapeView.xaml | 4 +- .../Windows/Shapes/PolygonShapeViewModel.cs | 40 ++++++--- .../GeometryCalculatorResultViewModel.cs | 8 +- .../Infrastructures/Exceptions/ErrorString.cs | 2 + .../Interfaces/IObjectConvertStrategy.cs | 10 +++ .../Shapes/Logics/ArcFlatteningOption.cs | 24 +++++ .../Shapes/Logics/IArcFlatteningOption.cs | 10 +++ .../Polyline2DToLinePoligonConvertLogic.cs | 89 +++++++++++++++++++ .../Exports/Factories/FileInputDataFactory.cs | 50 +++++++++++ .../Services/Exports/FileIOInputData.cs | 9 ++ .../Services/Exports/GetDxfLayerLogic.cs | 54 +++++++++++ .../Services/Exports/IExportLogic.cs | 7 ++ ...rtResultLogic.cs => IExportToFileLogic.cs} | 3 +- .../Services/Exports/IFileIOnputData.cs | 9 ++ .../Services/Exports/IGetDxfLayerLogic.cs | 12 +++ .../Services/Exports/IImportFromFileLogic.cs | 13 +++ .../Services/Exports/IImportLogic.cs | 13 +++ .../Exports/ShapesAllImportFromDxfLogic.cs | 31 +++++++ .../Exports/ShapesExportToDxfLogic.cs | 60 ++----------- .../SinglePolyline2DImportFromDxfLogic.cs | 18 ++++ .../Analyses/ExportFrameWorkElementLogic.cs | 2 +- .../ExportGeometryResultToCSVLogic.cs | 2 +- .../Analyses/ExportResultToBitmapLogic.cs | 2 +- .../Analyses/ExportToCSVLogicBase.cs | 2 +- 34 files changed, 498 insertions(+), 179 deletions(-) delete mode 100644 StructureHelper/Services/Exports/ExportToFileInputData.cs delete mode 100644 StructureHelper/Services/Exports/IExportService.cs delete mode 100644 StructureHelper/Services/Exports/IExportToFileInputData.cs create mode 100644 StructureHelper/Services/Exports/ImportFromFileService.cs create mode 100644 StructureHelperCommon/Models/Shapes/Logics/ArcFlatteningOption.cs create mode 100644 StructureHelperCommon/Models/Shapes/Logics/IArcFlatteningOption.cs create mode 100644 StructureHelperCommon/Models/Shapes/Logics/Polyline2DToLinePoligonConvertLogic.cs create mode 100644 StructureHelperCommon/Services/Exports/Factories/FileInputDataFactory.cs create mode 100644 StructureHelperCommon/Services/Exports/FileIOInputData.cs create mode 100644 StructureHelperCommon/Services/Exports/GetDxfLayerLogic.cs create mode 100644 StructureHelperCommon/Services/Exports/IExportLogic.cs rename StructureHelperCommon/Services/Exports/{IExportResultLogic.cs => IExportToFileLogic.cs} (77%) create mode 100644 StructureHelperCommon/Services/Exports/IFileIOnputData.cs create mode 100644 StructureHelperCommon/Services/Exports/IGetDxfLayerLogic.cs create mode 100644 StructureHelperCommon/Services/Exports/IImportFromFileLogic.cs create mode 100644 StructureHelperCommon/Services/Exports/IImportLogic.cs create mode 100644 StructureHelperCommon/Services/Exports/ShapesAllImportFromDxfLogic.cs create mode 100644 StructureHelperCommon/Services/Exports/SinglePolyline2DImportFromDxfLogic.cs diff --git a/StructureHelper/Services/Exports/ExportToFileInputData.cs b/StructureHelper/Services/Exports/ExportToFileInputData.cs deleted file mode 100644 index 51215e9..0000000 --- a/StructureHelper/Services/Exports/ExportToFileInputData.cs +++ /dev/null @@ -1,16 +0,0 @@ -using StructureHelperLogics.NdmCalculations.Analyses; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StructureHelper.Services.Exports -{ - internal class ExportToFileInputData : IExportToFileInputData - { - public string FileName { get; set; } = "New file"; - public string Filter { get; set; } - public string Title { get; set; } - } -} diff --git a/StructureHelper/Services/Exports/ExportToFileService.cs b/StructureHelper/Services/Exports/ExportToFileService.cs index 20d8138..667e18a 100644 --- a/StructureHelper/Services/Exports/ExportToFileService.cs +++ b/StructureHelper/Services/Exports/ExportToFileService.cs @@ -2,38 +2,33 @@ using StructureHelper.Windows.ViewModels.Errors; using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Services.Exports; -using StructureHelperLogics.NdmCalculations.Analyses; -using StructureHelperLogics.NdmCalculations.Analyses.ByForces; using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; namespace StructureHelper.Services.Exports { - internal class ExportToFileService : IExportService + public class ExportToFileService : IExportLogic { - IExportToFileInputData inputData; - IExportResultLogic logic; + private IFileIOnputData inputData; + private IExportToFileLogic exportLogic; - public ExportToFileService(IExportToFileInputData inputData, IExportResultLogic logic) + public ExportToFileService(IFileIOnputData inputData, IExportToFileLogic exportLogic) { this.inputData = inputData; - this.logic = logic; + this.exportLogic = exportLogic; } public void Export() { - SaveFileDialog saveFileDialog = new SaveFileDialog(); - saveFileDialog.Filter = inputData.Filter; - saveFileDialog.Title = inputData.Title; - if (saveFileDialog.ShowDialog() == DialogResult.OK) + SaveFileDialog dialog = new() { - var filename = saveFileDialog.FileName; - // If the file name is not an empty string open it for saving. + Filter = inputData.Filter, + Title = inputData.Title + }; + if (dialog.ShowDialog() == DialogResult.OK) + { + var filename = dialog.FileName; if (filename != "") { SaveFile(filename); @@ -79,8 +74,8 @@ namespace StructureHelper.Services.Exports } private void ExportFile(string fileName) { - logic.FileName = fileName; - logic.Export(); + exportLogic.FileName = fileName; + exportLogic.Export(); try { OpenFile(fileName); diff --git a/StructureHelper/Services/Exports/IExportService.cs b/StructureHelper/Services/Exports/IExportService.cs deleted file mode 100644 index 0885465..0000000 --- a/StructureHelper/Services/Exports/IExportService.cs +++ /dev/null @@ -1,14 +0,0 @@ -using StructureHelperLogics.NdmCalculations.Analyses; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StructureHelper.Services.Exports -{ - internal interface IExportService - { - void Export(); - } -} diff --git a/StructureHelper/Services/Exports/IExportToFileInputData.cs b/StructureHelper/Services/Exports/IExportToFileInputData.cs deleted file mode 100644 index 4712c74..0000000 --- a/StructureHelper/Services/Exports/IExportToFileInputData.cs +++ /dev/null @@ -1,16 +0,0 @@ -using StructureHelperLogics.NdmCalculations.Analyses; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StructureHelper.Services.Exports -{ - internal interface IExportToFileInputData - { - string FileName { get; set; } - string Filter { get; set; } - string Title { get; set; } - } -} diff --git a/StructureHelper/Services/Exports/ImportFromFileService.cs b/StructureHelper/Services/Exports/ImportFromFileService.cs new file mode 100644 index 0000000..9958e9b --- /dev/null +++ b/StructureHelper/Services/Exports/ImportFromFileService.cs @@ -0,0 +1,77 @@ +using StructureHelper.Windows.Errors; +using StructureHelper.Windows.ViewModels.Errors; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Services.Exports; +using System; +using System.IO; +using System.Windows.Forms; + +namespace StructureHelper.Services.Exports +{ + internal class ImportFromFileService : IImportFromFileLogic + { + private IFileIOnputData inputData; + private IImportFromFileLogic importLogic; + + public string FileName {get; set; } + public ImportFromFileService(IFileIOnputData inputData, IImportFromFileLogic importLogic) + { + this.inputData = inputData; + this.importLogic = importLogic; + } + + public void Import() + { + OpenFileDialog dialog = new OpenFileDialog() + { + Filter = inputData.Filter, + Title = inputData.Title + }; + if (dialog.ShowDialog() == DialogResult.OK) + { + var filename = dialog.FileName; + if (filename != "") + { + OpenFile(filename); + } + } + } + + private void OpenFile(string filename) + { + CheckIfFileExist(filename); + ImportFromFile(filename); + } + + private void ImportFromFile(string filename) + { + try + { + importLogic.FileName = filename; + importLogic.Import(); + } + catch (Exception ex) + { + var vm = new ErrorProcessor() + { + ShortText = ErrorStrings.FileCantBeOpened + ": " + filename, + DetailText = $"File: {filename} can be opened \n {ex}" + }; + new ErrorMessage(vm).ShowDialog(); + } + } + + private static void CheckIfFileExist(string filename) + { + if (!File.Exists(filename)) + { + var vm = new ErrorProcessor() + { + ShortText = ErrorStrings.FileDoesNotExsist + ": " + filename, + DetailText = $"File {filename} does not exist" + }; + new ErrorMessage(vm).ShowDialog(); + } + } + } +} diff --git a/StructureHelper/Windows/BeamShears/BeamShearResultViewModel.cs b/StructureHelper/Windows/BeamShears/BeamShearResultViewModel.cs index a0b30e8..0b98883 100644 --- a/StructureHelper/Windows/BeamShears/BeamShearResultViewModel.cs +++ b/StructureHelper/Windows/BeamShears/BeamShearResultViewModel.cs @@ -1,6 +1,8 @@ using StructureHelper.Infrastructure; using StructureHelper.Services.Exports; using StructureHelper.Windows.CalculationWindows.CalculatorsViews; +using StructureHelperCommon.Services.Exports; +using StructureHelperCommon.Services.Exports.Factories; using StructureHelperLogics.Models.BeamShears; using System.Collections.Generic; using System.Linq; @@ -48,13 +50,8 @@ namespace StructureHelper.Windows.BeamShears private void ExportToExcel(object obj) { if (SelectedResult is null) { return; } - var inputData = new ExportToFileInputData - { - Filter = "csv |*.csv", - Title = "Save in *.csv File" - }; var logic = new ExportActionResultToCSVLogic(SelectedResult); - var exportService = new ExportToFileService(inputData, logic); + var exportService = new ExportToFileService(FileInputDataFactory.GetFileIOInputData(FileInputDataType.Csv), logic); exportService.Export(); } diff --git a/StructureHelper/Windows/CalculationWindows/CalculatorsViews/Cracks/CrackResultViewModel.cs b/StructureHelper/Windows/CalculationWindows/CalculatorsViews/Cracks/CrackResultViewModel.cs index e327943..ea6d171 100644 --- a/StructureHelper/Windows/CalculationWindows/CalculatorsViews/Cracks/CrackResultViewModel.cs +++ b/StructureHelper/Windows/CalculationWindows/CalculatorsViews/Cracks/CrackResultViewModel.cs @@ -1,5 +1,6 @@ using StructureHelper.Infrastructure; using StructureHelper.Services.Exports; +using StructureHelperCommon.Services.Exports.Factories; using StructureHelperLogics.NdmCalculations.Analyses; using StructureHelperLogics.NdmCalculations.Cracking; using System.Collections.Generic; @@ -53,11 +54,7 @@ namespace StructureHelper.Windows.CalculationWindows.CalculatorsViews public ICommand ExportToCSVCommand => exportToCSVCommand ??= new RelayCommand(o => { ExportToCSV(); }); private void ExportToCSV() { - var inputData = new ExportToFileInputData - { - Filter = "csv |*.csv", - Title = "Save in *.csv File" - }; + var inputData = FileInputDataFactory.GetFileIOInputData(FileInputDataType.Csv); var logic = new ExportCrackResultToCSVLogic(resultModel); var exportService = new ExportToFileService(inputData, logic); exportService.Export(); diff --git a/StructureHelper/Windows/CalculationWindows/CalculatorsViews/ForceCalculatorViews/ForcesResultsViewModel.cs b/StructureHelper/Windows/CalculationWindows/CalculatorsViews/ForceCalculatorViews/ForcesResultsViewModel.cs index 0d43516..ce0b26f 100644 --- a/StructureHelper/Windows/CalculationWindows/CalculatorsViews/ForceCalculatorViews/ForcesResultsViewModel.cs +++ b/StructureHelper/Windows/CalculationWindows/CalculatorsViews/ForceCalculatorViews/ForcesResultsViewModel.cs @@ -18,6 +18,8 @@ using StructureHelperCommon.Infrastructures.Interfaces; using StructureHelperCommon.Infrastructures.Settings; using StructureHelperCommon.Models.Forces; using StructureHelperCommon.Models.Shapes; +using StructureHelperCommon.Services.Exports; +using StructureHelperCommon.Services.Exports.Factories; using StructureHelperCommon.Services.Forces; using StructureHelperLogics.NdmCalculations.Analyses; using StructureHelperLogics.NdmCalculations.Analyses.ByForces; @@ -134,13 +136,8 @@ namespace StructureHelper.Windows.CalculationWindows.CalculatorsViews.ForceCalcu public ICommand ExportToCSVCommand => exportToCSVCommand ??= new RelayCommand(o => { ExportToCSV();}); private void ExportToCSV() { - var inputData = new ExportToFileInputData - { - Filter = "csv |*.csv", - Title = "Save in *.csv File" - }; var logic = new ExportForcesResultToCSVLogic(resultModel); - var exportService = new ExportToFileService(inputData, logic); + var exportService = new ExportToFileService(FileInputDataFactory.GetFileIOInputData(FileInputDataType.Csv), logic); exportService.Export(); } public ICommand ShowGraphsCommand diff --git a/StructureHelper/Windows/Graphs/FrameWorkElementServiseLogic.cs b/StructureHelper/Windows/Graphs/FrameWorkElementServiseLogic.cs index 4480a28..cedbfb4 100644 --- a/StructureHelper/Windows/Graphs/FrameWorkElementServiseLogic.cs +++ b/StructureHelper/Windows/Graphs/FrameWorkElementServiseLogic.cs @@ -1,13 +1,9 @@ using StructureHelper.Services.Exports; +using StructureHelperCommon.Services.Exports.Factories; using StructureHelperLogics.NdmCalculations.Analyses; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows; -using System.Windows.Media.Imaging; using System.Windows.Media; +using System.Windows.Media.Imaging; namespace StructureHelper.Windows.Graphs { @@ -15,11 +11,7 @@ namespace StructureHelper.Windows.Graphs { public void SaveImageToFile(FrameworkElement element, double scaleFactor = 1) { - var inputData = new ExportToFileInputData - { - Filter = "png |*.png", - Title = "Save in *.png File" - }; + var inputData = FileInputDataFactory.GetFileIOInputData(FileInputDataType.Png); var logic = new ExportFrameWorkElementLogic(element, scaleFactor); var exportService = new ExportToFileService(inputData, logic); exportService.Export(); diff --git a/StructureHelper/Windows/Graphs/GraphViewModel.cs b/StructureHelper/Windows/Graphs/GraphViewModel.cs index 63cce6b..7a7586a 100644 --- a/StructureHelper/Windows/Graphs/GraphViewModel.cs +++ b/StructureHelper/Windows/Graphs/GraphViewModel.cs @@ -4,6 +4,8 @@ using StructureHelper.Infrastructure; using StructureHelper.Services.Exports; using StructureHelper.Windows.ViewModels; using StructureHelperCommon.Models.Parameters; +using StructureHelperCommon.Services.Exports; +using StructureHelperCommon.Services.Exports.Factories; using StructureHelperLogics.NdmCalculations.Analyses; using StructureHelperLogics.NdmCalculations.Analyses.ByForces; using System; @@ -87,11 +89,7 @@ namespace StructureHelper.Windows.Graphs private void ExportSeries() { - var inputData = new ExportToFileInputData - { - Filter = "csv |*.csv", - Title = "Save in *.csv File" - }; + var inputData = FileInputDataFactory.GetFileIOInputData(FileInputDataType.Csv); var logic = new ExportChartToCSVLogic(Series); var exportService = new ExportToFileService(inputData, logic); exportService.Export(); diff --git a/StructureHelper/Windows/Shapes/PolygonShapeView.xaml b/StructureHelper/Windows/Shapes/PolygonShapeView.xaml index e56a7dc..f178aa9 100644 --- a/StructureHelper/Windows/Shapes/PolygonShapeView.xaml +++ b/StructureHelper/Windows/Shapes/PolygonShapeView.xaml @@ -142,8 +142,8 @@ CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False"> - - + + diff --git a/StructureHelper/Windows/Shapes/PolygonShapeViewModel.cs b/StructureHelper/Windows/Shapes/PolygonShapeViewModel.cs index 838fcfd..bf85df0 100644 --- a/StructureHelper/Windows/Shapes/PolygonShapeViewModel.cs +++ b/StructureHelper/Windows/Shapes/PolygonShapeViewModel.cs @@ -9,10 +9,13 @@ using StructureHelper.Windows.BeamShears; using StructureHelper.Windows.Shapes.Logics; using StructureHelper.Windows.UserControls.WorkPlanes; using StructureHelper.Windows.ViewModels; +using StructureHelper.Windows.ViewModels.Errors; using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Infrastructures.Interfaces; using StructureHelperCommon.Models.Shapes; +using StructureHelperCommon.Models.Shapes.Logics; using StructureHelperCommon.Services.Exports; +using StructureHelperCommon.Services.Exports.Factories; using StructureHelperLogics.Models.BeamShears; using System; using System.Collections.Generic; @@ -67,25 +70,35 @@ namespace StructureHelper.Windows.Shapes private void ImportFromDxf(object commandParameter) { - // your DXF file name - string file = "sample.dxf"; - // this check is optional but recommended before loading a DXF file - DxfVersion dxfVersion = DxfDocument.CheckDxfFileVersion(file); - // netDxf is only compatible with AutoCad2000 and higher DXF versions - if (dxfVersion < DxfVersion.AutoCad2000) return; - // load file - DxfDocument loaded = DxfDocument.Load(file); + SafetyProcessor.RunSafeProcess(GetPolyline2D, "Error of obtaining of dxf polyline"); + SafetyProcessor.RunSafeProcess(UpdatePolygon, "Error of updating of polygon"); + } + + private void UpdatePolygon() + { + var convertLogic = new Polyline2DToLinePoligonConvertLogic(); + LinePolygonShape newPolygonShape = convertLogic.Convert(polyline); + newPolygonShape.IsClosed = true; + var updateLogic = new LinePolygonShapeUpdateStrategy(); + updateLogic.Update(polygonShape, newPolygonShape); + ReloadVertices(); + Redraw(null); + } + + private static void GetPolyline2D() + { + FileIOInputData inputData = FileInputDataFactory.GetFileIOInputData(FileInputDataType.Dxf); + var logic = new SinglePolyline2DImportFromDxfLogic(); + var importService = new ImportFromFileService(inputData, logic); + importService.Import(); + polyline = logic.Polyline2D; } public ICommand ExportToDxfCommand => exportToDxfCommand ??= new RelayCommand(ExportToDxf); private void ExportToDxf(object commandParameter) { - var inputData = new ExportToFileInputData - { - Filter = "dxf |*.dxf", - Title = "Save in *.dxf File" - }; + FileIOInputData inputData = FileInputDataFactory.GetFileIOInputData(FileInputDataType.Dxf); var logic = new ShapesExportToDxfLogic(polygonShape, LayerNames.StructiralPrimitives); var exportService = new ExportToFileService(inputData, logic); exportService.Export(); @@ -191,6 +204,7 @@ namespace StructureHelper.Windows.Shapes private RelayCommand deleteVertexCommand; private RelayCommand flipVerticalCommand; private RelayCommand flipHorizontalCommand; + private static Polyline2D polyline; public ICommand DeleteVertexCommand => deleteVertexCommand ??= new RelayCommand(DeleteVertex, o => SelectedVertex is not null && Vertices.Count >= minVertexCount); diff --git a/StructureHelper/Windows/ViewModels/Calculations/Calculators/GeometryCalculatorVMs/GeometryCalculatorResultViewModel.cs b/StructureHelper/Windows/ViewModels/Calculations/Calculators/GeometryCalculatorVMs/GeometryCalculatorResultViewModel.cs index 9ae07d3..17dbd67 100644 --- a/StructureHelper/Windows/ViewModels/Calculations/Calculators/GeometryCalculatorVMs/GeometryCalculatorResultViewModel.cs +++ b/StructureHelper/Windows/ViewModels/Calculations/Calculators/GeometryCalculatorVMs/GeometryCalculatorResultViewModel.cs @@ -10,6 +10,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; +using StructureHelperCommon.Services.Exports; +using StructureHelperCommon.Services.Exports.Factories; namespace StructureHelper.Windows.ViewModels.Calculations.Calculators.GeometryCalculatorVMs { @@ -32,11 +34,7 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators.GeometryCa } private void ExportToCSV() { - var inputData = new ExportToFileInputData - { - Filter = "csv |*.csv", - Title = "Save in csv File" - }; + var inputData = FileInputDataFactory.GetFileIOInputData(FileInputDataType.Csv); var logic = new ExportGeometryResultToCSVLogic(result); var exportService = new ExportToFileService(inputData, logic); exportService.Export(); diff --git a/StructureHelperCommon/Infrastructures/Exceptions/ErrorString.cs b/StructureHelperCommon/Infrastructures/Exceptions/ErrorString.cs index 6f381e6..fcc1dc9 100644 --- a/StructureHelperCommon/Infrastructures/Exceptions/ErrorString.cs +++ b/StructureHelperCommon/Infrastructures/Exceptions/ErrorString.cs @@ -29,5 +29,7 @@ public static string CalculationError => "#0019: Error of calculation"; public static string SourceObject => "#0020: Source object"; public static string TargetObject => "#0021: Target object"; + public static string FileDoesNotExsist => "#0022: File does not exist"; + public static string FileCantBeOpened => "#0023: File can not be opened"; } } diff --git a/StructureHelperCommon/Infrastructures/Interfaces/IObjectConvertStrategy.cs b/StructureHelperCommon/Infrastructures/Interfaces/IObjectConvertStrategy.cs index ec5e42e..f859ac1 100644 --- a/StructureHelperCommon/Infrastructures/Interfaces/IObjectConvertStrategy.cs +++ b/StructureHelperCommon/Infrastructures/Interfaces/IObjectConvertStrategy.cs @@ -6,8 +6,18 @@ using System.Threading.Tasks; namespace StructureHelperCommon.Infrastructures.Interfaces { + /// + /// Implements logic for convert from one object to another one + /// + /// Type of target object + /// Type of source object public interface IObjectConvertStrategy { + /// + /// Converts sourve object to another one + /// + /// Source object + /// Target object T Convert(V source); } } diff --git a/StructureHelperCommon/Models/Shapes/Logics/ArcFlatteningOption.cs b/StructureHelperCommon/Models/Shapes/Logics/ArcFlatteningOption.cs new file mode 100644 index 0000000..85e2f06 --- /dev/null +++ b/StructureHelperCommon/Models/Shapes/Logics/ArcFlatteningOption.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Models.Shapes +{ + public enum ArcFlatteningMode + { + ByAngleStep, + BySegmentCount, + ByMaxSegmentLength, + Combined + } + + public class ArcFlatteningOption : IArcFlatteningOption + { + public ArcFlatteningMode Mode { get; set; } = ArcFlatteningMode.Combined; + public double AngleStepRadians { get; set; } = Math.PI / 8; // 22.5° + public int SegmentCount { get; set; } = 2; + public double MaxSegmentLength { get; set; } = 0.05; // (m) + } +} diff --git a/StructureHelperCommon/Models/Shapes/Logics/IArcFlatteningOption.cs b/StructureHelperCommon/Models/Shapes/Logics/IArcFlatteningOption.cs new file mode 100644 index 0000000..98daa97 --- /dev/null +++ b/StructureHelperCommon/Models/Shapes/Logics/IArcFlatteningOption.cs @@ -0,0 +1,10 @@ +namespace StructureHelperCommon.Models.Shapes +{ + public interface IArcFlatteningOption + { + double AngleStepRadians { get; set; } + double MaxSegmentLength { get; set; } + ArcFlatteningMode Mode { get; set; } + int SegmentCount { get; set; } + } +} \ No newline at end of file diff --git a/StructureHelperCommon/Models/Shapes/Logics/Polyline2DToLinePoligonConvertLogic.cs b/StructureHelperCommon/Models/Shapes/Logics/Polyline2DToLinePoligonConvertLogic.cs new file mode 100644 index 0000000..e17d50c --- /dev/null +++ b/StructureHelperCommon/Models/Shapes/Logics/Polyline2DToLinePoligonConvertLogic.cs @@ -0,0 +1,89 @@ +using netDxf.Entities; +using StructureHelperCommon.Infrastructures.Interfaces; +using System; + +namespace StructureHelperCommon.Models.Shapes +{ + public class Polyline2DToLinePoligonConvertLogic : IObjectConvertStrategy + { + private const double metresToMillimeters = 1000.0; + private IArcFlatteningOption options = new ArcFlatteningOption(); + + public LinePolygonShape Convert(Polyline2D source) + { + var polygon = new LinePolygonShape(Guid.NewGuid()); + + for (int i = 0; i < source.Vertexes.Count; i++) + { + var v1 = source.Vertexes[i]; + var v2 = source.Vertexes[(i + 1) % source.Vertexes.Count]; + + polygon.AddVertex(new Vertex(v1.Position.X / metresToMillimeters, v1.Position.Y / metresToMillimeters)); + + double bulge = v1.Bulge; + if (Math.Abs(bulge) < 1e-9) + continue; + ProcessBulge(polygon, v1, v2, bulge); + } + + polygon.IsClosed = source.IsClosed; + return polygon; + } + + private void ProcessBulge(LinePolygonShape polygon, Polyline2DVertex v1, Polyline2DVertex v2, double bulge) + { + var p1 = v1.Position; + var p2 = v2.Position; + + double chord = Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2)); + double theta = 4 * Math.Atan(Math.Abs(bulge)); + double radius = chord / (2 * Math.Sin(theta / 2)); + + double dir = bulge > 0 ? 1 : -1; + + // Compute arc center + double mx = (p1.X + p2.X) / 2; + double my = (p1.Y + p2.Y) / 2; + double nx = -(p2.Y - p1.Y) / chord; + double ny = (p2.X - p1.X) / chord; + double d = radius * Math.Cos(theta / 2); + double cx = mx + dir * nx * d; + double cy = my + dir * ny * d; + + double a1 = Math.Atan2(p1.Y - cy, p1.X - cx); + double a2 = Math.Atan2(p2.Y - cy, p2.X - cx); + + double totalAngle = a2 - a1; + if (dir > 0 && totalAngle < 0) totalAngle += 2 * Math.PI; + if (dir < 0 && totalAngle > 0) totalAngle -= 2 * Math.PI; + + double stepAngle = GetEffectiveStepAngle(radius, Math.Abs(totalAngle), options); + int segments = Math.Max(2, (int)Math.Ceiling(Math.Abs(totalAngle) / stepAngle)); + + for (int j = 1; j < segments; j++) + { + double a = a1 + totalAngle * j / segments; + double x = cx + radius * Math.Cos(a); + double y = cy + radius * Math.Sin(a); + polygon.AddVertex(new Vertex(x / metresToMillimeters, y / metresToMillimeters)); + } + } + + private static double GetEffectiveStepAngle(double radius, double arcAngle, IArcFlatteningOption options) + { + // compute angle from each criterion + double byAngle = options.AngleStepRadians; + double byCount = arcAngle / options.SegmentCount; + double byLength = 2 * Math.Asin(options.MaxSegmentLength / (2 * radius)); + + return options.Mode switch + { + ArcFlatteningMode.ByAngleStep => byAngle, + ArcFlatteningMode.BySegmentCount => byCount, + ArcFlatteningMode.ByMaxSegmentLength => byLength, + ArcFlatteningMode.Combined => Math.Min(byAngle, Math.Min(byCount, byLength)), + _ => byAngle + }; + } + } +} diff --git a/StructureHelperCommon/Services/Exports/Factories/FileInputDataFactory.cs b/StructureHelperCommon/Services/Exports/Factories/FileInputDataFactory.cs new file mode 100644 index 0000000..d212164 --- /dev/null +++ b/StructureHelperCommon/Services/Exports/Factories/FileInputDataFactory.cs @@ -0,0 +1,50 @@ +using StructureHelperCommon.Infrastructures.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Services.Exports.Factories +{ + public enum FileInputDataType + { + Csv, + Png, + Dxf + } + public static class FileInputDataFactory + { + public static FileIOInputData GetFileIOInputData(FileInputDataType dataType) + { + if (dataType == FileInputDataType.Csv) + { + return new FileIOInputData + { + Filter = "csv |*.csv", + Title = "Save in csv File" + }; + } + else if (dataType == FileInputDataType.Png) + { + return new FileIOInputData + { + Filter = "png |*.png", + Title = "Save in *.png File" + }; + } + else if (dataType == FileInputDataType.Dxf) + { + return new FileIOInputData + { + Filter = "dxf |*.dxf", + Title = "Save in *.dxf File" + }; + } + else + { + throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(dataType)); + } + } + } +} diff --git a/StructureHelperCommon/Services/Exports/FileIOInputData.cs b/StructureHelperCommon/Services/Exports/FileIOInputData.cs new file mode 100644 index 0000000..96890ef --- /dev/null +++ b/StructureHelperCommon/Services/Exports/FileIOInputData.cs @@ -0,0 +1,9 @@ +namespace StructureHelperCommon.Services.Exports +{ + public class FileIOInputData : IFileIOnputData + { + public string FileName { get; set; } = "New file"; + public string Filter { get; set; } + public string Title { get; set; } + } +} diff --git a/StructureHelperCommon/Services/Exports/GetDxfLayerLogic.cs b/StructureHelperCommon/Services/Exports/GetDxfLayerLogic.cs new file mode 100644 index 0000000..b979a31 --- /dev/null +++ b/StructureHelperCommon/Services/Exports/GetDxfLayerLogic.cs @@ -0,0 +1,54 @@ +using netDxf; +using netDxf.Tables; +using StructureHelperCommon.Infrastructures.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Services.Exports +{ + public class GetDxfLayerLogic : IGetDxfLayerLogic + { + private const string PrimitivesLayer = "STR-PRM"; + private const string OpeningsLayer = "STR-OPN"; + private const string RebarLayer = "STR-REB"; + private const string LayerNameIsUnKnown = ": Layer name is unknown"; + public Layer GetOrCreateLayer(DxfDocument dxf, LayerNames layerName) + { + string newLayerName = GetLayerName(layerName); + Layer newLayer = dxf.Layers.Contains(newLayerName) + ? dxf.Layers[newLayerName] + : new Layer(newLayerName) + { + Color = GetLayerColor(layerName) + }; + + if (!dxf.Layers.Contains(newLayerName)) + dxf.Layers.Add(newLayer); + return newLayer; + } + public string GetLayerName(LayerNames layerName) + { + if (layerName == LayerNames.StructiralPrimitives) { return PrimitivesLayer; } + else if (layerName == LayerNames.StructuralOpenings) { return OpeningsLayer; } + else if (layerName == LayerNames.StructuralRebars) { return RebarLayer; } + else + { + throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(layerName) + LayerNameIsUnKnown); + } + } + + public AciColor GetLayerColor(LayerNames layerName) + { + if (layerName == LayerNames.StructiralPrimitives) { return AciColor.Blue; } + else if (layerName == LayerNames.StructuralOpenings) { return AciColor.DarkGray; } + else if (layerName == LayerNames.StructuralRebars) { return AciColor.Magenta; } + else + { + throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(layerName) + LayerNameIsUnKnown); + } + } + } +} diff --git a/StructureHelperCommon/Services/Exports/IExportLogic.cs b/StructureHelperCommon/Services/Exports/IExportLogic.cs new file mode 100644 index 0000000..2141c9d --- /dev/null +++ b/StructureHelperCommon/Services/Exports/IExportLogic.cs @@ -0,0 +1,7 @@ +namespace StructureHelperCommon.Services.Exports +{ + public interface IExportLogic + { + void Export(); + } +} diff --git a/StructureHelperCommon/Services/Exports/IExportResultLogic.cs b/StructureHelperCommon/Services/Exports/IExportToFileLogic.cs similarity index 77% rename from StructureHelperCommon/Services/Exports/IExportResultLogic.cs rename to StructureHelperCommon/Services/Exports/IExportToFileLogic.cs index 0987025..ab36e11 100644 --- a/StructureHelperCommon/Services/Exports/IExportResultLogic.cs +++ b/StructureHelperCommon/Services/Exports/IExportToFileLogic.cs @@ -6,9 +6,8 @@ using System.Threading.Tasks; namespace StructureHelperCommon.Services.Exports { - public interface IExportResultLogic + public interface IExportToFileLogic : IExportLogic { string FileName { get; set; } - void Export(); } } diff --git a/StructureHelperCommon/Services/Exports/IFileIOnputData.cs b/StructureHelperCommon/Services/Exports/IFileIOnputData.cs new file mode 100644 index 0000000..6855bef --- /dev/null +++ b/StructureHelperCommon/Services/Exports/IFileIOnputData.cs @@ -0,0 +1,9 @@ +namespace StructureHelperCommon.Services.Exports +{ + public interface IFileIOnputData + { + string FileName { get; set; } + string Filter { get; set; } + string Title { get; set; } + } +} diff --git a/StructureHelperCommon/Services/Exports/IGetDxfLayerLogic.cs b/StructureHelperCommon/Services/Exports/IGetDxfLayerLogic.cs new file mode 100644 index 0000000..2095cec --- /dev/null +++ b/StructureHelperCommon/Services/Exports/IGetDxfLayerLogic.cs @@ -0,0 +1,12 @@ +using netDxf; +using netDxf.Tables; + +namespace StructureHelperCommon.Services.Exports +{ + public interface IGetDxfLayerLogic + { + AciColor GetLayerColor(LayerNames layerName); + string GetLayerName(LayerNames layerName); + Layer GetOrCreateLayer(DxfDocument dxf, LayerNames layerName); + } +} \ No newline at end of file diff --git a/StructureHelperCommon/Services/Exports/IImportFromFileLogic.cs b/StructureHelperCommon/Services/Exports/IImportFromFileLogic.cs new file mode 100644 index 0000000..bd8f018 --- /dev/null +++ b/StructureHelperCommon/Services/Exports/IImportFromFileLogic.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Services.Exports +{ + public interface IImportFromFileLogic : IImportLogic + { + string FileName { get; set; } + } +} diff --git a/StructureHelperCommon/Services/Exports/IImportLogic.cs b/StructureHelperCommon/Services/Exports/IImportLogic.cs new file mode 100644 index 0000000..14b9e39 --- /dev/null +++ b/StructureHelperCommon/Services/Exports/IImportLogic.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Services.Exports +{ + public interface IImportLogic + { + void Import(); + } +} diff --git a/StructureHelperCommon/Services/Exports/ShapesAllImportFromDxfLogic.cs b/StructureHelperCommon/Services/Exports/ShapesAllImportFromDxfLogic.cs new file mode 100644 index 0000000..d165f2f --- /dev/null +++ b/StructureHelperCommon/Services/Exports/ShapesAllImportFromDxfLogic.cs @@ -0,0 +1,31 @@ +using netDxf; +using netDxf.Entities; +using netDxf.Header; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Services.Exports +{ + public class ShapesAllImportFromDxfLogic : IImportFromFileLogic + { + public string FileName { get; set; } + public List Entities { get; set; } = []; + public void Import() + { + // this check is optional but recommended before loading a DXF file + DxfVersion dxfVersion = DxfDocument.CheckDxfFileVersion(FileName); + // netDxf is only compatible with AutoCad2000 and higher DXF versions + if (dxfVersion < DxfVersion.AutoCad2000) return; + // load file + DxfDocument dxf = DxfDocument.Load(FileName); + Entities.Clear(); + if (dxf != null) + { + Entities.AddRange(dxf.Entities.All); + } + } + } +} diff --git a/StructureHelperCommon/Services/Exports/ShapesExportToDxfLogic.cs b/StructureHelperCommon/Services/Exports/ShapesExportToDxfLogic.cs index 13144ba..70d5953 100644 --- a/StructureHelperCommon/Services/Exports/ShapesExportToDxfLogic.cs +++ b/StructureHelperCommon/Services/Exports/ShapesExportToDxfLogic.cs @@ -3,11 +3,7 @@ using netDxf.Entities; using netDxf.Tables; using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Models.Shapes; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace StructureHelperCommon.Services.Exports { @@ -17,14 +13,12 @@ namespace StructureHelperCommon.Services.Exports StructuralOpenings, StructuralRebars } - public class ShapesExportToDxfLogic : IExportResultLogic + public class ShapesExportToDxfLogic : IExportToFileLogic { - private const string PrimitivesLayer = "STR-PRM"; - private const string OpeningsLayer = "STR-OPN"; - private const string RebarLayer = "STR-REB"; - private const string LayerNameIsUnKnown = ": Layer name is unknown"; private const string ShapeTypeIsUnknown = ": Shape is unknown"; + private const double metresToMillimeters = 1000.0; private readonly List<(IShape shape, LayerNames layerName)> shapes = []; + private IGetDxfLayerLogic layerLogic = new GetDxfLayerLogic(); public ShapesExportToDxfLogic(List<(IShape shape, LayerNames layerName)> shapes) { @@ -45,19 +39,12 @@ namespace StructureHelperCommon.Services.Exports { ProcessShape(dxf, shape); } - Layer primitiveLayer = new Layer(PrimitivesLayer) - { - Color = AciColor.Blue - }; - dxf.Layers.Add(primitiveLayer); - - // save to file dxf.Save(FileName); } private void ProcessShape(DxfDocument dxf, (IShape shape, LayerNames layerName) shape) { - Layer layer = GetOrCreateLayer(dxf, shape.layerName); + Layer layer = layerLogic.GetOrCreateLayer(dxf, shape.layerName); ProcessShape(dxf, shape.shape, layer); } @@ -78,7 +65,7 @@ namespace StructureHelperCommon.Services.Exports List polylineVertices = []; foreach (var item in linePolygon.Vertices) { - Polyline2DVertex vertex = new Polyline2DVertex(item.Point.X, item.Point.Y); + Polyline2DVertex vertex = new Polyline2DVertex(item.Point.X * metresToMillimeters, item.Point.Y * metresToMillimeters); polylineVertices.Add(vertex); } Polyline2D polyline2D = new Polyline2D(polylineVertices) @@ -88,42 +75,5 @@ namespace StructureHelperCommon.Services.Exports }; dxf.Entities.Add(polyline2D); } - - private Layer GetOrCreateLayer(DxfDocument dxf, LayerNames layerName) - { - string newLayerName = GetLayerName(layerName); - Layer newLayer = dxf.Layers.Contains("newLayerName") - ? dxf.Layers["newLayerName"] - : new Layer("newLayerName") - { - Color = GetLayerColor(layerName) - }; - - if (!dxf.Layers.Contains(newLayerName)) - dxf.Layers.Add(newLayer); - return newLayer; - } - - private string GetLayerName(LayerNames layerName) - { - if (layerName == LayerNames.StructiralPrimitives) { return PrimitivesLayer; } - else if (layerName == LayerNames.StructuralOpenings) { return OpeningsLayer; } - else if (layerName == LayerNames.StructuralRebars) { return RebarLayer; } - else - { - throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(layerName) + LayerNameIsUnKnown); - } - } - - private AciColor GetLayerColor(LayerNames layerName) - { - if (layerName == LayerNames.StructiralPrimitives) { return AciColor.Blue; } - else if (layerName == LayerNames.StructuralOpenings) { return AciColor.DarkGray; } - else if (layerName == LayerNames.StructuralRebars) { return AciColor.Magenta; } - else - { - throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(layerName) + LayerNameIsUnKnown); - } - } } } diff --git a/StructureHelperCommon/Services/Exports/SinglePolyline2DImportFromDxfLogic.cs b/StructureHelperCommon/Services/Exports/SinglePolyline2DImportFromDxfLogic.cs new file mode 100644 index 0000000..a3cc4a5 --- /dev/null +++ b/StructureHelperCommon/Services/Exports/SinglePolyline2DImportFromDxfLogic.cs @@ -0,0 +1,18 @@ +using netDxf.Entities; +using System.Linq; + +namespace StructureHelperCommon.Services.Exports +{ + public class SinglePolyline2DImportFromDxfLogic : IImportFromFileLogic + { + public string FileName { get; set; } + public Polyline2D Polyline2D { get; private set; } + public void Import() + { + var importLogic = new ShapesAllImportFromDxfLogic() { FileName = FileName}; + importLogic.Import(); + var entities = importLogic.Entities; + Polyline2D = entities.Single(x => x is Polyline2D) as Polyline2D; + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Analyses/ExportFrameWorkElementLogic.cs b/StructureHelperLogics/NdmCalculations/Analyses/ExportFrameWorkElementLogic.cs index 4a7000d..caf5737 100644 --- a/StructureHelperLogics/NdmCalculations/Analyses/ExportFrameWorkElementLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Analyses/ExportFrameWorkElementLogic.cs @@ -5,7 +5,7 @@ using System.Windows.Media.Imaging; namespace StructureHelperLogics.NdmCalculations.Analyses { - public class ExportFrameWorkElementLogic : IExportResultLogic + public class ExportFrameWorkElementLogic : IExportToFileLogic { private FrameworkElement element; private double scaleFactor; diff --git a/StructureHelperLogics/NdmCalculations/Analyses/ExportGeometryResultToCSVLogic.cs b/StructureHelperLogics/NdmCalculations/Analyses/ExportGeometryResultToCSVLogic.cs index e666771..182ea1c 100644 --- a/StructureHelperLogics/NdmCalculations/Analyses/ExportGeometryResultToCSVLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Analyses/ExportGeometryResultToCSVLogic.cs @@ -4,7 +4,7 @@ using System.Text; namespace StructureHelperLogics.NdmCalculations.Analyses { - public class ExportGeometryResultToCSVLogic : IExportResultLogic + public class ExportGeometryResultToCSVLogic : IExportToFileLogic { const string separator = ";"; StringBuilder output; diff --git a/StructureHelperLogics/NdmCalculations/Analyses/ExportResultToBitmapLogic.cs b/StructureHelperLogics/NdmCalculations/Analyses/ExportResultToBitmapLogic.cs index cbb3c35..d1c4416 100644 --- a/StructureHelperLogics/NdmCalculations/Analyses/ExportResultToBitmapLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Analyses/ExportResultToBitmapLogic.cs @@ -3,7 +3,7 @@ using System.Windows.Media.Imaging; namespace StructureHelperLogics.NdmCalculations.Analyses { - public class ExportResultToBitmapLogic : IExportResultLogic + public class ExportResultToBitmapLogic : IExportToFileLogic { private BitmapImage bitmapImage; diff --git a/StructureHelperLogics/NdmCalculations/Analyses/ExportToCSVLogicBase.cs b/StructureHelperLogics/NdmCalculations/Analyses/ExportToCSVLogicBase.cs index 65c7639..584ec60 100644 --- a/StructureHelperLogics/NdmCalculations/Analyses/ExportToCSVLogicBase.cs +++ b/StructureHelperLogics/NdmCalculations/Analyses/ExportToCSVLogicBase.cs @@ -3,7 +3,7 @@ using System.Text; namespace StructureHelperLogics.NdmCalculations.Analyses { - public abstract class ExportToCSVLogicBase : IExportResultLogic + public abstract class ExportToCSVLogicBase : IExportToFileLogic { public string separator => ";"; public StringBuilder output { get; } = new();