From 8e4b375e803f31f0c54419243915c151f12072ad Mon Sep 17 00:00:00 2001 From: palex Date: Tue, 6 Jan 2026 02:07:18 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D1=8C=D1=82?= =?UTF-8?q?=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.config | 26 + App.xaml | 13 + App.xaml.cs | 24 + BL/Bore.cs | 119 +++ BL/DataPair.cs | 26 + BL/DataR.cs | 404 ++++++++ BL/DataS.cs | 28 + BL/Enums.cs | 18 + BL/FoundLoad.cs | 82 ++ BL/Foundation.cs | 920 ++++++++++++++++++ BL/IGE.cs | 168 ++++ BL/Layer.cs | 96 ++ BL/PlanningVertex.cs | 39 + BL/PlayGround.cs | 69 ++ BL/Structure.cs | 30 + BL/TablesInterolator.cs | 415 ++++++++ BL/ToSerializ.cs | 15 + Dictionary.xaml | 107 ++ Geometry/BoundingBox2d.cs | 31 + Geometry/IVector.cs | 9 + Geometry/Line2d.cs | 96 ++ Geometry/Line3d.cs | 37 + Geometry/Matrix.cs | 200 ++++ Geometry/Plane.cs | 242 +++++ Geometry/Point2d.cs | 120 +++ Geometry/Point3d.cs | 156 +++ Geometry/Polygon.cs | 663 +++++++++++++ Geometry/Quadrangle.cs | 147 +++ Geometry/Triangle.cs | 67 ++ Geometry/UnitsEnums.cs | 11 + Geometry/Vector.cs | 57 ++ Geometry/Vector2d.cs | 97 ++ Geometry/Vector3d.cs | 107 ++ Grapfics/CanvasDrafter.cs | 231 +++++ Grapfics/RenderVisualService.cs | 85 ++ GroundOrganizer.csproj | 312 ++++++ GroundOrganizer.sln | 25 + Images/Bookmark-add-icon32.png | Bin 0 -> 1508 bytes Images/Help-and-Support-icon32.png | Bin 0 -> 1088 bytes Images/Save-icon32.png | Bin 0 -> 1570 bytes Images/Save_as-80_icon-icons.com32.png | Bin 0 -> 961 bytes Images/ShemaLoads.png | Bin 0 -> 14701 bytes Images/XLSX_export-32.png | Bin 0 -> 1611 bytes Images/XLSX_import-32.png | Bin 0 -> 1585 bytes Images/database-accept-icon.png | Bin 0 -> 2272 bytes Images/drawing1_32.png | Bin 0 -> 582 bytes Images/drawing32.png | Bin 0 -> 1794 bytes Images/icons8-export-csv-32.png | Bin 0 -> 1122 bytes Images/icons8-import-csv-32.png | Bin 0 -> 1021 bytes Images/icons8-mesh-32 (1).png | Bin 0 -> 1706 bytes Images/icons8-mesh-32.png | Bin 0 -> 1321 bytes Images/icons8-mesh-80_ed1.png | Bin 0 -> 1721 bytes Images/icons8-spiderweb-32.png | Bin 0 -> 1696 bytes Images/interfaceDXF.png | Bin 0 -> 855 bytes Images/table_1061_32.png | Bin 0 -> 1158 bytes Images/text-list-numbers-icon32.png | Bin 0 -> 1167 bytes MainWindow.xaml | 125 +++ MainWindow.xaml.cs | 70 ++ Pages/BoresPage.xaml | 300 ++++++ Pages/BoresPage.xaml.cs | 31 + Pages/FoundationsPage.xaml | 377 +++++++ Pages/FoundationsPage.xaml.cs | 31 + Pages/IGEsPage.xaml | 230 +++++ Pages/IGEsPage.xaml.cs | 41 + Pages/MainPage.xaml | 60 ++ Pages/MainPage.xaml.cs | 29 + Pages/PlayGroundsPage.xaml | 90 ++ Pages/PlayGroundsPage.xaml.cs | 31 + Pages/ResultsPage.cs | 31 + Pages/ResultsPage.xaml | 41 + Pages/StructuresPage.xaml | 350 +++++++ Pages/StructuresPage.xaml.cs | 31 + Properties/AssemblyInfo.cs | 55 ++ Properties/Resources.Designer.cs | 140 +++ Properties/Resources.resx | 136 +++ Properties/Settings.Designer.cs | 38 + Properties/Settings.settings | 9 + Resources/ShemaFound.png | Bin 0 -> 90517 bytes Resources/ShemaLoads.png | Bin 0 -> 19549 bytes ...iness-color_books_icon-icons.com_53474.ico | Bin 0 -> 67646 bytes Resources/tabl_5_5.csv | 46 + Resources/Аннотация 2019-06-14 145047.png | Bin 0 -> 14964 bytes Resources/ИГЭ.xlsx | Bin 0 -> 14199 bytes Settings.cs | 28 + TestWindow.xaml | 120 +++ TestWindow.xaml.cs | 28 + VM/BoresVM.cs | 208 ++++ VM/CalculationsVM.cs | 175 ++++ VM/DrawingVM.cs | 81 ++ VM/FoundLoadsVM.cs | 188 ++++ VM/FoundationsVM.cs | 401 ++++++++ VM/HelpsVM.cs | 94 ++ VM/IGEsVM.cs | 278 ++++++ VM/LayersVM.cs | 244 +++++ VM/PlanningVM.cs | 363 +++++++ VM/PlayGroundVM.cs | 87 ++ VM/RelayCommand.cs | 38 + VM/StructuresVM.cs | 96 ++ VM/UnitsViewModel .cs | 131 +++ VM/ViewModel.cs | 101 ++ Windows/AlertWindow.xaml | 24 + Windows/AlertWindow.xaml.cs | 32 + Windows/CanwasWindow.xaml | 71 ++ Windows/CanwasWindow.xaml.cs | 163 ++++ Windows/FoundPropWindow.xaml | 188 ++++ Windows/FoundPropWindow.xaml.cs | 43 + Windows/ImageWindow.xaml | 17 + Windows/ImageWindow.xaml.cs | 27 + packages.config | 7 + 109 files changed, 10817 insertions(+) create mode 100644 App.config create mode 100644 App.xaml create mode 100644 App.xaml.cs create mode 100644 BL/Bore.cs create mode 100644 BL/DataPair.cs create mode 100644 BL/DataR.cs create mode 100644 BL/DataS.cs create mode 100644 BL/Enums.cs create mode 100644 BL/FoundLoad.cs create mode 100644 BL/Foundation.cs create mode 100644 BL/IGE.cs create mode 100644 BL/Layer.cs create mode 100644 BL/PlanningVertex.cs create mode 100644 BL/PlayGround.cs create mode 100644 BL/Structure.cs create mode 100644 BL/TablesInterolator.cs create mode 100644 BL/ToSerializ.cs create mode 100644 Dictionary.xaml create mode 100644 Geometry/BoundingBox2d.cs create mode 100644 Geometry/IVector.cs create mode 100644 Geometry/Line2d.cs create mode 100644 Geometry/Line3d.cs create mode 100644 Geometry/Matrix.cs create mode 100644 Geometry/Plane.cs create mode 100644 Geometry/Point2d.cs create mode 100644 Geometry/Point3d.cs create mode 100644 Geometry/Polygon.cs create mode 100644 Geometry/Quadrangle.cs create mode 100644 Geometry/Triangle.cs create mode 100644 Geometry/UnitsEnums.cs create mode 100644 Geometry/Vector.cs create mode 100644 Geometry/Vector2d.cs create mode 100644 Geometry/Vector3d.cs create mode 100644 Grapfics/CanvasDrafter.cs create mode 100644 Grapfics/RenderVisualService.cs create mode 100644 GroundOrganizer.csproj create mode 100644 GroundOrganizer.sln create mode 100644 Images/Bookmark-add-icon32.png create mode 100644 Images/Help-and-Support-icon32.png create mode 100644 Images/Save-icon32.png create mode 100644 Images/Save_as-80_icon-icons.com32.png create mode 100644 Images/ShemaLoads.png create mode 100644 Images/XLSX_export-32.png create mode 100644 Images/XLSX_import-32.png create mode 100644 Images/database-accept-icon.png create mode 100644 Images/drawing1_32.png create mode 100644 Images/drawing32.png create mode 100644 Images/icons8-export-csv-32.png create mode 100644 Images/icons8-import-csv-32.png create mode 100644 Images/icons8-mesh-32 (1).png create mode 100644 Images/icons8-mesh-32.png create mode 100644 Images/icons8-mesh-80_ed1.png create mode 100644 Images/icons8-spiderweb-32.png create mode 100644 Images/interfaceDXF.png create mode 100644 Images/table_1061_32.png create mode 100644 Images/text-list-numbers-icon32.png create mode 100644 MainWindow.xaml create mode 100644 MainWindow.xaml.cs create mode 100644 Pages/BoresPage.xaml create mode 100644 Pages/BoresPage.xaml.cs create mode 100644 Pages/FoundationsPage.xaml create mode 100644 Pages/FoundationsPage.xaml.cs create mode 100644 Pages/IGEsPage.xaml create mode 100644 Pages/IGEsPage.xaml.cs create mode 100644 Pages/MainPage.xaml create mode 100644 Pages/MainPage.xaml.cs create mode 100644 Pages/PlayGroundsPage.xaml create mode 100644 Pages/PlayGroundsPage.xaml.cs create mode 100644 Pages/ResultsPage.cs create mode 100644 Pages/ResultsPage.xaml create mode 100644 Pages/StructuresPage.xaml create mode 100644 Pages/StructuresPage.xaml.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 Properties/Resources.Designer.cs create mode 100644 Properties/Resources.resx create mode 100644 Properties/Settings.Designer.cs create mode 100644 Properties/Settings.settings create mode 100644 Resources/ShemaFound.png create mode 100644 Resources/ShemaLoads.png create mode 100644 Resources/business-color_books_icon-icons.com_53474.ico create mode 100644 Resources/tabl_5_5.csv create mode 100644 Resources/Аннотация 2019-06-14 145047.png create mode 100644 Resources/ИГЭ.xlsx create mode 100644 Settings.cs create mode 100644 TestWindow.xaml create mode 100644 TestWindow.xaml.cs create mode 100644 VM/BoresVM.cs create mode 100644 VM/CalculationsVM.cs create mode 100644 VM/DrawingVM.cs create mode 100644 VM/FoundLoadsVM.cs create mode 100644 VM/FoundationsVM.cs create mode 100644 VM/HelpsVM.cs create mode 100644 VM/IGEsVM.cs create mode 100644 VM/LayersVM.cs create mode 100644 VM/PlanningVM.cs create mode 100644 VM/PlayGroundVM.cs create mode 100644 VM/RelayCommand.cs create mode 100644 VM/StructuresVM.cs create mode 100644 VM/UnitsViewModel .cs create mode 100644 VM/ViewModel.cs create mode 100644 Windows/AlertWindow.xaml create mode 100644 Windows/AlertWindow.xaml.cs create mode 100644 Windows/CanwasWindow.xaml create mode 100644 Windows/CanwasWindow.xaml.cs create mode 100644 Windows/FoundPropWindow.xaml create mode 100644 Windows/FoundPropWindow.xaml.cs create mode 100644 Windows/ImageWindow.xaml create mode 100644 Windows/ImageWindow.xaml.cs create mode 100644 packages.config diff --git a/App.config b/App.config new file mode 100644 index 0000000..ad911fa --- /dev/null +++ b/App.config @@ -0,0 +1,26 @@ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/App.xaml b/App.xaml new file mode 100644 index 0000000..286dcea --- /dev/null +++ b/App.xaml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/App.xaml.cs b/App.xaml.cs new file mode 100644 index 0000000..4021309 --- /dev/null +++ b/App.xaml.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace GroundOrganizer +{ + /// + /// Логика взаимодействия для App.xaml + /// + public partial class App : Application + { + //public static ViewModel vm; + //public App() + //{ + // InitializeComponent(); + // vm = new ViewModel(); + //} + } +} + diff --git a/BL/Bore.cs b/BL/Bore.cs new file mode 100644 index 0000000..eb09696 --- /dev/null +++ b/BL/Bore.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + public class Bore + { + /// + /// Порядковый номер скважины + /// + public int Number { get; set; } + /// + /// Имя скважины + /// + public string Name { get; set; } + /// + /// Х-координата распложения скважины + /// + public double X { get; set; } + /// + /// Y-координата распложения скважины + /// + public double Y { get; set; } + /// + /// Абсолютная отметка устья скважины + /// + public double Z { get; set; } + /// + /// Относительная отметка уровня грунтовых вод + /// + public double? WL { get; set; } + /// + /// Превышение глубины сважины в расчетах осадки + /// + public double DZ { get; set; } + /// + /// Массив грунтовых слоев + /// + public ObservableCollection Layers { get; set; } + + public Bore() + { + Layers = new ObservableCollection(); + } + + public void AddLayer(Layer layer) + { + if (Layers == null) Layers = new ObservableCollection(); + Layers.Add(layer); + } + public void AddLayers(ObservableCollection layers) + { + Layers = layers; + } + public void AddLayers(List layers) + { + if (Layers == null) Layers = new ObservableCollection(); + foreach (var item in layers) Layers.Add(item); + } + + public void DeleteLayers() + { + Layers = new ObservableCollection(); + } + + internal string PropsToString() + { + string s = ";"; + return Number + s + Name + s + X + s + Y + s + Z + s + WL + s + DZ; + } + + internal List PropsToList() + { + return new List { Number, Name, X, Y, Z, WL, DZ }; + } + + internal void StringToProps(string line, char separator = ';') + { + string[] src = line.Split(separator); + try + { + Number = Int32.Parse(src[0]); + Name = src[1]; + X = double.Parse(src[2]); + Y = double.Parse(src[3]); + Z = double.Parse(src[4]); + WL = double.Parse(src[5]); + DZ = double.Parse(src[6]); + } + catch + { + return; + } + } + + internal void ListToProps(List src) + { + try + { + Number = (int)(double)src[0]; + Name = (string)src[1]; + X = (double)src[2]; + Y = (double)src[3]; + Z = (double)src[4]; + WL = (double)src[5]; + DZ = (double)src[6]; + } + catch + { + return; + } + } + } +} diff --git a/BL/DataPair.cs b/BL/DataPair.cs new file mode 100644 index 0000000..7f406e2 --- /dev/null +++ b/BL/DataPair.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ [Serializable] + public struct DataPair + { + public string Описание { get; set; } + public object Параметр { get; set; } + public UnitsForce ForcesUnits { get; set; } + public UnitsStress StressUnits { get; set; } + public UnitsArea AreasUnits { get; set; } + public UnitsLin LenghtsUnits { get; set; } + } + + [Serializable] + public struct DataPairProps + { + public string Описание { get; set; } + public object Параметр { get; set; } + public UnitsList Ед_изм { get; set; } + } +} diff --git a/BL/DataR.cs b/BL/DataR.cs new file mode 100644 index 0000000..3c4f3a3 --- /dev/null +++ b/BL/DataR.cs @@ -0,0 +1,404 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + public struct DataR + { + public string Bore { get; set; } + public string Base { get; set; } + public double R { get; set; } + public double P { get; set; } + public double PmaxX { get; set; } + public double PmaxY { get; set; } + public double GapX { get; set; } + public double GapY { get; set; } + public double CheckP { get; set; } + public double CheckGap { get; set; } + public double YIIu { get; set; } + public double YII { get; set; } + public double FiII { get; set; } + public double CII { get; set; } + public double Yc1 { get; set; } + public double Yc2 { get; set; } + public double My { get; set; } + public double Mq { get; set; } + public double Mc { get; set; } + public double IL { get; set; } + public double Ys { get; set; } + public double Ke { get; set; } + public double Kz { get; set; } + public double K { get; set; } + public double d1 { get; set; } + public double db { get; set; } + public string Ground { get; set; } + public string GroundType { get; set; } + public List FullData { get; private set; } + public List MediumData { get; private set; } + public List SmallData { get; private set; } + + internal void CreateFullData() + { + FullData = new List(); + DataPair dataPair = new DataPair() { Описание = "Фундамент", Параметр = Base }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Скважина", Параметр = Bore }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Расчетное сопротивление", Параметр = R, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Среднее давление под подошвой", Параметр = P, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Максимальное давление под подошвой в направлении длины фундамента", + Параметр = PmaxX, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Максимальное давление под подошвой в направлении ширины фундамента", + Параметр = PmaxY, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффициент использования расчетного сопротивления", Параметр = CheckP }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении длины фундамента", Параметр = GapX}; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении ширины фундамента", Параметр = GapY}; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Максимальный отрыв подошвы", Параметр = CheckGap }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Глубина заложения", Параметр = d1, LenghtsUnits = UnitsLin.м }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Глубина подвала", Параметр = db, LenghtsUnits = UnitsLin.м }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Грунт под подошвой", Параметр = Ground }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Объемный вес (осредненный) грунта выше подошвы", Параметр = YIIu, + AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Объемный вес (осредненный) грунта ниже подошвы", Параметр = YII, + AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Угол внутреннего трения грунта основания (осредненный)", Параметр = FiII }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Удельное сцепление грунта основания (осредненное)", Параметр = CII, + AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Показатель текучести грунта основания ", Параметр = IL }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффициент пористости грунта основания ", Параметр = Ke }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Тип грунта основания согласно таблице 5.4", Параметр = GroundType }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Yc1 согласно таблице 5.4", Параметр = Yc1 }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Yc2 согласно таблице 5.4", Параметр = Yc2 }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт My согласно таблице 5.5", Параметр = My }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Mq согласно таблице 5.5", Параметр = Mq }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Mc согласно таблице 5.5", Параметр = Mc }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Kz", Параметр = Kz }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт K", Параметр = K }; + FullData.Add(dataPair); + + } + internal void CreateMediumData() + { + MediumData = new List(); + DataPair dataPair = new DataPair() { Описание = "Фундамент", Параметр = Base }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Расчетное сопротивление", Параметр = R, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Среднее давление под подошвой", Параметр = P, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении длины фундамента", + Параметр = PmaxX, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении ширины фундамента", + Параметр = PmaxY, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффициент использования расчетного сопротивления", Параметр = CheckP }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении длины фундамента", Параметр = GapX }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении ширины фундамента", Параметр = GapY }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Максимальный отрыв подошвы", Параметр = CheckGap }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Глубина заложения", Параметр = d1, LenghtsUnits = UnitsLin.м }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Глубина подвала", Параметр = db, LenghtsUnits = UnitsLin.м }; + MediumData.Add(dataPair); + //dataPair = new DataPair() { Descriptions = "Грунт под подошвой", DataEntity = Ground }; + //MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Объемный вес (осредненный) грунта выше подошвы", + Параметр = YIIu, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Объемный вес (осредненный) грунта ниже подошвы", + Параметр = YII, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Угол внутреннего трения грунта основания (осредненный)", Параметр = FiII }; + MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Удельное сцепление грунта основания (осредненное)", + Параметр = CII, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + } + internal void CreateSmallData() + { + SmallData = new List(); + DataPair dataPair = new DataPair() { Описание = "Фундамент", Параметр = Base }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Расчетное сопротивление", Параметр = R, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Среднее давление под подошвой", Параметр = P, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + SmallData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении длины фундамента", + Параметр = PmaxX, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + SmallData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении ширины фундамента", + Параметр = PmaxY, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении длины фундамента", Параметр = GapX }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении ширины фундамента", Параметр = GapY }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Максимальный отрыв подошвы", Параметр = CheckGap }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффициент использования расчетного сопротивления", Параметр = CheckP }; + SmallData.Add(dataPair); + } + + internal List FullResults() + { + FullData = new List(); + DataPair dataPair = new DataPair() { Описание = "Фундамент", Параметр = Base }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Скважина", Параметр = Bore }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Расчетное сопротивление", Параметр = R, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Среднее давление под подошвой", Параметр = P, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + FullData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении длины фундамента", + Параметр = PmaxX, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + FullData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении ширины фундамента", + Параметр = PmaxY, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении длины фундамента", Параметр = GapX }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении ширины фундамента", Параметр = GapY }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Максимальный отрыв подошвы", Параметр = CheckGap }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффициент использования расчетного сопротивления", Параметр = CheckP }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Глубина заложения", Параметр = d1, LenghtsUnits = UnitsLin.м }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Глубина подвала", Параметр = db, LenghtsUnits = UnitsLin.м }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Грунт под подошвой", Параметр = Ground }; + FullData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Объемный вес (осредненный) грунта выше подошвы", + Параметр = YIIu, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + FullData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Объемный вес (осредненный) грунта ниже подошвы", + Параметр = YII, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Угол внутреннего трения грунта основания (осредненный)", Параметр = FiII }; + FullData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Удельное сцепление грунта основания (осредненное)", + Параметр = CII, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Показатель текучести грунта основания ", Параметр = IL }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффициент пористости грунта основания ", Параметр = Ke }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Тип грунта основания согласно таблице 5.4", Параметр = GroundType }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Yc1 согласно таблице 5.4", Параметр = Yc1 }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Yc2 согласно таблице 5.4", Параметр = Yc2 }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт My согласно таблице 5.5", Параметр = My }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Mq согласно таблице 5.5", Параметр = Mq }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Mc согласно таблице 5.5", Параметр = Mc }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт Kz", Параметр = Kz }; + FullData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффицинт K", Параметр = K }; + FullData.Add(dataPair); + + return FullData; + } + internal List MediumResults() + { + MediumData = new List(); + DataPair dataPair = new DataPair() { Описание = "Фундамент", Параметр = Base }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Расчетное сопротивление", Параметр = R, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Среднее давление под подошвой", Параметр = P, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении длины фундамента", + Параметр = PmaxX, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении ширины фундамента", + Параметр = PmaxY, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении длины фундамента", Параметр = GapX }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении ширины фундамента", Параметр = GapY }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Максимальный отрыв подошвы", Параметр = CheckGap }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффициент использования расчетного сопротивления", Параметр = CheckP }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Глубина заложения", Параметр = d1, LenghtsUnits = UnitsLin.м }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Глубина подвала", Параметр = db, LenghtsUnits = UnitsLin.м }; + MediumData.Add(dataPair); + //dataPair = new DataPair() { Descriptions = "Грунт под подошвой", DataEntity = Ground }; + //MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Объемный вес (осредненный) грунта выше подошвы", + Параметр = YIIu, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Объемный вес (осредненный) грунта ниже подошвы", + Параметр = YII, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + dataPair = new DataPair() { Описание = "Угол внутреннего трения грунта основания (осредненный)", Параметр = FiII }; + MediumData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Удельное сцепление грунта основания (осредненное)", + Параметр = CII, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + MediumData.Add(dataPair); + + return MediumData; + } + internal List SmallResults() + { + SmallData = new List(); + DataPair dataPair = new DataPair() { Описание = "Фундамент", Параметр = Base }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Расчетное сопротивление", Параметр = R, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Среднее давление под подошвой", Параметр = P, AreasUnits = UnitsArea.м, ForcesUnits = UnitsForce.т }; + SmallData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении длины фундамента", + Параметр = PmaxX, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + SmallData.Add(dataPair); + dataPair = new DataPair() + { + Описание = "Максимальное давление под подошвой в направлении ширины фундамента", + Параметр = PmaxY, + AreasUnits = UnitsArea.м, + ForcesUnits = UnitsForce.т + }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении длины фундамента", Параметр = GapX }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Отрыв в направлении ширины фундамента", Параметр = GapY }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Максимальный отрыв подошвы", Параметр = CheckGap }; + SmallData.Add(dataPair); + dataPair = new DataPair() { Описание = "Коэффициент использования расчетного сопротивления", Параметр = CheckP }; + SmallData.Add(dataPair); + + return SmallData; + } + } +} diff --git a/BL/DataS.cs b/BL/DataS.cs new file mode 100644 index 0000000..2ab4c29 --- /dev/null +++ b/BL/DataS.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + public struct DataS + { + public string Bore { get; set; } + public string Base { get; set; } + public double Sp { get; set; } + public double Sr { get; set; } + public double p { get; set; } + public double Hc { get; set; } + public double Hmin { get; set; } + public double YIIu { get; set; } + public List Z { get; set; } + public List Alfa { get; set; } + public List sig_zp { get; set; } + public List sig_zy { get; set; } + public List sig_zg { get; set; } + public List E { get; set; } + public List N { get; set; } + } +} diff --git a/BL/Enums.cs b/BL/Enums.cs new file mode 100644 index 0000000..fb1b307 --- /dev/null +++ b/BL/Enums.cs @@ -0,0 +1,18 @@ +namespace GroundOrganizer +{ + public enum TypeFound { Прямоугольный, Ленточный, Круглый } + public enum PointFound { Центр, Угол} + public enum TypeFlexStructure { Гибкая, Жесткая } + public enum ResKey { eps_b_max, eps_b_min, sig_b_max, sig_b_min, eps_bult, eps_s_max, eps_s_min, sig_s_max, sig_s_min, asel, kf, Mxult, Myult, Nult, Mxcrc, Mycrc, num_itr, rep, info } + public enum SecShape { прямоугольник, круг, кольцо, тавр_с_полками_вверху, тавр_с_полками_внизу, двутавр, короб, пользовательское } + public enum ElementType { стержень, пластина } + public enum CharMat { C, CL, N, NL } + public enum LongForces { кратковременное, длительное } + public enum Vlajnost { Ниже_40, От_40_до_75, Выше_75 } + public enum Orientation { вертикальная, горизонтальная } + public enum ClassBet { B10, B15, B20, B25, B30, B35, B40, B45, B50, B55, B60 } + public enum ClassArm { A240, A400, A500, B500, A600, A800, A1000, Bp500, Bp1200 } + public enum TypeDiagramm { трехлинейная, двухлинейная } + public enum TypeLayer { Au, As1, As2, As3, As4, одиночный, радиальный, линейный, AuAs } + public enum ParamsLayer { AsDs, AsNd, DsNd } +} \ No newline at end of file diff --git a/BL/FoundLoad.cs b/BL/FoundLoad.cs new file mode 100644 index 0000000..e5a9361 --- /dev/null +++ b/BL/FoundLoad.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + public class FoundLoad + { + public double NC { get; set; } + public double MxC { get; set; } + public double MyC { get; set; } + public double QyC { get; set; } + public double QxC { get; set; } + + + public double N { get; set; } + public double Mx { get; set; } + public double My { get; set; } + public double Qy { get; set; } + public double Qx { get; set; } + public double q { get; set; } + + public int Number { get; set; } + + public bool InFoot { get; set; } + + public UnitsForce UnitsF { get; set; } + public UnitsLin UnitsL { get; set; } + + internal string PropsToString() + { + string s = ";"; + return Number + s + N + s + Mx + s + My + s + Qx + s + Qy + s + q; + } + + internal List PropsToList() + { + return new List { Number, N, Mx, My, Qx, Qy, q, InFoot }; + } + + internal void StringToProps(string line, char separator = ';') + { + string[] src = line.Split(separator); + try + { + Number = Int32.Parse(src[0]); + N = double.Parse(src[1]); + Mx = double.Parse(src[2]); + My = double.Parse(src[3]); + Qx = double.Parse(src[4]); + Qy = double.Parse(src[5]); + q = double.Parse(src[6]); + } + catch + { + return; + } + } + + internal void ListToProps(List src) + { + try + { + Number = (int)(double)src[0]; + N = (double)src[1]; + Mx = (double)src[2]; + My = (double)src[3]; + Qx = (double)src[4]; + Qy = (double)src[5]; + q = (double)src[6]; + InFoot = (bool)src[7]; + } + catch + { + return; + } + } + } +} diff --git a/BL/Foundation.cs b/BL/Foundation.cs new file mode 100644 index 0000000..1fe6ade --- /dev/null +++ b/BL/Foundation.cs @@ -0,0 +1,920 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Geo; +using TriangleNet; +using TriangleNet.Geometry; +using TriangleNet.Meshing; +using TriangleNet.Tools; + +namespace GroundOrganizer +{ + [Serializable] + public class Foundation + { + public int Number { get; set; } + public string Name { get; set; } + public TypeFound Type { get; set; } + public bool Basement { get; set; } + public double B { get; set; } + public double L { get; set; } + public double Db { get; set; } + public double D1 { get; set; } + public double H { get; set; } + public double AlfaDeg { get; set; } + public double Hs { get; set; } + public double Hcf { get; set; } + public double Ycf { get; set; } + public double X { get; set; } + public double Y { get; set; } + /// + /// Относительная отметка подошвы фундамента + /// + public double FL { get; set; } + /// + /// Абсолютная отметка планировки в центральной точке фундамента + /// + public double DL { get; set; } + /// + /// Абсолютная отметка естественного рельефа в центральной точке фундамента + /// + public double NL { get; set; } + public ObservableCollection Loads { get; set; } + public UnitsForce UnitsF { get; set; } + public UnitsLin UnitsL { get; set; } + public Quadrangle Contour { get; set; } + + public List FullResults { get; private set; } + public List FullProps { get; private set; } + public List MediumResults { get; private set; } + public List MediumProps { get; private set; } + public List SmallResults{ get; private set; } + public List SmallProps{ get; private set; } + + public Foundation() + { + Loads = new ObservableCollection(); + Type = TypeFound.Прямоугольный; + UnitsF = UnitsForce.т; + UnitsL = UnitsLin.м; + Ycf = 2.2; + FullResults = new List(); + MediumResults = new List(); + SmallResults = new List(); + } + + public Foundation(Quadrangle cntr) + { + if (cntr.Units == UnitsLin.см) + { + Contour.Vertex1 = cntr.Vertex1 * 0.01; + Contour.Vertex2 = cntr.Vertex2 * 0.01; + Contour.Vertex3 = cntr.Vertex3 * 0.01; + Contour.Vertex4 = cntr.Vertex4 * 0.01; + } + if (cntr.Units == UnitsLin.мм) + { + Contour.Vertex1 = cntr.Vertex1 * 0.001; + Contour.Vertex2 = cntr.Vertex2 * 0.001; + Contour.Vertex3 = cntr.Vertex3 * 0.001; + Contour.Vertex4 = cntr.Vertex4 * 0.001; + } + if(cntr.Units == UnitsLin.м) Contour = cntr; + + X = Math.Round(Contour.Centroid.X, 3); + Y = Math.Round(Contour.Centroid.Y, 3); + + IOrderedEnumerable selected = from l in Contour.Segments // определяем каждый объект как + orderby l.Length // упорядочиваем по возрастанию + select l; // выбираем объект + + AlfaDeg = Math.Round(RadToDeg(Math.Acos(selected.First().Directive.Vx / selected.First().Length)), 3); + B = Math.Round(selected.First().Length, 3); + L = Math.Round(selected.Last().Length, 3); + + Loads = new ObservableCollection(); + Type = TypeFound.Прямоугольный; + UnitsF = UnitsForce.т; + UnitsL = UnitsLin.м; + Ycf = 2.2; + FullResults = new List(); + MediumResults = new List(); + SmallResults = new List(); + } + + internal void CreateFullPropsList() + { + FullProps = new List(); + DataPairProps dataPair = new DataPairProps() { Описание = "Номер", Параметр = Number }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Марка", Параметр = Name }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Ширина", Параметр = B, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Длина", Параметр = L, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Высота", Параметр = H, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Отметка подошвы", Параметр = FL, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Глубина заложения", Параметр = D1, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Отметка планировки", Параметр = DL }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Отметка рельефа", Параметр = NL }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Наличие подвала", Параметр = Basement }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Глубина подвала", Параметр = Db, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "h_s", Параметр = Hs, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "h_cf", Параметр = Hcf, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Ycf, т/м3", Параметр = Ycf }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Х", Параметр = X, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Y", Параметр = Y, Ед_изм = UnitsList.м }; + FullProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Поворот", Параметр = AlfaDeg, Ед_изм= UnitsList.градус }; + FullProps.Add(dataPair); + + } + + internal void CreateMediumPropsList() + { + MediumProps = new List(); + DataPairProps dataPair = new DataPairProps() { Описание = "Номер", Параметр = Number }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Марка", Параметр = Name }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Ширина", Параметр = B, Ед_изм = UnitsList.м }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Длина", Параметр = L, Ед_изм = UnitsList.м }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Высота", Параметр = H, Ед_изм = UnitsList.м }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Отметка подошвы", Параметр = FL, Ед_изм = UnitsList.м }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Глубина заложения", Параметр = D1, Ед_изм = UnitsList.м }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Отметка планировки", Параметр = DL }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Отметка рельефа", Параметр = NL }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Наличие подвала", Параметр = Basement }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Глубина подвала", Параметр = Db, Ед_изм = UnitsList.м }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "h_s", Параметр = Hs, Ед_изм = UnitsList.м }; + MediumProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "h_cf", Параметр = Hcf, Ед_изм = UnitsList.м }; + MediumProps.Add(dataPair); + } + + internal void CreateSmallPropsList() + { + SmallProps = new List(); + DataPairProps dataPair = new DataPairProps() { Описание = "Номер", Параметр = Number }; + SmallProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Марка", Параметр = Name }; + SmallProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Ширина b", Параметр = B, Ед_изм = UnitsList.м }; + SmallProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Длина l", Параметр = L, Ед_изм = UnitsList.м }; + SmallProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Высота h", Параметр = H, Ед_изм = UnitsList.м }; + SmallProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Отметка подошвы FL", Параметр = FL, Ед_изм = UnitsList.м }; + SmallProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Глубина заложения d_1", Параметр = D1, Ед_изм = UnitsList.м }; + SmallProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Отметка планировки DL", Параметр = DL, Ед_изм = UnitsList.м }; + SmallProps.Add(dataPair); + dataPair = new DataPairProps() { Описание = "Отметка рельефа NL", Параметр = NL, Ед_изм = UnitsList.м }; + SmallProps.Add(dataPair); + } + + public DataS Sp(Bore bore, FoundLoad load, double kHc = 0.5, PointFound ptFond = PointFound.Центр) + { + DataS res = new DataS(); + List downFS = DownFS(bore); + List n = res.N; + n = new List(); + + foreach (Layer item in downFS) + { + n.Add(Math.Ceiling(item.H / (0.4 * B))); + } + + List layers = new List(); + for (int i = 0; i < n.Count; i++) + { + double z = downFS[i].Up; + double dlt = downFS[i].H / n[i]; + while (downFS[i].Down > z) + { + z += dlt; + Layer lay = downFS[i].Clone(); + lay.Down = z; + lay.H = dlt; + lay.Up = z - dlt; + layers.Add(lay); + } + } + + double FL; + if (Basement) FL = Hs + Hcf + Db; + else FL = D1; + + res.Z = new List() { 0 }; + foreach (Layer item in layers) + { + res.Z.Add(item.Up + 0.5 * item.H - FL); + } + + res.Alfa = TablesInterolator.Table_5_8(res.Z, B, L, Type); + + List upF = UpF(bore); + double roh = 0; + double h = 0; + if (upF.Count > 0) + { + foreach (Layer item in upF) + { + roh += item.H * item.IGE.RoII; + h += item.H; + } + } + res.YIIu = Math.Round(roh / h, 3); + + double sig_zg0 = res.YIIu * FL; + double p = load.N / (B * L) + load.q + 2 * FL; + + res.sig_zy = new List(); + res.sig_zp = new List(); + for (int i = 0; i < res.Z.Count; i++) + { + res.sig_zp.Add((double)res.Alfa[i] * p); + res.sig_zy.Add((double)res.Alfa[i] * sig_zg0); + } + + res.sig_zg = new List { sig_zg0 }; + res.E = new List(); + for (int i = 0; i < layers.Count; i++) + { + res.sig_zg.Add(sig_zg0 + layers[i].IGE.RoII * (res.Z[i + 1] - (layers[i].Up - FL))); + sig_zg0 += layers[i].H * layers[i].IGE.RoII; + res.E.Add(layers[i].IGE.E * 101.972); + } + + sig_zg0 = res.YIIu * FL; + + if (B <= 10) res.Hmin = B / 2; + else if (B > 10 && B <= 60) res.Hmin = 4 + 0.1 * B; + else res.Hmin = 10; + + int j = 0; + for (int i = 0; i < layers.Count; i++) + { + if (res.sig_zp[i] >= kHc * res.sig_zg[i]) + { + res.Hc = res.Z[i]; + } + else + { + j = i; + break; + } + } + + int t = 0; double pt = layers[t].H; + while (pt <= res.Hmin) + { + t++; + pt += layers[t].H; + } + + if (res.Hmin > res.Hc) + { + res.Hc = res.Hmin; + j = t; + } + + if (sig_zg0 >= p) + { + for (int i = 0; i <= j; i++) + { + res.Sp += res.sig_zp[i + 1] * layers[i].H / (5 * res.E[i]); + } + res.Sp *= 0.8; + } + else + { + for (int i = 0; i <= j; i++) + { + res.Sp += (res.sig_zp[i + 1] - res.sig_zy[i + 1]) * layers[i].H / res.E[i] + res.sig_zy[i + 1] * layers[i].H / (5 * res.E[i]); + } + res.Sp *= 0.8; + } + + res.Sp = Math.Round(res.Sp * 100, 1); + res.p = Math.Round(p, 2); + + return res; + } + public DataR P(Bore bore, TypeFlexStructure ts, double ls, double hs, double k = 1) + { + DataR dataR = R(bore, ts, ls, hs, k); + dataR.Base = Name; + dataR.Bore = "Скв." + bore.Name; + + if (Loads == null || Loads.Count == 0) + { + FullResults = dataR.FullResults(); + MediumResults = dataR.MediumResults(); + SmallResults = dataR.SmallResults(); + return dataR; + } + List P = new List(Loads.Count); + List PmaxX = new List(Loads.Count); + List PmaxY = new List(Loads.Count); + List chP = new List(Loads.Count); + List GapX = new List(Loads.Count); + List GapY = new List(Loads.Count); + List chGap = new List(Loads.Count); + foreach (FoundLoad item in Loads) + { + P.Add(item.N / (B * L) + item.q + 2 * D1); + double ex = (Math.Abs(item.Mx) / (item.N + 2 * D1 * L * B)) / L; + double wx = (B * L * L * L) / 6; + double pmaxx; + if (ex <= (1.0 / 6)) {pmaxx= item.N / (B * L) + 2 * D1 + Math.Abs(item.Mx) / wx; PmaxX.Add(pmaxx); GapX.Add(0); ex = 0; } + else + { + double C0x = 0.5 * L - item.Mx / (item.N + 2 * D1 * L * B); + pmaxx = 2 * (item.N + 2 * D1 * L * B) / (3 * B * C0x); + PmaxX.Add(pmaxx); + GapX.Add(ex); + } + double ey = (Math.Abs(item.My) / (item.N + 2 * D1 * L * B)) / B; + double wy = (L * B * B * B) / 6; + double pmaxy; + if (ey <= (1.0 / 6)) {pmaxy= item.N / (B * L) + 2 * D1 + Math.Abs(item.My) / wy; PmaxY.Add(pmaxy); GapY.Add(0); ey = 0; } + else + { + double C0y = 0.5 * B - item.My / (item.N + 2 * D1 * L * B); + pmaxy = 2 * (item.N + 2 * D1 * L * B) / (3 * L * C0y); + PmaxY.Add(pmaxy); + GapY.Add(ey); + } + chGap.Add(Math.Max(ex, ey)); + List chp = new List { (item.N / (B * L) + item.q + 2 * D1) / dataR.R, pmaxx / (1.2 * dataR.R), pmaxy / (1.2 * dataR.R) }; + chP.Add(chp.Max()); + } + dataR.P = Math.Round(P.Max(), 3); + dataR.PmaxX = Math.Round(PmaxX.Max(), 3); + dataR.PmaxY = Math.Round(PmaxY.Max(), 3); + dataR.CheckP = Math.Round(chP.Max(), 3); + dataR.CheckGap = Math.Round(chGap.Max(), 3); + dataR.GapX = Math.Round(GapX.Max(), 3); + dataR.GapY = Math.Round(GapY.Max(), 3); + + FullResults = dataR.FullResults(); + MediumResults = dataR.MediumResults(); + SmallResults = dataR.SmallResults(); + + return dataR; + } + public ObservableCollection P(ObservableCollection bores, TypeFlexStructure ts, double ls, double hs, double k = 1) + { + ObservableCollection res = new ObservableCollection(); + foreach (Bore bore in bores) + { + DataR dataR = R(bore, ts, ls, hs, k); + dataR.Base = Name; + dataR.Bore = "Скв." + bore.Name; + + if (Loads == null || Loads.Count == 0) + { + dataR.CreateFullData(); + dataR.CreateMediumData(); + dataR.CreateSmallData(); + res.Add(dataR); + continue; + } + List P = new List(Loads.Count); + List PmaxX = new List(Loads.Count); + List PmaxY = new List(Loads.Count); + List chP = new List(Loads.Count); + List GapX = new List(Loads.Count); + List GapY = new List(Loads.Count); + List chGap = new List(Loads.Count); + foreach (FoundLoad item in Loads) + { + P.Add(item.N / (B * L) + item.q + 2 * D1); + double ex = (item.Mx / (item.N + 2 * D1 * L * B)) / L; + double wx = (B * L * L * L) / 6; + double pmaxx; + if (ex <= 1 / 6) { pmaxx = item.N / (B * L) + 2 * D1 + Math.Abs(item.Mx) / wx; PmaxX.Add(pmaxx); GapX.Add(0); ex = 0; } + else + { + double C0x = 0.5 * L - item.Mx / (item.N + 2 * D1 * L * B); + pmaxx = 2 * (item.N + 2 * D1 * L * B) / (3 * B * C0x); + PmaxX.Add(pmaxx); + GapX.Add(ex); + } + double ey = (item.My / (item.N + 2 * D1 * L * B)) / B; + double wy = (L * B * B * B) / 6; + double pmaxy; + if (ey <= 1 / 6) { pmaxy = item.N / (B * L) + 2 * D1 + Math.Abs(item.My) / wy; PmaxY.Add(pmaxy); GapY.Add(0); ey = 0; } + else + { + double C0y = 0.5 * B - item.My / (item.N + 2 * D1 * L * B); + pmaxy = 2 * (item.N + 2 * D1 * L * B) / (3 * L * C0y); + PmaxY.Add(pmaxy); + GapY.Add(ey); + } + chGap.Add(Math.Max(ex, ey)); + List chp = new List { (item.N / (B * L) + item.q + 2 * D1) / dataR.R, pmaxx / (1.2 * dataR.R), pmaxy / (1.2 * dataR.R) }; + chP.Add(chp.Max()); + } + dataR.P = Math.Round(P.Max(), 3); + dataR.PmaxX = Math.Round(PmaxX.Max(), 3); + dataR.PmaxY = Math.Round(PmaxY.Max(), 3); + dataR.CheckP = Math.Round(chP.Max(), 3); + dataR.CheckGap = Math.Round(chGap.Max(), 3); + dataR.GapX = Math.Round(GapX.Max(), 3); + dataR.GapY = Math.Round(GapY.Max(), 3); + + dataR.CreateFullData(); + dataR.CreateMediumData(); + dataR.CreateSmallData(); + + res.Add(dataR); + } + + return res; + } + private DataR R(Bore bore, TypeFlexStructure ts, double ls, double hs, double k = 1) + { + DataR res = new DataR(); + List upF = UpF(bore); + List downF = DownF(bore); + double roh = 0; + double h = 0; + if (upF.Count > 0) + { + foreach (Layer item in upF) + { + roh += item.H * item.IGE.RoII; + h += item.H; + } + } + res.YIIu = Math.Round(roh / h, 3); + + double fih = 0; + double ch = 0; + roh = 0; + h = 0; + if (downF.Count > 0) + { + foreach (Layer item in downF) + { + fih += item.H * item.IGE.FiII; + ch += item.H * item.IGE.CII * 100; + roh += item.H * item.IGE.RoII; + h += item.H; + } + } + res.YII = Math.Round(roh / h, 3); + res.FiII = Math.Round(fih / h); + res.CII = Math.Round(ch / h, 3); + res.IL = downF[0].IGE.IL; + res.Ke = downF[0].IGE.Ke; + res.Ys = downF[0].IGE.Ys; + res.Ground = "ИГЭ " + downF[0].IGE.NumIGE + " " + downF[0].IGE.Description; + res.GroundType = downF[0].IGE.GroundType; + res.Yc1 = TablesInterolator.Yc1(res.GroundType); + res.Yc2 = TablesInterolator.Yc2(res.GroundType, ts, ls, hs); + double[] MyMqMc = TablesInterolator.My_Mq_Mc(res.FiII); + res.My = MyMqMc[0]; + res.Mq = MyMqMc[1]; + res.Mc = MyMqMc[2]; + res.K = k; + + if (B < 10) res.Kz = 1; + else res.Kz = 8 / B + 0.2; + + if (Basement) res.d1 = Math.Round(Hs + Hcf * (Ycf / res.YIIu), 3); + else res.d1 = D1; + + if (Basement && Db > 2) res.db = 2; + else if (Basement && Db <= 2) res.db = Db; + else res.db = 0; + + res.R = res.Yc1 * res.Yc2 * (res.My * res.Kz * B * res.YII + res.Mq * res.d1 * res.YIIu + (res.Mq - 1) * res.db * res.YIIu + res.Mc * res.CII) / k; + res.R = Math.Round(res.R, 2); + //res.GroundType = ""; + + return res; + } + private List UpF(Bore bore) + { + List res = new List(); + double d; + if (Basement) d = Hs + Hcf + Db; + else d = D1; + + double FL; + FL = d; + + Bore boreW = BoreW(bore); + if (boreW.Layers.Count == 0) return res; + foreach (Layer item in boreW.Layers) + { + if (item.Up > FL) break; + res.Add(item.Clone()); + } + res[res.Count - 1].Down = FL; + res[res.Count - 1].H = res[res.Count - 1].Down - res[res.Count - 1].Up; + + return res; + } + private List DownF(Bore bore) + { + List res = new List(); + double d, z; + if (Basement) d = Hs + Hcf + Db; + else d = D1; + + if (B < 10) z = 0.5 * B; + else z = 4 + 0.1 * B; + + double FL, ZL; + FL = d; + ZL = d + z; + + Bore boreW = BoreW(bore); + if (boreW.Layers.Count == 0) return res; + foreach (Layer item in boreW.Layers) + { + if (item.Down > FL) res.Add(item.Clone()); + if (item.Down >= ZL) break; + } + res[0].Up = FL; + res[0].H = res[0].Down - res[0].Up; + res[res.Count - 1].Down = ZL; + res[res.Count - 1].H = res[res.Count - 1].Down - res[res.Count - 1].Up; + return res; + } + private List UpW(Bore bore) + { + List res = new List(); + foreach (Layer item in bore.Layers) + { + if (item.Up > bore.WL) break; + res.Add(item.Clone()); + } + if (res.Count > 0) + { + res[res.Count - 1].Down = (double)bore.WL; + res[res.Count - 1].H = res[res.Count - 1].Down - res[res.Count - 1].Up; + } + return res; + } + private List DownW(Bore bore) + { + List layers = new List(bore.Layers.Reverse()); + List res = new List(); + foreach (Layer item in layers) + { + if (item.Down <= bore.WL) break; + if (item.IGE.W) item.IGE.RoII = (item.IGE.Ys - 1) / (1 + item.IGE.Ke); + res.Add(item.Clone()); + } + if (res.Count > 0) + { + res.Reverse(); + res[0].Up = (double)bore.WL; + res[0].H = res[0].Down - res[0].Up; + } + return res; + } + private List DownFS(Bore bore) + { + List res = new List(); + double FL; + + if (Basement) FL = Hs + Hcf + Db; + else FL = D1; + + Bore boreW = BoreW(bore); + if (boreW.Layers.Count == 0) return res; + + foreach (Layer item in boreW.Layers.Reverse()) + { + if (item.Down < FL) break; + res.Add(item.Clone()); + } + + if (res.Count > 0) res.Reverse(); + res[0].Up = FL; + res[0].H = res[0].Down - res[0].Up; + + return res; + } + private Bore BoreW(Bore bore) + { + Bore res = new Bore + { + Name = bore.Name, + Number = bore.Number, + WL = bore.WL, + X = bore.X, + Y = bore.Y, + Z = bore.Z + }; + List downW = DownW(bore); + List layers = new List(UpW(bore)); + if (downW.Count > 0) layers.AddRange(downW); + if (layers.Count > 0) + { + res.Layers = new ObservableCollection(layers); + res.Layers[res.Layers.Count - 1].Down = res.Layers[res.Layers.Count - 1].Down + bore.DZ; + res.Layers[res.Layers.Count - 1].H = res.Layers[res.Layers.Count - 1].H + bore.DZ; + res.Layers[res.Layers.Count - 1].Z = res.Layers[res.Layers.Count - 1].Z - bore.DZ; + return res; + } + else + { + bore.Layers[bore.Layers.Count - 1].Down = bore.Layers[bore.Layers.Count - 1].Down + bore.DZ; + bore.Layers[bore.Layers.Count - 1].H = bore.Layers[bore.Layers.Count - 1].H + bore.DZ; + bore.Layers[bore.Layers.Count - 1].Z = bore.Layers[bore.Layers.Count - 1].Z - bore.DZ; + return bore; + } + } + + internal void CalcDL(Structure str) + { + if (str == null || str.RedPlanning == null || str.RedPlanning.Count == 0) return; + + List vrtxs = new List(); + Vertex vrtx; + int i = 1; + foreach (PlanningVertex item in str.RedPlanning) + { + vrtx = new Vertex(item.X, item.Y, item.Number, 2); + vrtx.Attributes[0] = item.Red; + vrtx.Attributes[1] = item.Black; + vrtxs.Add(vrtx); + i++; + } + + Contour cnt = new Contour(vrtxs); + TriangleNet.Geometry.Polygon polygon = new TriangleNet.Geometry.Polygon(); + polygon.Add(cnt); + GenericMesher mesher = new GenericMesher(); + ConstraintOptions constraint = new ConstraintOptions(); + constraint.Convex = true; + Mesh meshPlanning = (Mesh)mesher.Triangulate(polygon, constraint); + TriangleQuadTree meshTree = new TriangleQuadTree(meshPlanning); + TriangleNet.Topology.Triangle trgl = (TriangleNet.Topology.Triangle)meshTree.Query(X, Y); + if (trgl == null) + { + Dictionary valuePairs = new Dictionary(); + Line2d ln; + foreach (Vertex item in meshPlanning.Vertices) + { + ln = new Line2d(new Point2d(X, Y), new Point2d(item.X, item.Y)); + valuePairs.Add(item, ln.Length); + } + IOrderedEnumerable> selected = from v in valuePairs // определяем каждый объект как + orderby v.Value // упорядочиваем по возрастанию + select v; // выбираем объект + List> lst = selected.ToList(); + foreach (TriangleNet.Topology.Triangle item in meshPlanning.Triangles) + { + if (item.Contains(lst[0].Key) && item.Contains(lst[1].Key)) { trgl = item; break; } + } + } + vrtx = new Vertex(X, Y, Number, 2); + Interpolation.InterpolateAttributes(vrtx, trgl, 1); + DL = Math.Round(vrtx.Attributes[0], 3); + } + + internal void CalcDL(Mesh planningMesh) + { + if (planningMesh == null) return; + + Vertex vrtx; + TriangleQuadTree meshTree = new TriangleQuadTree(planningMesh); + TriangleNet.Topology.Triangle trgl = (TriangleNet.Topology.Triangle)meshTree.Query(X, Y); + if (trgl == null) + { + Dictionary valuePairs = new Dictionary(); + Line2d ln; + foreach (Vertex item in planningMesh.Vertices) + { + ln = new Line2d(new Point2d(X, Y), new Point2d(item.X, item.Y)); + valuePairs.Add(item, ln.Length); + } + IOrderedEnumerable> selected = from v in valuePairs // определяем каждый объект как + orderby v.Value // упорядочиваем по возрастанию + select v; // выбираем объект + List> lst = selected.ToList(); + foreach (TriangleNet.Topology.Triangle item in planningMesh.Triangles) + { + if (item.Contains(lst[0].Key) && item.Contains(lst[1].Key)) { trgl = item; break; } + } + } + vrtx = new Vertex(X, Y, Number, 2); + Interpolation.InterpolateAttributes(vrtx, trgl, 1); + DL = Math.Round(vrtx.Attributes[0], 3); + } + + internal void CalcNL(Mesh blackMesh) + { + if (blackMesh == null) return; + + Vertex vrtx; + TriangleQuadTree meshTree = new TriangleQuadTree(blackMesh); + TriangleNet.Topology.Triangle trgl = (TriangleNet.Topology.Triangle)meshTree.Query(X, Y); + if (trgl == null) + { + Dictionary valuePairs = new Dictionary(); + Line2d ln; + foreach (Vertex item in blackMesh.Vertices) + { + ln = new Line2d(new Point2d(X, Y), new Point2d(item.X, item.Y)); + valuePairs.Add(item, ln.Length); + } + IOrderedEnumerable> selected = from v in valuePairs // определяем каждый объект как + orderby v.Value // упорядочиваем по возрастанию + select v; // выбираем объект + List> lst = selected.ToList(); + foreach (TriangleNet.Topology.Triangle item in blackMesh.Triangles) + { + if (item.Contains(lst[0].Key) && item.Contains(lst[1].Key)) { trgl = item; break; } + } + } + vrtx = new Vertex(X, Y, Number, 2); + Interpolation.InterpolateAttributes(vrtx, trgl, 1); + NL = Math.Round(vrtx.Attributes[0], 3); + } + + internal void DLtoD1(double nullLevel) + { + double dlt = nullLevel - DL; + D1 = Math.Round(-FL - dlt, 3); + } + + internal void D1toDL(double nullLevel) + { + DL = Math.Round(nullLevel + FL + D1, 3); + } + + internal void D1toFL(double nullLevel) + { + double dlt = nullLevel - DL; + FL = Math.Round(-dlt - D1, 3); + } + + internal void FLtoD1(double nullLevel) + { + double dlt = nullLevel + FL; + D1 = Math.Round(DL - dlt, 3); + } + + internal string PropsToString() + { + string s = ";"; + return Number + s + Name + s + (int)Type + s + Basement + s + B + s + L + s + H + s + Db + s + D1 + s + Hs + s + Hcf + s + Ycf + s + X + s + Y + s + FL + + s + DL + s + NL + s + AlfaDeg; + } + + internal List PropsToList() + { + return new List { Number, Name, (int)Type, Basement, B, L, H, Db, D1, Hs, Hcf, Ycf, X, Y, FL, DL, NL, AlfaDeg }; + } + + internal void StringToProps(string line, char separator = ';') + { + string[] src = line.Split(separator); + try + { + Number = Int32.Parse(src[0]); + Name = src[1]; + Type = (TypeFound)Int32.Parse(src[2]); + Basement = bool.Parse(src[3]); + B = double.Parse(src[4]); + L = double.Parse(src[5]); + H = double.Parse(src[6]); + Db = double.Parse(src[7]); + D1 = double.Parse(src[8]); + Hs = double.Parse(src[9]); + Hcf = double.Parse(src[10]); + Ycf = double.Parse(src[11]); + X = double.Parse(src[12]); + Y = double.Parse(src[13]); + FL = double.Parse(src[14]); + DL = double.Parse(src[15]); + NL = double.Parse(src[16]); + AlfaDeg = double.Parse(src[17]); + } + catch + { + return; + } + } + + internal void ListToProps(List src) + { + try + { + Number = (int)(double)src[0]; + Name = (string)src[1]; + Type = (TypeFound)(int)(double)src[2]; + Basement = (bool)src[3]; + B = (double)src[4]; + L = (double)src[5]; + H = (double)src[6]; + Db = (double)src[7]; + D1 = (double)src[8]; + Hs = (double)src[9]; + Hcf = (double)src[10]; + Ycf = (double)src[11]; + X = (double)src[12]; + Y = (double)src[13]; + FL = (double)src[14]; + DL = (double)src[15]; + NL = (double)src[16]; + AlfaDeg = (double)src[17]; + } + catch + { + return; + } + } + + internal void CalcLevels(Mesh planningMesh, Mesh blackMesh) + { + CalcDL(planningMesh); + CalcNL(blackMesh); + } + + public void CopyProps(IEnumerable founds) + { + foreach (Foundation item in founds) + { + if (this.Equals(item)) continue; + item.Name = Name; + item.B = B; + item.L = L; + item.H = H; + item.FL = FL; + item.DL = DL; + item.D1 = D1; + item.Loads = Loads; + } + } + + internal void CalcContour() + { + if (Type == TypeFound.Круглый) return; + Point2d v1 = new Point2d(-0.5 * B, -0.5 * L); + Point2d v2 = new Point2d(-0.5 * B, 0.5 * L); + Point2d v3 = new Point2d(0.5 * B, 0.5 * L); + Point2d v4 = new Point2d(0.5 * B, -0.5 * L); + double alfa = DegToRad(AlfaDeg); + double x = v1.X; double y = v1.Y; + v1.X = x * Math.Cos(alfa) - y * Math.Sin(alfa) + X; + v1.Y = x * Math.Sin(alfa) + y * Math.Cos(alfa) + Y; + x = v2.X; y = v2.Y; + v2.X = x * Math.Cos(alfa) - y * Math.Sin(alfa) + X; + v2.Y = x * Math.Sin(alfa) + y * Math.Cos(alfa) + Y; + x = v3.X; y = v3.Y; + v3.X = x * Math.Cos(alfa) - y * Math.Sin(alfa) + X; + v3.Y = x * Math.Sin(alfa) + y * Math.Cos(alfa) + Y; + x = v4.X; y = v4.Y; + v4.X = x * Math.Cos(alfa) - y * Math.Sin(alfa) + X; + v4.Y = x * Math.Sin(alfa) + y * Math.Cos(alfa) + Y; + + Contour = new Quadrangle(v1, v2, v3, v4); + } + + private double RadToDeg(double radians) + { + return radians * 180 / Math.PI; + } + + private double DegToRad(double degries) + { + return degries * Math.PI / 180; + } + } +} diff --git a/BL/IGE.cs b/BL/IGE.cs new file mode 100644 index 0000000..89f33ec --- /dev/null +++ b/BL/IGE.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + public class IGE + { + private string groundType; + public int Number { get; set; } + /// + /// Номер иженерно-геологического элемента + /// + public string NumIGE { get; set; } + /// + /// Тип грунта согласно таблицы 5.4 СП 22.13330.2011 + /// + public string GroundType { get => groundType; set { groundType = value; ChangeTypeGroundIdx(); } } + /// + /// Плотность грунта для расчетов по 2-й группе предельных сосотояний + /// + public double RoII { get; set; } + /// + /// Угол внутреннего трения грунта в градусах для расчетов по 2-й группе предельных сосотояний + /// + public double FiII { get; set; } + /// + /// Удельное сцепление для расчетов по 2-й группе предельных сосотояний + /// + public double CII { get; set; } + /// + /// Модуль деформации грунта + /// + public double E { get; set; } + /// + /// Удельный вес частиц (минеральной части) грунта + /// + public double Ys { get; set; } + /// + /// Коэффициент пористости + /// + public double Ke { get; set; } + /// + ///Показатель текучести + /// + public double IL { get; set; } + /// + /// Наличие водонасыщения + /// + public bool W { get; set; } + /// + /// Описание слоя грунта + /// + public string Description { get; set; } + + public int GroundTypeIdx { get; private set; } + + /// + /// Типы грунтов согласно таблицы 5.4 СП 22.13330.2011 + /// + private readonly string[] groundTypes = new string[] + { + "Крупнообломочные с песчаным заполнителем и пески кроме мелких и пылеватых", + "Пески мелкие", + "Пески пылеватые маловлажные", + "Пески пылеватые влажные насыщенные водой", + "Пески рыхлые", + "Глинистые, а также крупнообломочные с глинистым заполнителем при IL<=0.25", + "Глинистые, а также крупнообломочные с глинистым заполнителем при 0.25 PropsToList() + { + return new List { Number, NumIGE, Description, RoII, FiII, CII, E, Ys, Ke, IL, W, GroundType, GroundTypeIdx }; + } + + internal void StringToProps(string line, char separator = ';') + { + string[] src = line.Split(separator); + try + { + Number = Int32.Parse(src[0]); + NumIGE = src[1]; + Description = src[2]; + RoII = double.Parse(src[3]); + FiII = double.Parse(src[4]); + CII = double.Parse(src[5]); + E = double.Parse(src[6]); + Ys = double.Parse(src[7]); + Ke = double.Parse(src[8]); + IL = double.Parse(src[9]); + W = bool.Parse(src[10]); + GroundType = src[11]; + } + catch + { + return; + } + } + internal void ListToProps(List src) + { + try + { + Number = (int)(double)src[0]; + NumIGE = (string)src[1]; + Description = (string)src[2]; + RoII = (double)src[3]; + FiII = (double)src[4]; + CII = (double)src[5]; + E = (double)src[6]; + Ys = (double)src[7]; + Ke = (double)src[8]; + IL = (double)src[9]; + W = (bool)src[10]; + GroundType = (string)src[11]; + } + catch + { + return; + } + } + } +} diff --git a/BL/Layer.cs b/BL/Layer.cs new file mode 100644 index 0000000..d9153d0 --- /dev/null +++ b/BL/Layer.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + public class Layer + { + public int Number { get; set; } + + public string NumIGE { get; set; } + public IGE IGE { get; set; } + /// + ///Относительная отметка верхней границы слоя относительно устья скважины + /// + public double Up { get; set; } + /// + ///Относительная отметка нижней границы слоя относительно устья скважины + /// + public double Down { get; set; } + /// + ///Мощность слоя + /// + public double H { get; set; } + /// + ///Абсолютная отметка подошвы слоя + /// + public double Z { get; set; } + /// + /// Описание слоя грунта + /// + public string Description { get; set; } + + public Layer Clone() + { + return new Layer() + { + Number = this.Number, + NumIGE = this.NumIGE, + IGE = this.IGE, + Up = this.Up, + Down = this.Down, + H = this.H, + Z = this.Z, + Description = this.Description + }; + } + + internal string PropsToString() + { + string s = ";"; + return Number + s + NumIGE + s + Down + s + H + s + Z; + } + + internal List PropsToList() + { + return new List { Number, NumIGE, Down, H, Z }; + } + + internal void StringToProps(string line, char separator = ';') + { + string[] src = line.Split(separator); + try + { + Number = Int32.Parse(src[0]); + NumIGE = src[1]; + Down = double.Parse(src[2]); + H = double.Parse(src[3]); + Z = double.Parse(src[4]); + } + catch + { + return; + } + } + + internal void ListToProps(List src) + { + try + { + Number = (int)(double)src[0]; + NumIGE = (string)src[1]; + Down = (double)src[2]; + H = (double)src[3]; + Z = (double)src[4]; + } + catch + { + return; + } + } + } +} diff --git a/BL/PlanningVertex.cs b/BL/PlanningVertex.cs new file mode 100644 index 0000000..4de151b --- /dev/null +++ b/BL/PlanningVertex.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + public class PlanningVertex : Geo.Point3d + { + public int Number { get; set; } + public double Red { get; set; } + public double Black { get; set; } + + internal string PropsToString() + { + string s = ";"; + return Number + s + X + s + Y + s + Red + s + Black; + } + + internal void StringToProps(string line, char separator = ';') + { + string[] src = line.Split(separator); + try + { + Number = Int32.Parse(src[0]); + X = double.Parse(src[1]); + Y = double.Parse(src[2]); + Red = double.Parse(src[3]); + Black = double.Parse(src[4]); + } + catch + { + return; + } + } + } +} diff --git a/BL/PlayGround.cs b/BL/PlayGround.cs new file mode 100644 index 0000000..4c0888a --- /dev/null +++ b/BL/PlayGround.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + public class PlayGround + { + public string Description { get; set; } + public int Number { get; set; } + public string Name { get; set; } + public ObservableCollection IGEs { get; private set; } + public ObservableCollection Bores { get; private set; } + public ObservableCollection Structures { get; private set; } + + public PlayGround() + { + IGEs = new ObservableCollection(); + Bores = new ObservableCollection(); + Structures = new ObservableCollection(); + } + + public void AddIGE(IGE ige) + { + if (IGEs == null) IGEs = new ObservableCollection(); + IGEs.Add(ige); + } + public void AddIGEs(ObservableCollection iges) + { + IGEs = iges; + } + public void AddIGEs(List iges) + { + if (IGEs == null) IGEs = new ObservableCollection(); + foreach (var item in iges) IGEs.Add(item); + } + + public void AddBore(Bore bore) + { + if (Bores == null) Bores = new ObservableCollection(); + Bores.Add(bore); + } + public void AddBores(ObservableCollection bores) + { + Bores = bores; + } + public void AddBores(List bores) + { + if (Bores == null) Bores = new ObservableCollection(); + foreach (var item in bores) Bores.Add(item); + } + + public void DeleteBores() + { + Bores = new ObservableCollection(); + } + + public void DeleteIGEs() + { + IGEs = new ObservableCollection(); + } + + + } +} diff --git a/BL/Structure.cs b/BL/Structure.cs new file mode 100644 index 0000000..7437423 --- /dev/null +++ b/BL/Structure.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + public class Structure + { + public TypeFlexStructure flexStructure { get; set; } + public double L { get; set; } + public double H { get; set; } + public double Null { get; set; } + public int Number { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public ObservableCollection Foundations { get; set; } + public ObservableCollection RedPlanning { get; set; } + public ObservableCollection BlackPlanning { get; set; } + public Structure() + { + Foundations = new ObservableCollection(); + RedPlanning = new ObservableCollection(); + BlackPlanning = new ObservableCollection(); + } + } +} diff --git a/BL/TablesInterolator.cs b/BL/TablesInterolator.cs new file mode 100644 index 0000000..882d9bb --- /dev/null +++ b/BL/TablesInterolator.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Geo; + +namespace GroundOrganizer +{ + public struct My_Mq_Mc + { + public double My; + public double Mq; + public double Mc; + Dictionary table_5_5; + + public My_Mq_Mc(double fi) + { + table_5_5 = new Dictionary + { + {0,new double[]{0,1,3.14}}, + {1,new double[]{0.01,1.06,3.23}}, + {2,new double[]{0.03,1.12,3.32}}, + {3,new double[]{0.04,1.18,3.41}}, + {4,new double[]{0.06,1.25,3.51}}, + {5,new double[]{0.08,1.32,3.61}}, + {6,new double[]{0.1,1.39,3.71}}, + {7,new double[]{0.12,1.47,3.82}}, + {8,new double[]{0.14,1.55,3.93}}, + {9,new double[]{0.16,1.64,4.05}}, + {10,new double[]{0.18,1.73,4.17}}, + {11,new double[]{0.21,1.83,4.29}}, + {12,new double[]{0.23,1.94,4.42}}, + {13,new double[]{0.26,2.05,4.55}}, + {14,new double[]{0.29,2.17,4.69}}, + {15,new double[]{0.32,2.3,4.84}}, + {16,new double[]{0.36,2.43,4.99}}, + {17,new double[]{0.39,2.57,5.15}}, + {18,new double[]{0.43,2.73,5.31}}, + {19,new double[]{0.47,2.89,5.48}}, + {20,new double[]{0.51,3.06,5.66}}, + {21,new double[]{0.56,3.24,5.84}}, + {22,new double[]{0.61,3.44,6.04}}, + {23,new double[]{0.66,3.65,6.24}}, + {24,new double[]{0.72,3.87,6.45}}, + {25,new double[]{0.78,4.11,6.67}}, + {26,new double[]{0.84,4.37,6.9}}, + {27,new double[]{0.91,4.64,7.14}}, + {28,new double[]{0.98,4.93,7.4}}, + {29,new double[]{1.06,5.25,7.67}}, + {30,new double[]{1.15,5.59,7.95}}, + {31,new double[]{1.24,5.95,8.24}}, + {32,new double[]{1.34,6.34,8.55}}, + {33,new double[]{1.44,6.76,8.88}}, + {34,new double[]{1.55,7.22,9.22}}, + {35,new double[]{1.68,7.71,9.58}}, + {36,new double[]{1.81,8.24,9.97}}, + {37,new double[]{1.95,8.81,10.37}}, + {38,new double[]{2.11,9.44,10.8}}, + {39,new double[]{2.28,10.11,11.25}}, + {40,new double[]{2.46,10.85,11.73}}, + {41,new double[]{2.66,11.64,12.24}}, + {42,new double[]{2.88,12.51,12.79}}, + {43,new double[]{3.12,13.46,13.37}}, + {44,new double[]{3.38,14.5,13.98}}, + {45,new double[]{3.66,15.64,14.64}} + }; + My= table_5_5[fi][0]; + Mq = table_5_5[fi][1]; + Mc = table_5_5[fi][2]; + } + } + public class TablesInterolator + { + static readonly Dictionary table_5_5 = new Dictionary + { + {0,new double[]{0,1,3.14}}, + {1,new double[]{0.01,1.06,3.23}}, + {2,new double[]{0.03,1.12,3.32}}, + {3,new double[]{0.04,1.18,3.41}}, + {4,new double[]{0.06,1.25,3.51}}, + {5,new double[]{0.08,1.32,3.61}}, + {6,new double[]{0.1,1.39,3.71}}, + {7,new double[]{0.12,1.47,3.82}}, + {8,new double[]{0.14,1.55,3.93}}, + {9,new double[]{0.16,1.64,4.05}}, + {10,new double[]{0.18,1.73,4.17}}, + {11,new double[]{0.21,1.83,4.29}}, + {12,new double[]{0.23,1.94,4.42}}, + {13,new double[]{0.26,2.05,4.55}}, + {14,new double[]{0.29,2.17,4.69}}, + {15,new double[]{0.32,2.3,4.84}}, + {16,new double[]{0.36,2.43,4.99}}, + {17,new double[]{0.39,2.57,5.15}}, + {18,new double[]{0.43,2.73,5.31}}, + {19,new double[]{0.47,2.89,5.48}}, + {20,new double[]{0.51,3.06,5.66}}, + {21,new double[]{0.56,3.24,5.84}}, + {22,new double[]{0.61,3.44,6.04}}, + {23,new double[]{0.66,3.65,6.24}}, + {24,new double[]{0.72,3.87,6.45}}, + {25,new double[]{0.78,4.11,6.67}}, + {26,new double[]{0.84,4.37,6.9}}, + {27,new double[]{0.91,4.64,7.14}}, + {28,new double[]{0.98,4.93,7.4}}, + {29,new double[]{1.06,5.25,7.67}}, + {30,new double[]{1.15,5.59,7.95}}, + {31,new double[]{1.24,5.95,8.24}}, + {32,new double[]{1.34,6.34,8.55}}, + {33,new double[]{1.44,6.76,8.88}}, + {34,new double[]{1.55,7.22,9.22}}, + {35,new double[]{1.68,7.71,9.58}}, + {36,new double[]{1.81,8.24,9.97}}, + {37,new double[]{1.95,8.81,10.37}}, + {38,new double[]{2.11,9.44,10.8}}, + {39,new double[]{2.28,10.11,11.25}}, + {40,new double[]{2.46,10.85,11.73}}, + {41,new double[]{2.66,11.64,12.24}}, + {42,new double[]{2.88,12.51,12.79}}, + {43,new double[]{3.12,13.46,13.37}}, + {44,new double[]{3.38,14.5,13.98}}, + {45,new double[]{3.66,15.64,14.64}} + }; + static readonly Dictionary table_5_4 = new Dictionary + { + {"Крупнообломочные с песчаным заполнителем и пески кроме мелких и пылеватых", new double[]{1.4, 1.2, 1.4} }, + {"Пески мелкие", new double[]{1.3, 1.1, 1.3} }, + {"Пески пылеватые маловлажные", new double[]{1.25, 1.0, 1.2} }, + {"Пески пылеватые влажные насыщенные водой", new double[]{1.1, 1.0, 1.2} }, + {"Пески рыхлые", new double[]{1.0, 1.0, 1.0} }, + {"Глинистые, а также крупнообломочные с глинистым заполнителем при IL<=0.25", new double[]{1.25, 1.0, 1.1} }, + {"Глинистые, а также крупнообломочные с глинистым заполнителем при 0.25 1.5) return interpolant.Interpolation(L / H); + else if (L / H >= 4) return Yc21; + else return Yc22; + } + + public static double? table_5_8(double z, double b, double l, TypeFound typeFound = TypeFound.Прямоугольный, PointFound ptFound = PointFound.Центр) + { + double nu, ksi; + if (ptFound == PointFound.Центр) ksi = 2 * z / b; + else ksi = z / b; + + if (typeFound == TypeFound.Прямоугольный && l / b < 10) + { + nu = l / b; + return BilinearInterpolation(table_5_8_ksi, table_5_8_nu, table_5_8_R, ksi, nu); + } + if (typeFound == TypeFound.Ленточный || l / b >= 10) + { + return LinearInterpolation(table_5_8_ksi, table_5_8_L, ksi); + } + if (typeFound == TypeFound.Круглый) + { + return LinearInterpolation(table_5_8_ksi, table_5_8_C, ksi); + } + + return null; + } + + public static List Table_5_8(List z, double b, double l, TypeFound typeFound = TypeFound.Прямоугольный, PointFound ptFound = PointFound.Центр) + { + List res = new List(); + double nu, ksi; + + foreach (double item in z) + { + if (ptFound == PointFound.Центр) ksi = 2 * item / b; + else ksi = item / b; + + if (typeFound == TypeFound.Прямоугольный && l / b < 10) + { + nu = l / b; + res.Add(BilinearInterpolation(table_5_8_ksi, table_5_8_nu, table_5_8_R, ksi, nu)); + } + if (typeFound == TypeFound.Ленточный || l / b >= 10) + { + res.Add(LinearInterpolation(table_5_8_ksi, table_5_8_L, ksi)); + } + if (typeFound == TypeFound.Круглый) + { + res.Add(LinearInterpolation(table_5_8_ksi, table_5_8_C, ksi)); + } + } + + return res; + } + + static double? LinearInterpolation(double[] x, double[] y, double xval) + { + double? zval = null; + Line2d interpolant; + int lx = x.Length; + int ly = y.Length; + + if (lx < 2 || ly < 2) return zval; + if (lx != ly) return zval; + + for (int i = 0; i < lx - 1; i++) + { + if (xval >= x[i] && xval < x[i + 1]) + { + interpolant = new Line2d(new Point2d(x[i], y[i]), new Point2d(x[i + 1], y[i + 1])); + return interpolant.Interpolation(xval); + } + + if (xval < x[0]) + { + interpolant = new Line2d(new Point2d(x[0], y[0]), new Point2d(x[1], y[1])); + return interpolant.Interpolation(xval); + } + + if (xval >= x[lx - 1]) + { + interpolant = new Line2d(new Point2d(x[lx - 2], y[lx - 2]), new Point2d(x[lx - 1], y[lx - 1])); + return interpolant.Interpolation(xval); + } + } + + return zval; + } + + static double? BilinearInterpolation(double[] x, double[] y, double[,] z, double xval, double yval) + { + //calculates single point bilinear interpolation + double? zval = null; + Plane interpolant; + int lx = x.Length; + int ly = y.Length; + + if (lx < 2 || ly < 2 || z.Length < 4) return zval; + if (lx !=z.GetLength(0)) return zval; + if (ly !=z.GetLength(1)) return zval; + + for (int i = 0; i < lx - 1; i++) + { + for (int j = 0; j < ly - 1; j++) + { + if (xval >= x[i] && xval < x[i + 1] && yval >= y[j] && yval < y[j + 1]) + { + interpolant = new Plane( + new Point3d(x[i], y[j], z[i, j]), + new Point3d(x[i + 1], y[j], z[i + 1, j]), + new Point3d(x[i], y[j + 1], z[i, j + 1]) + ); + return interpolant.Interpolation(xval, yval); + } + + if (xval >= x[lx-1] && yval >= y[j] && yval < y[j + 1]) + { + interpolant = new Plane( + new Point3d(x[lx - 2], y[j], z[lx - 2, j]), + new Point3d(x[lx - 1], y[j], z[lx - 1, j]), + new Point3d(x[lx - 2], y[j + 1], z[lx - 2, j + 1]) + ); + return interpolant.Interpolation(xval, yval); + } + + if (xval < x[0] && yval >= y[j] && yval < y[j + 1]) + { + interpolant = new Plane( + new Point3d(x[0], y[j], z[0, j]), + new Point3d(x[1], y[j], z[1, j]), + new Point3d(x[0], y[j + 1], z[0, j + 1]) + ); + return interpolant.Interpolation(xval, yval); + } + + if (xval >= x[i] && xval < x[i + 1] && yval >= y[ly-1]) + { + interpolant = new Plane( + new Point3d(x[i], y[ly - 2], z[i, ly - 2]), + new Point3d(x[i + 1], y[ly - 2], z[i + 1, ly - 2]), + new Point3d(x[i], y[ly - 1], z[i, ly - 1]) + ); + return interpolant.Interpolation(xval, yval); + } + + if (xval >= x[i] && xval < x[i + 1] && yval < y[0]) + { + interpolant = new Plane( + new Point3d(x[i], y[0], z[i, 0]), + new Point3d(x[i + 1], y[0], z[i + 1, 0]), + new Point3d(x[i], y[1], z[i, 1]) + ); + return interpolant.Interpolation(xval, yval); + } + + if (xval < x[0] && yval < y[0]) + { + interpolant = new Plane( + new Point3d(x[0], y[0], z[0, 0]), + new Point3d(x[1], y[0], z[1, 0]), + new Point3d(x[0], y[1], z[0, 1]) + ); + return interpolant.Interpolation(xval, yval); + } + + if (xval >= x[lx-1] && yval < y[0]) + { + interpolant = new Plane( + new Point3d(x[lx - 2], y[0], z[lx - 2, 0]), + new Point3d(x[lx - 1], y[0], z[lx - 1, 0]), + new Point3d(x[lx - 2], y[1], z[lx - 2, 1]) + ); + return interpolant.Interpolation(xval, yval); + } + + if (xval < x[0] && yval >= y[ly-1]) + { + interpolant = new Plane( + new Point3d(x[0], y[ly - 2], z[0, ly - 2]), + new Point3d(x[0], y[ly - 1], z[0, ly - 1]), + new Point3d(x[1], y[ly - 1], z[1, ly - 1]) + ); + return interpolant.Interpolation(xval, yval); + } + + if (xval >= x[lx-1] && yval >= y[ly - 1]) + { + interpolant = new Plane( + new Point3d(x[lx - 2], y[ly - 2], z[lx - 2, ly - 2]), + new Point3d(x[lx - 1], y[ly - 2], z[lx - 1, ly - 2]), + new Point3d(x[lx - 2], y[ly - 1], z[lx - 2, ly - 1]) + ); + return interpolant.Interpolation(xval, yval); + } + } + } + return zval; + } + + //double[] BilinearInterpolation(double[] x, double[] y, double[,] z, double[] xvals, double[] yvals) + //{ + // //calculates multiple point bilinear interpolation + // double[] zvals = new double[xvals.Length]; + // for (int i = 0; i < xvals.Length; i++) + // zvals[i] = BilinearInterpolation(x, y, z, xvals[i], yvals[i]); + // return zvals; + //} + } +} diff --git a/BL/ToSerializ.cs b/BL/ToSerializ.cs new file mode 100644 index 0000000..63550f5 --- /dev/null +++ b/BL/ToSerializ.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + [Serializable] + internal class ToSerializ + { + public ObservableCollection PlayGroundList { get; set; } + } +} diff --git a/Dictionary.xaml b/Dictionary.xaml new file mode 100644 index 0000000..5113408 --- /dev/null +++ b/Dictionary.xaml @@ -0,0 +1,107 @@ + + + + + Крупнообломочные с песчаным заполнителем и пески кроме мелких и пылеватых + Пески мелкие + Пески пылеватые маловлажные + Пески пылеватые влажные насыщенные водой + Пески рыхлые + Глинистые, а также крупнообломочные с глинистым заполнителем при IL<=0.25 + Глинистые, а также крупнообломочные с глинистым заполнителем при 0.25<IL<=0.5 + Глинистые, а также крупнообломочные с глинистым заполнителем при 0.5<IL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Параметры проекта + Площадки + Сечения + Усилия + Арматура + Бетон + Элементы + Трещиностойкость + Расчет + Вывод результатов + + Тип элементов + + + 25 + \ No newline at end of file diff --git a/Geometry/BoundingBox2d.cs b/Geometry/BoundingBox2d.cs new file mode 100644 index 0000000..33f8d04 --- /dev/null +++ b/Geometry/BoundingBox2d.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class BoundingBox2d + { + Point2d min; + Point2d max; + + public Point2d Min { get => min; private set => min = value; } + public Point2d Max { get => max; private set => max = value; } + + public BoundingBox2d() + { + min = new Point2d(); + max = new Point2d(); + } + + public BoundingBox2d(Point2d minPt, Point2d maxPt) + { + min = minPt; + max = maxPt; + } + + } +} diff --git a/Geometry/IVector.cs b/Geometry/IVector.cs new file mode 100644 index 0000000..e46556b --- /dev/null +++ b/Geometry/IVector.cs @@ -0,0 +1,9 @@ +namespace Geo +{ + public interface IVector + { + int N { get; } + + double[] ToArray(); + } +} \ No newline at end of file diff --git a/Geometry/Line2d.cs b/Geometry/Line2d.cs new file mode 100644 index 0000000..0e9da42 --- /dev/null +++ b/Geometry/Line2d.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class Line2d + { + protected Point3d startPoint; + protected Point3d endPoint; + protected Vector2d directive; + protected Vector2d normal; + + public Point3d StartPoint { get => startPoint; set { startPoint = value; if (EndPoint != null) { directive = endPoint.ToPoint2d() - startPoint.ToPoint2d(); CalcLine(); }; } } + public Point3d EndPoint { get => endPoint; set { endPoint = value; directive = endPoint.ToPoint2d() - startPoint.ToPoint2d(); CalcLine(); } } + public Point3d CenterPoint { get; private set; } + public Vector2d Directive { get => directive; private set => directive = value; } + public Vector2d Normal { get => normal; private set => normal = value; } + public double A { get; private set; } + public double B { get; private set; } + public double C { get; private set; } + public double k { get; private set; } + public double b { get; private set; } + public double Length { get => Directive.Norma; } + public double cosAlfa { get; private set; } + public double cosBeta { get; private set; } + public double p { get; private set; } + + public Line2d() + { + + } + + public Line2d(Point2d startPt, Point2d endPt) + { + startPoint = startPt.ToPoint3d(); endPoint = endPt.ToPoint3d(); + directive = endPoint.ToPoint2d() - startPoint.ToPoint2d(); + CalcLine(); + } + + public Line2d(Point3d startPt, Point3d endPt) + { + startPoint = startPt; + endPoint = endPt; + directive = endPoint.ToPoint2d() - startPoint.ToPoint2d(); + CalcLine(); + } + + protected void CalcLine() + { + A = Directive.Vy; + B = -Directive.Vx; + normal = new Vector2d(A, B); + C = Directive.Vx * StartPoint.Y - Directive.Vy * StartPoint.X; + if (Directive.Vx != 0) { k = Directive.Vy / Directive.Vx; } + else { k = Double.PositiveInfinity; } + if (Directive.Vx != 0) { b = -Directive.Vy / Directive.Vx * StartPoint.X + StartPoint.Y; } + else { b= Double.PositiveInfinity; } + double normC = 1 / Math.Sqrt(A * A + B * B); + if (C < 0) normC *= -1; + cosAlfa = A * normC; + cosBeta = B * normC; + p = C * normC; + double dx = 0.5 * (EndPoint.X - StartPoint.X); + double dy = 0.5 * (EndPoint.Y - StartPoint.Y); + CenterPoint = new Point3d(StartPoint.X + dx, StartPoint.Y + dy, 0); + } + + public double LengthTo(Point2d point) + { + double normC = 1 / Math.Sqrt(A * A + B * B); + if (C < 0) normC *= -1; + cosAlfa = A * normC; + cosBeta = B * normC; + p = C * normC; + return normC * (A * point.X + B * point.Y + C); + } + public double LengthTo(Point3d point) + { + double normC = 1 / Math.Sqrt(A * A + B * B); + if (C < 0) normC *= -1; + cosAlfa = A * normC; + cosBeta = B * normC; + p = C * normC; + return normC * (A * point.X + B * point.Y + C); + } + public double Interpolation(double x) + { + if (B == 0) return double.PositiveInfinity; + else return (-A * x - C) / B; + } + } +} diff --git a/Geometry/Line3d.cs b/Geometry/Line3d.cs new file mode 100644 index 0000000..dd5b612 --- /dev/null +++ b/Geometry/Line3d.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class Line3d + { + Point3d startPoint; + Point3d endPoint; + + public Point3d StartPoint { get => startPoint; set { startPoint = value; Directive = endPoint - startPoint; } } + public Point3d EndPoint { get => endPoint; set { endPoint = value; Directive = endPoint - startPoint; } } + public Vector3d Directive { get; private set; } + public double Length { get => Directive.Norma; } + + public Line3d() + { + + } + + public Line3d(Point2d startPt, Point2d endPt) + { + startPoint = startPt.ToPoint3d(); endPoint = endPt.ToPoint3d(); + Directive = endPoint - startPoint; ; + } + + public Line3d(Point3d startPt, Point3d endPt) + { + startPoint = startPt; endPoint = endPt; + Directive = endPoint - startPoint; ; + } + } +} diff --git a/Geometry/Matrix.cs b/Geometry/Matrix.cs new file mode 100644 index 0000000..a5dff6a --- /dev/null +++ b/Geometry/Matrix.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class Matrix + { + double[,] arr; + int m, n; + public int N + { + get + { + if (n > 0) + return n; + else + return -1; + } + } + public int M + { + get + { + if (m > 0) + return m; + else + return -1; + } + } + public double this[int i, int j] + { + get + { + if (n > 0 && m > 0) + if (i > -1 && j > -1) + return arr[i, j]; + else + Console.WriteLine("Неверный индексы"); + else + Console.WriteLine("Не задана матрица"); + return -1; + } + set + { + if (n > 0 && m > 0) + if (i > -1 && j > -1) + arr[i, j] = value; + else + Console.WriteLine("Неверный индексы"); + else + Console.WriteLine("Не задана матрица"); + } + } + + public Matrix(int N, int M) + { + m = M; + n = N; + arr = new double[N, M]; + } + + public Matrix(Matrix source) + { + m = source.M; + n = source.N; + arr = new double[source.N, source.M]; + arr = (double[,])source.arr.Clone(); + } + + public Matrix(double[,] source) + { + m = source.GetLength(1); + n = source.GetLength(0); + arr = new double[source.GetLength(0), source.GetLength(1)]; + arr = (double[,])source.Clone(); + } + + public double[,] ToArray() + { + return arr; + } + + public Matrix Copy() + { + return new Matrix(this); + } + + public static Matrix operator ^(Matrix A, Matrix B) + { + if (A.M != B.N) { throw new System.ArgumentException("Не совпадают размерности матриц"); } //Нужно только одно соответствие + Matrix C = new Matrix(A.N, B.M); //Столько же строк, сколько в А; столько столбцов, сколько в B + for (int i = 0; i < A.N; ++i) + { + for (int j = 0; j < B.M; ++j) + { + C[i, j] = 0; + for (int k = 0; k < A.M; ++k) + { //ТРЕТИЙ цикл, до A.m=B.n + C[i, j] += A[i, k] * B[k, j]; //Собираем сумму произведений + } + } + } + return C; + } + + public static Matrix operator *(Matrix A, Matrix B) + { + if (((A.n != B.n) || (A.m != B.m)) == true) { throw new System.ArgumentException("Не совпадают размерности матриц"); } + double[,] res = new double[A.n, B.m]; + + for (int i = 0; i < A.n; i++) + { + for (int j = 0; j < B.m; j++) + { + res[i, j] = A[i, j] * B[i, j]; + } + } + return new Matrix(res); + } + + public static Vector operator *(Matrix A, Vector B) + { + if (A.M != B.N) { throw new System.ArgumentException("Не совпадают размерности матриц"); } + double[] res = new double[A.N]; + + for (int i = 0; i < A.N; i++) + { + for (int j = 0; j < B.N; j++) + { + res[i] += A[i, j] * B[j]; + } + } + return new Vector(res); + } + + public static Vector3d operator *(Matrix A, Vector3d B) + { + if (A.n != 3 && A.m != 3) { throw new System.ArgumentException("Не верна размерность матрицы"); } + double[] res = new double[3]; + + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + res[i] += A[i, j] * B[j]; + } + } + return new Vector3d (res); + } + + public static Point3d operator *(Matrix A, Point3d B) + { + if (A.n != 3 && A.m != 3) { throw new System.ArgumentException("Не верна размерность матрицы"); } + double[] res = new double[3]; + + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + res[i] += A[i, j] * B[j]; + } + } + return new Point3d(res); + } + + public static Matrix operator *(Matrix A, double B) + { + double[,] res = new double[A.n, A.m]; + + for (int i = 0; i < A.n; i++) + { + for (int j = 0; j < A.m; j++) + { + res[i, j] = A[i, j] * B; + } + } + + return new Matrix(res); + } + + public static Matrix operator +(Matrix A, Matrix B) + { + if (((A.n != B.n) || (A.m != B.m)) == true) { throw new System.ArgumentException("Не совпадают размерности матриц"); } + double[,] res = new double[A.n, B.m]; + + for (int i = 0; i < A.n; i++) + { + for (int j = 0; j < B.m; j++) + { + res[i, j] = A[i, j] + B[i, j]; + } + } + return new Matrix(res); + } + } +} diff --git a/Geometry/Plane.cs b/Geometry/Plane.cs new file mode 100644 index 0000000..05e39ef --- /dev/null +++ b/Geometry/Plane.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static System.Math; + +namespace Geo +{ + [Serializable] + public class Plane + { + double a; + double b; + double c; + double d; + double gammaRad; + double gammaDeg; + + public double A { get => a; set { a = value; CalcPlane(); } } + public double B { get => b; set { b = value; CalcPlane(); } } + public double C { get => c; set { c = value; CalcPlane(); } } + public double D { get => d; set { d = value; CalcPlane(); } } + public double AlfaRad { get; private set; } + public double BetaRad { get; private set; } + public double GammaRad { get => gammaRad; set { gammaRad = value; RadToDeg(); } } + public double AlfaDeg { get; private set; } + public double BetaDeg { get; private set; } + public double GammaDeg { get => gammaDeg; set { gammaDeg = value; DegToRad(); } } + public Matrix MrAlfa { get; private set; } + public Matrix MrBeta { get; private set; } + public Matrix MrGamma { get; private set; } + public Vector3d X1 { get; private set; } + public Vector3d Y1 { get; private set; } + public Vector3d Z1 { get; private set; } + public Vector3d Normal { get; private set; } + public Matrix Mr { get; private set; } + public Point3d Basis { get; set; } + + public Plane() + { + Basis = new Point3d() { X = 0, Y = 0, Z = 0 }; + + a = 0; + b = 0; + c = 1; + d = 0; + + CalcPlane(); + } + + public Plane(Point3d pt1, Point3d pt2, Point3d pt3) + { + Basis = pt1; + + Vector3d v1 = new Vector3d() + { + Vx = pt2.X - pt1.X, + Vy = pt2.Y - pt1.Y, + Vz = pt2.Z - pt1.Z + }; + + Vector3d v2 = new Vector3d() + { + Vx = pt3.X - pt1.X, + Vy = pt3.Y - pt1.Y, + Vz = pt3.Z - pt1.Z + }; + + a = v1.Vy * v2.Vz - v1.Vz * v2.Vy; + b = v1.Vz * v2.Vx - v1.Vx * v2.Vz; + c = v1.Vx * v2.Vy - v1.Vy * v2.Vx; + d = -a * pt1.X - b * pt1.Y - c * pt1.Z; + + CalcPlane(); + RadToDeg(); + + } + + public Plane(Point3d pt1, Point3d pt2, Point3d pt3, Point3d bpt) + { + Basis = bpt; + + Vector3d v1 = new Vector3d() + { + Vx = pt2.X - pt1.X, + Vy = pt2.Y - pt1.Y, + Vz = pt2.Z - pt1.Z + }; + + Vector3d v2 = new Vector3d() + { + Vx = pt3.X - pt1.X, + Vy = pt3.Y - pt1.Y, + Vz = pt3.Z - pt1.Z + }; + + a = v1.Vy * v2.Vz - v1.Vz * v2.Vy; + b = v1.Vz * v2.Vx - v1.Vx * v2.Vz; + c = v1.Vx * v2.Vy - v1.Vy * v2.Vx; + d = -a * pt1.X - b * pt1.Y - c * pt1.Z; + + CalcPlane(); + RadToDeg(); + + } + + public double Interpolation(double x, double y) + { + if (C == 0) return double.PositiveInfinity; + else return (-A * x - B * y - D) / C; + } + + protected void CreatePlane(Point3d pt1, Point3d pt2, Point3d pt3) + { + Basis = pt1; + + Vector3d v1 = new Vector3d() + { + Vx = pt2.X - pt1.X, + Vy = pt2.Y - pt1.Y, + Vz = pt2.Z - pt1.Z + }; + + Vector3d v2 = new Vector3d() + { + Vx = pt3.X - pt1.X, + Vy = pt3.Y - pt1.Y, + Vz = pt3.Z - pt1.Z + }; + + a = v1.Vy * v2.Vz - v1.Vz * v2.Vy; + b = v1.Vz * v2.Vx - v1.Vx * v2.Vz; + c = v1.Vx * v2.Vy - v1.Vy * v2.Vx; + d = -a * pt1.X - b * pt1.Y - c * pt1.Z; + + CalcPlane(); + RadToDeg(); + } + + protected void CalcPlane() + { + Normal = new Vector3d + { + Vx = a, + Vy = b, + Vz = c + }; + + Intersect(); + CreateMatrix(); + + } + + protected void Intersect() + { + if ((a == 0 & b == 0) == false) + { + Vector3d v3 = new Vector3d { Vx = 0, Vy = 0, Vz = 1 }; + Z1 = new Vector3d(Normal.Unit); + X1 = new Vector3d((v3 ^ Z1).Unit); + Y1 = new Vector3d((Z1 ^ X1).Unit); + + AlfaRad = -Acos(X1.Vx); + BetaRad = -Acos(Z1.Vz); + + //alfaRad = Math.Acos(unitP.Vx); + //betaRad = Math.Acos(unitNormal.Vz); + } + } + + protected void CreateMatrix() + { + Vector3d o = new Vector3d(); + o[0] = -X1.Vx * Basis.X - X1.Vy * Basis.Y - X1.Vz * Basis.Z; + o[1] = -Y1.Vx * Basis.X - Y1.Vy * Basis.Y - Y1.Vz * Basis.Z; + o[2] = -Z1.Vx * Basis.X - Z1.Vy * Basis.Y - Z1.Vz * Basis.Z; + + Mr = new Matrix(4, 4); + + Mr[0, 0] = X1.Vx; Mr[0, 1] = X1.Vy; Mr[0, 2] = X1.Vz; Mr[0, 3] = o.Vx; + Mr[1, 0] = Y1.Vx; Mr[1, 1] = Y1.Vy; Mr[1, 2] = Y1.Vz; Mr[1, 3] = o.Vy; + Mr[2, 0] = Z1.Vx; Mr[2, 1] = Z1.Vy; Mr[2, 2] = Z1.Vz; Mr[2, 3] = o.Vz; + Mr[3, 0] = 0; Mr[3, 1] = 0; Mr[3, 2] = 0; Mr[3, 3] = 1; + + MrAlfa = new Matrix(3, 3); + + MrAlfa[0, 0] = Cos(AlfaRad); MrAlfa[0, 1] = -Sin(AlfaRad); MrAlfa[0, 2] = 0; + MrAlfa[1, 0] = Sin(AlfaRad); MrAlfa[1, 1] = Cos(AlfaRad); MrAlfa[1, 2] = 0; + MrAlfa[2, 0] = 0; MrAlfa[2, 1] = 0; MrAlfa[2, 2] = 0; + + MrBeta = new Matrix(3, 3); + + MrBeta[0, 0] = 1; MrBeta[0, 1] = 0; MrBeta[0, 2] = 0; + MrBeta[1, 0] = 0; MrBeta[1, 1] = Cos(BetaRad); MrBeta[1, 2] = -Sin(BetaRad); + MrBeta[2, 0] = 0; MrBeta[2, 1] = Sin(BetaRad); MrBeta[2, 2] = Cos(BetaRad); + + MrGamma = new Matrix(3, 3); + + MrGamma[0, 0] = Cos(gammaRad); MrGamma[0, 1] = -Sin(gammaRad); MrGamma[0, 2] = 0; + MrGamma[1, 0] = Sin(gammaRad); MrGamma[1, 1] = Cos(gammaRad); MrGamma[1, 2] = 0; + MrGamma[2, 0] = 0; MrGamma[2, 1] = 0; MrGamma[2, 2] = 1; + } + + public Point3d PointInLCS(Point3d pt) + { + double[] d1 = new double[] { 0, 0, 0, 1 }; ; + Vector v1 = new Vector(d1); + v1[0] = pt.X; v1[1] = pt.Y; v1[2] = pt.Z; + + return new Point3d().FromArray((Mr * v1).ToArray()); + } + + protected double[] MultiplyMtxVec(double[,] _Matrix, double[] _Vector) + { + int n = _Vector.Length; + double[] _Result = new double[n]; + + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + _Result[i] += _Matrix[i, j] * _Vector[j]; + } + } + + return _Result; + } + + protected void RadToDeg() + { + AlfaDeg = AlfaRad * 180 / PI; + BetaDeg = BetaRad * 180 / PI; + gammaDeg = gammaRad * 180 / PI; + } + + protected void DegToRad() + { + gammaRad = gammaDeg * 180 / PI; + } + } +} diff --git a/Geometry/Point2d.cs b/Geometry/Point2d.cs new file mode 100644 index 0000000..8d56f6f --- /dev/null +++ b/Geometry/Point2d.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class Point2d + { + double[] arr = new double[2]; + + public double this[int i] { get => arr[i]; set => arr[i] = value; } + public double X { get => arr[0]; set => arr[0] = value; } + public double Y { get => arr[1]; set => arr[1] = value; } + + public Point2d() + { + arr = new double[2]; + } + + public Point2d(double x, double y) + { + arr = new double[2]; + arr[0] = x; arr[1] = y; + } + + public Point2d(Point2d source) + { + arr = new double[2]; + arr = (double[])source.arr.Clone(); + } + + public Point2d(Point3d source) + { + arr = new double[2]; + arr[0]=source.X; arr[1] = source.Y; + } + + public Point2d(double[] source) + { + arr = new double[2]; + if (source.Length >= 2) + { + arr[0] = source[0]; arr[1] = source[1]; + } + } + + public double[] ToArray() + { + return new double[] { X, Y }; + } + + public Vector2d ToVector2d() + { + return new Vector2d { Vx = X, Vy = Y}; + } + + public Vector3d ToVector3d() + { + return new Vector3d { Vx = X, Vy = Y, Vz = 0 }; + } + + public Point3d ToPoint3d() + { + return new Point3d { X = X, Y = Y, Z = 0 }; + } + + public Point2d FromArray(double[] arr) + { + X = arr[0]; Y = arr[1]; + return this; + } + + public double LengthTo(Point2d node) + { + Line2d line = new Line2d(this, node); + return line.Length; + } + + public static Vector2d operator -(Point2d pt1, Point2d pt2) + { + Vector2d res = new Vector2d(); + res[0] = pt1.X - pt2.X; + res[1] = pt1.Y - pt2.Y; + return res; + } + + public static bool operator ==(Point2d p1, Point2d p2) + { + bool check = false; + if (p1.X == p2.X && p1.Y == p2.Y) + { + check = true; + } + return (check); + } + + public static bool operator !=(Point2d p1, Point2d p2) + { + bool check = true; + if (p1.X == p2.X && p1.Y == p2.Y) + { + check = false; + } + return (check); + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + } +} diff --git a/Geometry/Point3d.cs b/Geometry/Point3d.cs new file mode 100644 index 0000000..7868d0c --- /dev/null +++ b/Geometry/Point3d.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class Point3d : IVector + { + double[] arr; + //int n = 3; + + public double this[int i] { get => arr[i]; set => arr[i] = value; } + public double X { get => arr[0]; set => arr[0] = value; } + public double Y { get => arr[1]; set => arr[1] = value; } + public double Z { get => arr[2]; set => arr[2] = value; } + + public int N => 3; + + //int N { get => n; } + + public Point3d() + { + arr = new double[3]; + } + + public Point3d(double x, double y, double z) + { + arr = new double[3]; + arr[0] = x; arr[1] = y; arr[2] = z; + } + + public Point3d(double x, double y) + { + arr = new double[3]; + arr[0] = x; arr[1] = y; arr[2] = 0; + } + + public Point3d(Point3d source) + { + arr = new double[3]; + arr = (double[])source.arr.Clone(); + } + + public Point3d(double[] source) + { + arr = new double[3]; + if (source.Length >= 3) { arr[0] = source[0]; arr[1] = source[1]; arr[2] = source[2]; } + else if (source.Length == 2) { arr[0] = source[0]; arr[1] = source[1]; } + else { arr[0] = source[0]; } + } + + public double[] ToArray() + { + return new double[] { X, Y, Z }; + } + + public Vector3d ToVector3d() + { + return new Vector3d { Vx = X, Vy = Y, Vz = Z }; + } + + public Point2d ToPoint2d() + { + return new Point2d { X = X, Y = Y }; + } + + public Point3d FromArray(double[] arr) + { + X = arr[0]; Y = arr[1]; Z = arr[2]; + return this; + } + + public double LengthTo(Point3d node) + { + Line3d line = new Line3d(this, node); + return line.Length; + } + + public double AngleTo(Point3d startPoint, Point3d endPoint) + { + Point3d tempNode = new Point3d(); + + Line3d tempLine1 = new Line3d(this, startPoint); + Line3d tempLine2 = new Line3d(this, endPoint); + double cosTo = Vector3d.CosAngleBetVectors(tempLine1.Directive, tempLine2.Directive); + return RadToDeg(Math.Acos(cosTo)); + } + + public bool NormalDirection(Point3d startNode, Point3d endNode) + { + Line3d tempLine1 = new Line3d(this, startNode); + Line3d tempLine2 = new Line3d(this, endNode); + double norm = (tempLine1.Directive ^ tempLine2.Directive).Vz; + bool res = false; + if (norm > 0) res = true; + return res; + } + + private double RadToDeg(double radians) + { + return radians * 180 / Math.PI; + } + + public static Point3d operator *(Point3d pt, double prime) + { + return new Point3d + { + X = pt.X * prime, + Y = pt.Y * prime, + Z = pt.Z * prime + }; + } + + public static Vector3d operator -(Point3d pt1, Point3d pt2) + { + Vector3d res = new Vector3d(); + res[0] = pt1.X - pt2.X; + res[1] = pt1.Y - pt2.Y; + res[2] = pt1.Z - pt2.Z; + return res; + } + + public static bool operator ==(Point3d p1, Point3d p2) + { + bool check = false; + if (p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z) + { + check = true; + } + return (check); + } + + public static bool operator !=(Point3d p1, Point3d p2) + { + bool check = true; + if (p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z) + { + check = false; + } + return (check); + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + } +} diff --git a/Geometry/Polygon.cs b/Geometry/Polygon.cs new file mode 100644 index 0000000..7b4a265 --- /dev/null +++ b/Geometry/Polygon.cs @@ -0,0 +1,663 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class Polygon + { + private double area; + private double ix; + private double iy; + private List vertices = new List(); + + public bool Ckw { get; internal set; } + //public bool? IsSelfItersected { get; private set; } + public double Area { get => Math.Abs(area); } + public double Perimeter { get; internal set; } + public Point3d Centroid { get; internal set; } + public double Ix { get => Math.Abs(ix); } + public double Iy { get => Math.Abs(iy); } + public List Vertices { get => vertices; set { vertices = value; CalcPolygon(); } } + public BoundingBox2d BoundingBox { get; internal set; } + public List Segments { get; internal set; } + + public Polygon() + { + + } + + public Polygon(List vrts) + { + vertices = vrts; + if (vertices[0].X != vertices[vrts.Count - 1].X && vertices[0].Y != vertices[vrts.Count - 1].Y) vertices.Add(vertices[0]); + CalcPolygon(); + } + + public Polygon(List vrts) + { + foreach (Point2d item in vrts) vertices.Add(item.ToPoint3d()); + if (vertices[0].X != vertices[vrts.Count - 1].X && vertices[0].Y != vertices[vrts.Count - 1].Y) vertices.Add(vertices[0]); + CalcPolygon(); + } + + public virtual void AddVertice(Point2d pt) + { + if (vertices.Count == 0) + { + vertices.Add(pt.ToPoint3d()); + return; + } + if (vertices.Count == 1) + { + vertices.Add(pt.ToPoint3d()); + vertices.Add(vertices[0]); + return; + } + if (vertices.Count >= 3) + { + vertices.RemoveAt(vertices.Count - 1); + vertices.Add(pt.ToPoint3d()); + vertices.Add(vertices[0]); + CalcPolygon(); + } + } + + public virtual void AddVertice(Point3d pt) + { + if (vertices.Count == 0) + { + vertices.Add(pt); + return; + } + if (vertices.Count == 1) + { + vertices.Add(pt); + vertices.Add(vertices[0]); + return; + } + if (vertices.Count >= 3) + { + vertices.RemoveAt(vertices.Count - 1); + vertices.Add(pt); + vertices.Add(vertices[0]); + CalcPolygon(); + } + } + + private void CalcBB() + { + double minX = 1000000000; + double minY = 1000000000; + double maxX = -1000000000; + double maxY = -1000000000; + + if (vertices.Count > 0) + { + foreach (Point3d item in vertices) + { + if (item.X < minX) { minX = item.X; } + if (item.Y < minY) { minY = item.Y; } + if (item.X > maxX) { maxX = item.X; } + if (item.Y > maxY) { maxY = item.Y; } + } + + BoundingBox = new BoundingBox2d(new Point2d(minX, minY), new Point2d(maxX, maxY)); + } + } + + private void CalcSegs() + { + if (vertices.Count > 3) + { + Segments = new List(); + for (int i = 0; i < vertices.Count - 1; i++) + { + Segments.Add(new Line2d(vertices[i], vertices[i + 1])); + } + } + } + + protected void CalcI() + { + if (Segments.Count > 2) + { + double tempX = 0; + double tempY = 0; + for (int i = 0; i < Segments.Count; i++) + { + Point3d arrTemp = Segments[i].StartPoint; Point3d arrTemp1 = Segments[i].EndPoint; + tempX += (Math.Pow(arrTemp.X, 2) + arrTemp.X * arrTemp1.X + Math.Pow(arrTemp1.X, 2)) * (arrTemp.X * arrTemp1.Y - arrTemp.Y * arrTemp1.X); + tempY += (Math.Pow(arrTemp.Y, 2) + arrTemp.Y * arrTemp1.Y + Math.Pow(arrTemp1.Y, 2)) * (arrTemp.X * arrTemp1.Y - arrTemp.Y * arrTemp1.X); + } + ix = tempX / 12; + iy = tempY / 12; + } + } + + protected void CalcCentroid() + { + if (Segments.Count > 2) + { + Point3d temp = new Point3d(); + for (int i = 0; i < Segments.Count; i++) + { + Point3d arrTemp = Segments[i].StartPoint; Point3d arrTemp1 = Segments[i].EndPoint; + temp.X += 1 / (6 * area) * (arrTemp.X + arrTemp1.X) * (arrTemp.X * arrTemp1.Y - arrTemp.Y * arrTemp1.X); + temp.Y += 1 / (6 * area) * (arrTemp.Y + arrTemp1.Y) * (arrTemp.X * arrTemp1.Y - arrTemp.Y * arrTemp1.X); + } + Centroid = temp; + } + } + + protected void CalcArea() + { + double temp = 0; + if (Segments.Count > 2) + { + for (int i = 0; i < Segments.Count; i++) + { + Point3d arrTemp = Segments[i].StartPoint; Point3d arrTemp1 = Segments[i].EndPoint; + temp += 0.5 * (arrTemp.X * arrTemp1.Y - arrTemp1.X * arrTemp.Y); + } + area = temp; + } + } + + protected void CalcPerimeter() + { + if (Segments.Count > 2) + { + Perimeter = 0; + foreach (Line2d item in Segments) + { + Perimeter += item.Length; + } + } + } + + protected void CalcCkw() + { + if (area < 0) Ckw = true; + else Ckw = false; + } + + /// + /// Вычисление свойств полигона + /// + public void CalcPolygon() + { + if (Vertices.Count > 3) + { + if ((Vertices[0].X != Vertices[vertices.Count - 1].X && Vertices[0].Y != Vertices[Vertices.Count - 1].Y)|| + (Vertices[0].X == Vertices[vertices.Count - 1].X && Vertices[0].Y != Vertices[Vertices.Count - 1].Y)|| + (Vertices[0].X != Vertices[vertices.Count - 1].X && Vertices[0].Y == Vertices[Vertices.Count - 1].Y)) + Vertices.Add(Vertices[0]); + } + CalcBB(); + CalcSegs(); + CalcPerimeter(); + CalcArea(); + CalcCkw(); + CalcCentroid(); + CalcI(); + } + + /// + /// Замена вершины полигона + /// + /// индекс заменяемой вершины + /// объект заменяющей вершины + public bool ReplaceVertice( int oldVertIdx, Point3d newVert) + { + try + { + Vertices[oldVertIdx] = newVert; + if (oldVertIdx == 0 || oldVertIdx == Vertices.Count - 1) { Vertices[0] = newVert; Vertices[Vertices.Count - 1] = newVert; } + CalcPolygon(); + return true; + } + catch + { + return false; + } + } + + public void Triangulation(double shag, out List innerNodes, out List triangles) + { + innerNodes = new List(); + triangles = new List(); + List polygons = new List(); + int n = Tesselation(shag); + Polygon front = new Polygon(Vertices); + //int p = 1; + do + { + if (polygons.Count != 0) { front = polygons[0]; polygons.RemoveAt(0); } + for (int j = 0; j < 1000; j++) + { + AngleIn3Point minAngle; + front.MinAngleDeg(out minAngle); + while (minAngle.AngleDeg == 0 && front.Vertices.Count > 3) + { + if(minAngle.VerticeIdx == 0) + { + front.Vertices.RemoveRange(Vertices.Count - 2, 2); + front.Vertices.RemoveAt(0); + } + else front.Vertices.RemoveRange(minAngle.PreviousIdx, 2); + front.CalcPolygon(); + front.MinAngleDeg(out minAngle); + } + + if (Math.Round(minAngle.AngleDeg) < 90) + { + triangles.Add(new Triangle(front.Vertices[minAngle.PreviousIdx], front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx])); + front.Vertices.RemoveAt(minAngle.VerticeIdx); + if (minAngle.VerticeIdx == 0 && front.Vertices.Count > 3) front.Vertices.RemoveAt(front.Vertices.Count - 1); + front.CalcPolygon(); + } + + else if (Math.Round(minAngle.AngleDeg) == 90 /*&& Math.Round(minAngle.AngleDeg) <= 140*/) + { + Line2d lin = new Line2d(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.PreviousIdx]); + Point3d temp = front.Vertices[minAngle.VerticeIdx]; + Point3d g = new Point3d(front.Vertices[minAngle.NextIdx].X + lin.Directive.Vx, front.Vertices[minAngle.NextIdx].Y + lin.Directive.Vy, 0); + Point3d gNode = new Point3d { X = g.X, Y = g.Y, Z = g.Z/*, Number = n*/ }; + bool ch = false; + int k = -1; + for (int i = 0; i < front.Vertices.Count - 1; i++) + { + //if (i == minAngle.VerticeIdx) continue; + double d = g.LengthTo(front.Vertices[i]); + if (Math.Round(g.X, 2) == Math.Round(front.Vertices[i].X, 2) && Math.Round(g.Y, 2) == Math.Round(front.Vertices[i].Y, 2)) + { ch = true; k = i; break; } + } + + Triangle t1, t2; + + if (ch) + { + t1 = new Triangle(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx], front.Vertices[k]); + t2 = new Triangle(front.Vertices[minAngle.PreviousIdx], front.Vertices[minAngle.VerticeIdx], front.Vertices[k]); + } + else + { + t1 = new Triangle(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx], gNode); + t2 = new Triangle(front.Vertices[minAngle.PreviousIdx], front.Vertices[minAngle.VerticeIdx], gNode); + } + + front.ReplaceVertice(minAngle.VerticeIdx, gNode); + + if (front.SelfItersectCheck()) + { + front.ReplaceVertice(minAngle.VerticeIdx, temp); + double dist = 100000000; + k = -1; + for (int i = 0; i < front.Vertices.Count - 1; i++) + { + if (i == minAngle.NextIdx || i == minAngle.PreviousIdx || i == minAngle.VerticeIdx) continue; + double d = front.Vertices[minAngle.VerticeIdx].LengthTo(front.Vertices[i]); + if (d < dist) { dist = d; k = i; } + } + Polygon sub; + front.Bisection(k, minAngle.VerticeIdx, out sub); + polygons.Add(sub); + } + else + { + if (!ch) { innerNodes.Add(gNode); n++; } + triangles.Add(t1); triangles.Add(t2); + } + + } + + else + { + Line2d linPrev = new Line2d(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.PreviousIdx]); + Line2d linNext = new Line2d(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx]); + double vx = (linPrev.Directive.Unit[0] + linNext.Directive.Unit[0]) * 0.5; + double vy = (linPrev.Directive.Unit[1] + linNext.Directive.Unit[1]) * 0.5; + //double lengthBis = (linPrev.Length + linNext.Length) * 0.5; + double x = front.Vertices[minAngle.VerticeIdx].X + vx * shag; + double y = front.Vertices[minAngle.VerticeIdx].Y + vy * shag; + Point3d temp = front.Vertices[minAngle.VerticeIdx]; + Point3d g = new Point3d(x, y, 0); + Line2d linBis = new Line2d(front.Vertices[minAngle.VerticeIdx], g); + x = front.Vertices[minAngle.VerticeIdx].X + linBis.Directive.Unit[0] * shag; + y = front.Vertices[minAngle.VerticeIdx].Y + linBis.Directive.Unit[1] * shag; + g = new Point3d(x, y, 0); + Point3d gNode = new Point3d() { X = g.X, Y = g.Y, Z = g.Z/*, Number = n*/ }; + Triangle t1, t2; + t1 = new Triangle(front.Vertices[minAngle.VerticeIdx], front.Vertices[minAngle.NextIdx], gNode); + t2 = new Triangle(front.Vertices[minAngle.PreviousIdx], front.Vertices[minAngle.VerticeIdx], gNode); + front.ReplaceVertice(minAngle.VerticeIdx, gNode); + //if (p == 1) { Shpunt.AcCreator.CreateContour(front); p++; } + + if (front.SelfItersectCheck()) + { + front.ReplaceVertice(minAngle.VerticeIdx, temp); + double dist = 100000000; + int k = -1; + for (int i = 0; i < front.Vertices.Count - 1; i++) + { + if (i == minAngle.NextIdx || i == minAngle.PreviousIdx || i == minAngle.VerticeIdx) continue; + double d = front.Vertices[minAngle.VerticeIdx].LengthTo(front.Vertices[i]); + if (d < dist) { dist = d; k = i; } + } + Polygon sub; + front.Bisection(k, minAngle.VerticeIdx, out sub); + polygons.Add(sub); + } + else + { + triangles.Add(t1); + triangles.Add(t2); + innerNodes.Add(gNode); + } + n++; + } + if (front.Vertices.Count < 4) break; + } + } while (polygons.Count != 0); + } + + /// + /// Тесселяция полигона с заданным шагом + /// + /// Величина шага тесселяции + public int Tesselation(double shag) + { + List nodes = new List(); + int n = 1; + int nD = 0; + foreach (Line2d seg in Segments) + { + Point3d start = seg.StartPoint; + Point3d end = seg.EndPoint; + nD = (int)Math.Round(seg.Length / shag); + if (nD > 1) + { + double delta = seg.Length / nD; + double deltaX = (end.X - start.X) / nD; + double deltaY = (end.Y - start.Y) / nD; + double deltaZ = (end.Z - start.Z) / nD; + for (int j = 0; j < nD; j++) + { + Point3d pt = new Point3d(start.X + j * deltaX, start.Y + j * deltaY, start.Z + j * deltaZ); + //FEA.Node nd = new FEA.Node(pt) { Number = n }; + nodes.Add(pt); + n++; + } + } + else + { + Point3d pt = new Point3d(start.X, start.Y, start.Z); + //FEA.Node nd = new FEA.Node(pt) { Number = n }; + nodes.Add(pt); + n++; + } + } + Vertices = nodes; + if (!Ckw) { Vertices.Reverse(); CalcPolygon(); } + return n; + } + + /// + /// Деление полигона через указание 2-х точек деления + /// + /// Индекс первой точки деления(секущей) + /// Индекс второй точки деления(базовой) + /// Возвращаемый отсеченный полигон + public void Bisection(int sectPointIdx,int basePointIdx, out Polygon newPolygon) + { + newPolygon = new Polygon(); + List tmp = new List(); + if (basePointIdx > sectPointIdx) + { + for (int i = sectPointIdx; i <= basePointIdx; i++) + { + newPolygon.AddVertice(Vertices[i]); + } + newPolygon.CalcPolygon(); + Vertices.RemoveRange(sectPointIdx + 1, basePointIdx - sectPointIdx - 1); + CalcPolygon(); + } + else + { + for (int i = basePointIdx; i <= sectPointIdx; i++) + { + newPolygon.AddVertice(Vertices[i]); + } + newPolygon.CalcPolygon(); + Vertices.RemoveRange(basePointIdx + 1, sectPointIdx - basePointIdx - 1); + CalcPolygon(); + } + } + + /// + /// Проверка полигона на самопересечение (возвращает булево значение, если true - полигон самопересекающийся) + /// + public bool SelfItersectCheck() + { + bool IsSelfItersected = false; + if (Segments.Count < 4) return IsSelfItersected; + for (int i = 0; i < Segments.Count; i++) + { + for (int j = 0; j < Segments.Count; j++) + { + if (i == j) continue; + double a1 = Segments[i].A; + double a2 = Segments[j].A; + double b1 = Segments[i].B; + double b2 = Segments[j].B; + double c1 = Segments[i].C; + double c2 = Segments[j].C; + double p1 = (b2 - b1 * a2 / a1); + if (p1 == 0) continue; + double y = (a2 * c1 / a1 - c2) / p1; + double x = (-b1 * y - c1) / a1; + Point3d ptItersect = new Point3d(x, y, 0); + Line2d linTmp1 = new Line2d(Segments[i].CenterPoint, ptItersect); + Line2d linTmp2 = new Line2d(Segments[j].CenterPoint, ptItersect); + double l1 = Math.Round(linTmp1.Length, 2); + double l11 = Math.Round(Segments[i].Length / 2, 2); + double l2 = Math.Round(linTmp2.Length, 2); + double l22 = Math.Round(Segments[j].Length / 2, 2); + if (Math.Round(linTmp1.Length, 2) < Math.Round(Segments[i].Length / 2, 2) && + Math.Round(linTmp2.Length, 2) < Math.Round(Segments[j].Length / 2, 2)) + { + IsSelfItersected = true; + return IsSelfItersected; + } + } + } + return IsSelfItersected; + } + /// + /// Вычисление минимального угла полигона в градусах + /// + /// + public double MinAngleDeg() + { + double minAngle = 360; + double angleTmp; + bool type; + for (int i = 0; i < Vertices.Count - 1; i++) + { + if (i == 0) + { + angleTmp = Vertices[0].AngleTo(Vertices[Vertices.Count - 2], Vertices[1]); + if (angleTmp is double.NaN) angleTmp = 180; + type = Vertices[0].NormalDirection(Vertices[Vertices.Count - 2], Vertices[1]); + if (!type && angleTmp != 0) angleTmp = 360 - angleTmp; + if (!type && angleTmp == 0) angleTmp = 0; + if (angleTmp < minAngle) minAngle = angleTmp; + } + else + { + angleTmp = Vertices[i].AngleTo(Vertices[i - 1], Vertices[i + 1]); + if (angleTmp is double.NaN) angleTmp = 180; + type = Vertices[i].NormalDirection(Vertices[i - 1], Vertices[i + 1]); + if (!type && angleTmp != 0) angleTmp = 360 - angleTmp; + if (!type && angleTmp == 0) angleTmp = 0; + if (angleTmp < minAngle) minAngle = angleTmp; + } + } + return minAngle; + } + /// + /// Вычисление минимального угла полигона в градусах (возвращает массив индексов 3-х точек на которых был найден угол) + /// + /// Возвращаемое значение минимального угла в градусах + public int[] MinAngleDeg(out double minAngle) + { + minAngle = 0; + if (Vertices.Count < 3) return null; + int[] res = new int[3]; + minAngle = 360; + double angleTmp; + bool type; + for (int i = 0; i < Vertices.Count - 1; i++) + { + if (i == 0) + { + angleTmp = Vertices[0].AngleTo(Vertices[Vertices.Count - 2], Vertices[i + 1]); + if (angleTmp is double.NaN) angleTmp = 180; + type = Vertices[i].NormalDirection(Vertices[Vertices.Count - 2], Vertices[i + 1]); + if (!type && angleTmp != 0) angleTmp = 360 - angleTmp; + if (!type && angleTmp == 0) angleTmp = 0; + if (angleTmp < minAngle) + { + res[0] = Vertices.Count - 2; + res[1] = 0; + res[2] = 1; + minAngle = angleTmp; + } + } + else + { + angleTmp = Vertices[i].AngleTo(Vertices[i - 1], Vertices[i + 1]); + if (angleTmp is double.NaN) angleTmp = 180; + type = Vertices[i].NormalDirection(Vertices[i - 1], Vertices[i + 1]); + if (!type && angleTmp != 0) angleTmp = 360 - angleTmp; + if (!type && angleTmp == 0) angleTmp = 0; + if (angleTmp < minAngle) + { + res[0] = i - 1; + res[1] = i; + res[2] = i + 1; + minAngle = angleTmp; + } + } + } + return res; + } + + /// + /// Вычисление минимального угла полигона в градусах + /// + /// Возвращаемое значение в виде объекта со свойствами индексов трех точек образуюших угол и значения угла в градусах + public void MinAngleDeg(out AngleIn3Point result) + { + result = new AngleIn3Point(); + result.AngleDeg = 0; + if (Vertices.Count < 3) return; + result.AngleDeg = 360; + double angleTmp; + bool type; + for (int i = 0; i < Vertices.Count - 1; i++) + { + if (i == 0) + { + angleTmp = Vertices[0].AngleTo(Vertices[Vertices.Count - 2], Vertices[i + 1]); + if (angleTmp is double.NaN) angleTmp = 180; + type = Vertices[i].NormalDirection(Vertices[Vertices.Count - 2], Vertices[i + 1]); + if (!type && angleTmp != 0) angleTmp = 360 - angleTmp; + if (!type && angleTmp == 0) angleTmp = 0; + if (angleTmp < result.AngleDeg) + { + result.PreviousIdx = Vertices.Count - 2; + result.VerticeIdx = 0; + result.NextIdx = 1; + result.AngleDeg = angleTmp; + } + } + else + { + angleTmp = Vertices[i].AngleTo(Vertices[i - 1], Vertices[i + 1]); + if (angleTmp is double.NaN) angleTmp = 180; + type = Vertices[i].NormalDirection(Vertices[i - 1], Vertices[i + 1]); + if (!type && angleTmp != 0) angleTmp = 360 - angleTmp; + if (!type && angleTmp == 0) angleTmp = 0; + if (angleTmp < result.AngleDeg) + { + result.PreviousIdx = i - 1; + result.VerticeIdx = i; + result.NextIdx = i + 1; + result.AngleDeg = angleTmp; + } + } + } + } + /// + /// Вычисление максимального угла полигона в градусах + /// + /// + public double MaxAngleDeg() + { + double minAngle = 0; + double angleTmp; + bool type; + for (int i = 0; i < Vertices.Count - 1; i++) + { + if (i == 0) + { + angleTmp = Vertices[0].AngleTo(Vertices[Vertices.Count - 2], Vertices[i + 1]); + if (angleTmp is double.NaN) angleTmp = 180; + type = Vertices[i].NormalDirection(Vertices[Vertices.Count - 2], Vertices[i + 1]); + if (!type && angleTmp != 0) angleTmp = 360 - angleTmp; + if (!type && angleTmp == 0) angleTmp = 0; + if (angleTmp > minAngle) minAngle = angleTmp; + } + else + { + angleTmp = Vertices[i].AngleTo(Vertices[i - 1], Vertices[i + 1]); + if (angleTmp is double.NaN) angleTmp = 180; + type = Vertices[i].NormalDirection(Vertices[i - 1], Vertices[i + 1]); + if (!type && angleTmp != 0) angleTmp = 360 - angleTmp; + if (!type && angleTmp == 0) angleTmp = 0; + if (angleTmp > minAngle) minAngle = angleTmp; + } + } + + return minAngle; + } + } + /// + /// Объект-структура со свойствами индексов трех точек образуюших угол и значения угла в градусах + /// + public struct AngleIn3Point + { + /// + /// Индекс предыдущей вершины + /// + public int PreviousIdx { get; set; } + /// + /// Индех следующей вершины + /// + public int NextIdx { get; set; } + /// + /// Индекс вершины, на которой найден угол + /// + public int VerticeIdx { get; set; } + /// + /// Значение найденного угла в градусах + /// + public double AngleDeg { get; set; } + + } +} diff --git a/Geometry/Quadrangle.cs b/Geometry/Quadrangle.cs new file mode 100644 index 0000000..6b80dc9 --- /dev/null +++ b/Geometry/Quadrangle.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class Quadrangle : Polygon + { + private Point3d vertex1 = new Point3d(); + private Point3d vertex2 = new Point3d(); + private Point3d vertex3 = new Point3d(); + private Point3d vertex4 = new Point3d(); + + public Point3d Vertex1 { get => vertex1; set { vertex1 = value; Vertices[0] = vertex1; CalcQuadrangle(); } } + public Point3d Vertex2 { get => vertex2; set { vertex2 = value; Vertices[1] = vertex2; CalcQuadrangle(); } } + public Point3d Vertex3 { get => vertex3; set { vertex3 = value; Vertices[2] = vertex3; CalcQuadrangle(); } } + public Point3d Vertex4 { get => vertex4; set { vertex4 = value; Vertices[3] = vertex4; CalcQuadrangle(); } } + public double MaxAngleDeg { get; private set; } + public bool IsValid { get; private set; } + public UnitsLin Units { get; set; } + + public Quadrangle(Triangle trg1, Triangle trg2) + { + List vrt = new List(); + List dgn = new List(); + vrt.Add(trg1.Vertex1); + vrt.Add(trg1.Vertex2); + vrt.Add(trg1.Vertex3); + vrt.Add(trg2.Vertex1); + vrt.Add(trg2.Vertex2); + vrt.Add(trg2.Vertex3); + for (int i = 0; i < vrt.Count; i++) + { + for (int j = 0; j < vrt.Count; j++) + { + if (i == j) continue; + if (Math.Round(vrt[i].X, 2) == Math.Round(vrt[j].X,2) && Math.Round(vrt[i].Y,2) == Math.Round(vrt[j].Y,2)) + { + dgn.Add(vrt[i]); + vrt.RemoveAt(j); + break; + } + } + } + + if (vrt.Count == 4) + { + if (vrt[0].Equals(dgn[0]) && vrt[1].Equals(dgn[1])) + { + vertex1 = vrt[0]; + AddVertice(Vertex1); + vertex2 = vrt[2]; + AddVertice(Vertex2); + vertex3 = vrt[1]; + AddVertice(Vertex3); + vertex4 = vrt[3]; + AddVertice(Vertex4); + } + if (vrt[1].Equals(dgn[0]) && vrt[2].Equals(dgn[1])) + { + vertex1 = vrt[0]; + AddVertice(Vertex1); + vertex2 = vrt[2]; + AddVertice(Vertex2); + vertex3 = vrt[3]; + AddVertice(Vertex3); + vertex4 = vrt[1]; + AddVertice(Vertex4); + } + if (vrt[0].Equals(dgn[0]) && vrt[2].Equals(dgn[1])) + { + vertex1 = vrt[0]; + AddVertice(Vertex1); + vertex2 = vrt[1]; + AddVertice(Vertex2); + vertex3 = vrt[2]; + AddVertice(Vertex3); + vertex4 = vrt[3]; + AddVertice(Vertex4); + } + if (vrt[1].Equals(dgn[0]) && vrt[3].Equals(dgn[1])) + { + vertex1 = vrt[0]; + AddVertice(Vertex1); + vertex2 = vrt[1]; + AddVertice(Vertex2); + vertex3 = vrt[2]; + AddVertice(Vertex3); + vertex4 = vrt[3]; + AddVertice(Vertex4); + } + IsValid = true; + CalcQuadrangle(); + } + else + { + IsValid = false; + Vertices.Add(new Point3d()); + Vertices.Add(new Point3d()); + Vertices.Add(new Point3d()); + Vertices.Add(new Point3d()); + } + } + + public Quadrangle(Point3d node1, Point3d node2, Point3d node3, Point3d node4) + { + vertex1 = node1; + AddVertice(node1); + vertex2 = node2; + AddVertice(node2); + vertex3 = node3; + AddVertice(node3); + vertex4 = node4; + AddVertice(node4); + CalcQuadrangle(); + IsValid = true; + } + + public Quadrangle(Point2d node1, Point2d node2, Point2d node3, Point2d node4) + { + vertex1 = node1.ToPoint3d(); + AddVertice(node1); + vertex2 = node2.ToPoint3d(); + AddVertice(node2); + vertex3 = node3.ToPoint3d(); + AddVertice(node3); + vertex4 = node4.ToPoint3d(); + AddVertice(node4); + CalcQuadrangle(); + IsValid = true; + } + + public void CalcQuadrangle() + { + double ang1, ang2, ang3, ang4; + ang1 = vertex1.AngleTo(vertex4, vertex2); + ang2 = vertex2.AngleTo(vertex1, vertex3); + ang3 = vertex3.AngleTo(vertex2, vertex4); + ang4 = vertex4.AngleTo(vertex3, vertex1); + MaxAngleDeg = Math.Max(Math.Max(Math.Max(ang1, ang2), ang3), ang4); + CalcPolygon(); + } + } +} diff --git a/Geometry/Triangle.cs b/Geometry/Triangle.cs new file mode 100644 index 0000000..933e285 --- /dev/null +++ b/Geometry/Triangle.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class Triangle : Polygon + { + private Point3d vertex1; + private Point3d vertex2; + private Point3d vertex3; + + public Point3d Vertex1 { get => vertex1; set { vertex1 = value; Vertices[0] = vertex1; CalcTriangle(); } } + public Point3d Vertex2 { get => vertex2; set { vertex2 = value; Vertices[1] = vertex2; CalcTriangle(); } } + public Point3d Vertex3 { get => vertex3; set { vertex3 = value; Vertices[2] = vertex3; CalcTriangle(); } } + public double MaxAngleDeg { get; private set; } + + public Triangle(Point3d node1, Point3d node2, Point3d node3) + { + vertex1 = node1; + AddVertice(vertex1); + vertex2 = node2; + AddVertice(vertex2); + vertex3 = node3; + AddVertice(vertex3); + CalcTriangle(); + } + + public Triangle(Point2d node1, Point2d node2, Point2d node3) + { + vertex1 = node1.ToPoint3d(); + AddVertice(vertex1); + vertex2 = node2.ToPoint3d(); + AddVertice(vertex2); + vertex3 = node3.ToPoint3d(); + AddVertice(vertex3); + CalcTriangle(); + } + + public void CalcTriangle() + { + //Edge1 = new Line3d(vertex1, vertex2); + //Edge2 = new Line3d(vertex2, vertex3); + //Edge3 = new Line3d(vertex3, vertex1); + //Centroid = new Point3d((vertex1.X + vertex2.X + vertex3.X) / 3, (vertex1.Y + vertex2.Y + vertex3.Y) / 3, (vertex1.Z + vertex2.Z + vertex3.Z) / 3); + //Point3d minPt, maxPt; + //minPt = new Point3d( + // Math.Min(Math.Min(vertex1.X, vertex2.X), vertex3.X), + // Math.Min(Math.Min(vertex1.Y, vertex2.Y), vertex3.Y), + // Math.Min(Math.Min(vertex1.Z, vertex2.Z), vertex3.Z)); + //maxPt = new Point3d( + // Math.Max(Math.Max(vertex1.X, vertex2.X), vertex3.X), + // Math.Max(Math.Max(vertex1.Y, vertex2.Y), vertex3.Y), + // Math.Max(Math.Max(vertex1.Z, vertex2.Z), vertex3.Z)); + //BoundingBox = new BoundingBox2d(minPt.ToPoint2d(), maxPt.ToPoint2d()); + double ang1, ang2, ang3; + ang1 = vertex1.AngleTo(vertex3, vertex2); + ang2 = vertex2.AngleTo(vertex1, vertex3); + ang3 = vertex3.AngleTo(vertex2, vertex1); + MaxAngleDeg = Math.Max(Math.Max(ang1, ang2), ang3); + CalcPolygon(); + } + } +} diff --git a/Geometry/UnitsEnums.cs b/Geometry/UnitsEnums.cs new file mode 100644 index 0000000..83c47e4 --- /dev/null +++ b/Geometry/UnitsEnums.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +public enum UnitsLin { м = 1, см = 2, мм = 3, _ = 0 } +public enum UnitsArea { м = 1, см = 2, мм = 3, _ = 0 } +public enum UnitsForce { т = 1, кН = 3, Н = 4, кг = 2, _ = 0 } +public enum UnitsStress { т = 1, кН = 2, Н = 3, МПа = 4, кПа = 5, _ = 0 } +public enum UnitsList { _, м, см, мм, т, кг, Н, кН, кПа, МПа, градус, rad } diff --git a/Geometry/Vector.cs b/Geometry/Vector.cs new file mode 100644 index 0000000..e290c87 --- /dev/null +++ b/Geometry/Vector.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Geo +{ + [Serializable] + public class Vector : IVector + { + double[] arr; + int n; + + public int N { get => n; } + public double this[int i] { get => arr[i]; set => arr[i] = value; } + + public Vector(int N) + { + n = N; + arr = new double[N]; + } + + public Vector(Vector source) + { + n = source.N; + arr = new double[source.N]; + arr = (double[])source.arr.Clone(); + } + + public Vector(Vector3d source) + { + n = 3; + arr = new double[n]; + arr[0] = source.Vx; + arr[1] = source.Vy; + arr[2] = source.Vz; + } + + public Vector(double[] source) + { + n = source.Length; + arr = new double[source.Length]; + arr = (double[])source.Clone(); + } + + public double[] ToArray() + { + return arr; + } + + public Vector3d ToVector3d() + { + return new Vector3d { Vx = arr[0], Vy = arr[1], Vz = arr[2] }; + } + } +} diff --git a/Geometry/Vector2d.cs b/Geometry/Vector2d.cs new file mode 100644 index 0000000..e32b749 --- /dev/null +++ b/Geometry/Vector2d.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static System.Math; + +namespace Geo +{ + [Serializable] + public class Vector2d + { + double[] arr = new double[2]; + + public double this[int i] { get => arr[i]; set => arr[i] = value; } + public double Vx { get => arr[0]; set => arr[0] = value; } + public double Vy { get => arr[1]; set => arr[1] = value; } + public double Norma { get => Sqrt(Pow(Vx, 2) + Pow(Vy, 2)); } + public double[] Unit { get => new double[] { Vx / Norma, Vy / Norma }; } + + public Vector2d() + { + arr = new double[3]; + } + + public Vector2d(double v1, double v2) + { + arr = new double[2]; + arr[0] = v1; arr[1] = v2; + } + + public Vector2d(Vector2d source) + { + arr = new double[3]; + arr = (double[])source.arr.Clone(); + } + + public Vector2d(Point2d source) + { + arr = new double[2]; + arr[0] = source.X; arr[1] = source.Y; + } + + public Vector2d(Vector source) + { + arr = new double[2]; + if (source.N >= 2) + { + arr[0] = source[0]; arr[1] = source[1]; + } + } + + public Vector2d(double[] source) + { + arr = new double[2]; + if (source.Length >= 2) + { + arr[0] = source[0]; arr[1] = source[1]; + } + } + + public static double CosAngleBetVectors(Vector2d v1, Vector2d v2) + { + return (v1.Vx * v2.Vx + v1.Vy * v2.Vy) / (Sqrt(v1.Vx * v1.Vx + v1.Vy * v1.Vy) * Sqrt(v2.Vx * v2.Vx + v2.Vy * v2.Vy)); + } + + public double[] ToArray() + { + return arr; + } + + public Vector ToVector() + { + return new Vector(arr); + } + + public static Vector3d operator ^(Vector2d v1, Vector2d v2) + { + Vector3d tempV1 = new Vector3d(v1); Vector3d tempV2 = new Vector3d(v2); + return new Vector3d + { + Vx = tempV1.Vy * tempV2.Vz - tempV1.Vz * tempV2.Vy, + Vy = tempV1.Vz * tempV2.Vx - tempV1.Vx * tempV2.Vz, + Vz = tempV1.Vx * tempV2.Vy - tempV1.Vy * tempV2.Vx + }; + } + + public static Vector2d operator *(Vector2d v1, Vector2d v2) + { + return new Vector2d + { + Vx = v1.Vx * v2.Vx, + Vy = v1.Vy * v2.Vy + }; + } + } +} diff --git a/Geometry/Vector3d.cs b/Geometry/Vector3d.cs new file mode 100644 index 0000000..3a7aac8 --- /dev/null +++ b/Geometry/Vector3d.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static System.Math; + +namespace Geo +{ + [Serializable] + public class Vector3d : IVector + { + double[] arr; + int n = 3; + + public double this[int i] { get => arr[i]; set => arr[i] = value; } + public double Vx { get => arr[0]; set => arr[0] = value; } + public double Vy { get => arr[1]; set => arr[1] = value; } + public double Vz { get => arr[2]; set => arr[2] = value; } + public double Norma { get => Sqrt(Pow(Vx, 2) + Pow(Vy, 2) + Pow(Vz, 2)); } + public double[] Unit { get => new double[] { Vx / Norma, Vy / Norma, Vz / Norma }; } + public int N { get => n; } + + public Vector3d() + { + arr = new double[3]; + } + + public Vector3d(Vector3d source) + { + arr = new double[3]; + arr = (double[])source.arr.Clone(); + } + + public Vector3d(Point3d source) + { + arr = new double[3]; + arr[0] = source.X; arr[1] = source.Y; arr[2] = source.Z; + } + + public Vector3d(Vector source) + { + arr = new double[3]; + if (source.N >= 3) + { + arr[0] = source[0]; arr[1] = source[1]; arr[2] = source[2]; + } + } + + public Vector3d(Vector2d source) + { + arr = new double[3]; + arr[0] = source.Vx; + arr[1] = source.Vy; + arr[2] = 0; + } + + public Vector3d(double[] source) + { + arr = new double[3]; + if (source.Length >= 3) + { + arr[0] = source[0]; arr[1] = source[1]; arr[2] = source[2]; + } + } + + public static double CosAngleBetVectors(Vector3d v1, Vector3d v2) + { + return (v1.Vx * v2.Vx + v1.Vy * v2.Vy + v1.Vz * v2.Vz) / (Sqrt(v1.Vx* v1.Vx + v1.Vy* v1.Vy+ v1.Vz * v1.Vz) * Sqrt(v2.Vx * v2.Vx + v2.Vy * v2.Vy + v2.Vz * v2.Vz)); + } + + public double[] ToArray() + { + return arr; + } + + public Vector2d ToVector2d() + { + return new Vector2d() { Vx = Vx, Vy = Vy }; + } + + public Vector ToVector() + { + return new Vector(arr); + } + + public static Vector3d operator ^(Vector3d v1, Vector3d v2) + { + return new Vector3d + { + Vx = v1.Vy * v2.Vz - v1.Vz * v2.Vy, + Vy = v1.Vz * v2.Vx - v1.Vx * v2.Vz, + Vz = v1.Vx * v2.Vy - v1.Vy * v2.Vx + }; + } + + public static Vector3d operator *(Vector3d v1, Vector3d v2) + { + return new Vector3d + { + Vx = v1.Vx * v2.Vx, + Vy = v1.Vy * v2.Vy, + Vz = v1.Vz * v2.Vz + }; + } + } +} diff --git a/Grapfics/CanvasDrafter.cs b/Grapfics/CanvasDrafter.cs new file mode 100644 index 0000000..464a3cd --- /dev/null +++ b/Grapfics/CanvasDrafter.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Shapes; +using AForge.Math.Geometry; +using AForge; +using netDxf.Entities; +using Point = System.Windows.Point; + +namespace GroundOrganizer +{ + public partial class CanvasDrafter + { + //const double WXMIN = -300; + //const double WXMAX = 300; + //const double WYMIN = -300; + //const double WYMAX = 300; + const double DMARGIN = 0; + + static Matrix WtoDMatrix; + static Matrix DtoWMatrix; + + static public void DrawPolygonsFromDxfLwPolyline(IEnumerable dxfEntitys,Canvas canvas, double h) + { + double dxmin = DMARGIN; + double dymin = DMARGIN; + double dymax = h - DMARGIN; + + double wxmin; + double wxmax; + double wymin; + double wymax; + + List dxfVertices = new List(); + foreach (LwPolyline item in dxfEntitys) + { + dxfVertices.AddRange(item.Vertexes); + } + + IOrderedEnumerable selected = from x in dxfVertices // определяем каждый объект как x + orderby x.Position.X // упорядочиваем по возрастанию + select x; // выбираем объект + wxmin = selected.First().Position.X; + wxmax = selected.Last().Position.X; + + selected = from y in dxfVertices orderby y.Position.Y select y; + + wymin = selected.First().Position.Y; + wymax = selected.Last().Position.Y; + + double w = (wxmax - wxmin) / (wymax - wymin)*h; + double dxmax = w - DMARGIN; + + PrepareTransformations(wxmin, wxmax, wymin, wymax, dxmin, dxmax, dymax, dymin); + + Canvas da = canvas; + da.Width = w; + da.Height = h; + + Polygon contour; + foreach (LwPolyline item in dxfEntitys) + { + dxfVertices = item.Vertexes; + Point pt; + contour = new Polygon + { + Points = new PointCollection(), + Stroke = Brushes.Black, + StrokeThickness = 2, + Fill = Brushes.White + }; + foreach (LwPolylineVertex v in dxfVertices) + { + pt = WtoDMatrix.Transform(new Point(v.Position.X, v.Position.Y)); + contour.Points.Add(pt); + } + da.Children.Add(contour); + //da.Children.Add(new Rectangle() { Width = 80, Height = 80,Stroke=Brushes.Black,StrokeThickness=1,Fill=Brushes.White }); + } + } + + static public void DrawFoundations(ObservableCollection founds, Canvas canvas, double h) + { + double dxmin = DMARGIN; + double dymin = DMARGIN; + double dymax = h - DMARGIN; + + double wxmin; + double wxmax; + double wymin; + double wymax; + + List Vertices = new List(); + foreach (Foundation item in founds) + { + if (item.Contour != null) Vertices.AddRange(item.Contour.Vertices); + } + + if (Vertices.Count < 4) return; + IOrderedEnumerable selected = from x in Vertices // определяем каждый объект как x + orderby x.X // упорядочиваем по возрастанию + select x; // выбираем объект + + wxmin = selected.First().X; + wxmax = selected.Last().X; + + selected = from y in Vertices orderby y.Y select y; + + wymin = selected.First().Y; + wymax = selected.Last().Y; + + double w = (wxmax - wxmin) / (wymax - wymin) * h; + double dxmax = w - DMARGIN; + + PrepareTransformations(wxmin, wxmax, wymin, wymax, dxmin, dxmax, dymax, dymin); + + Canvas da = canvas; + da.Width = w; + da.Height = h; + + Polygon contour; + foreach (Foundation item in founds) + { + if (item.Contour == null) continue; + ToolTip toolTip = new ToolTip(); + StackPanel toolTipPanel = new StackPanel(); + DataGrid props = new DataGrid() { ItemsSource = item.SmallProps, FontSize = 11 }; + //DataGrid results = new DataGrid() { ItemsSource = item.SmallResults}; + toolTipPanel.Children.Add(props); + //toolTipPanel.Children.Add(results); + toolTip.Content = toolTipPanel; + Vertices = item.Contour.Vertices; + Point pt; + contour = new Polygon + { + Points = new PointCollection(), + Stroke = Brushes.Black, + StrokeThickness = 2, + Fill = Brushes.White + }; + ToolTipService.SetToolTip(contour, toolTip); + ToolTipService.SetShowDuration(contour, int.MaxValue); + + foreach (Geo.Point3d v in Vertices) + { + pt = WtoDMatrix.Transform(new Point(v.X, v.Y)); + contour.Points.Add(pt); + } + da.Children.Add(contour); + + //da.Children.Add(new Rectangle() { Width = 80, Height = 80,Stroke=Brushes.Black,StrokeThickness=1,Fill=Brushes.White }); + } + } + static public void DrawFoundationsNumbers(ObservableCollection founds, Canvas canvas) + { + double dxmin = DMARGIN; + double dymin = DMARGIN; + double dymax = canvas.ActualHeight - DMARGIN; + double dxmax = canvas.ActualWidth - DMARGIN; + + double wxmin; + double wxmax; + double wymin; + double wymax; + + List Vertices = new List(); + foreach (Foundation item in founds) + { + if (item.Contour != null) Vertices.AddRange(item.Contour.Vertices); + } + + if (Vertices.Count < 4) return; + IOrderedEnumerable selected = from x in Vertices // определяем каждый объект как x + orderby x.X // упорядочиваем по возрастанию + select x; // выбираем объект + + wxmin = selected.First().X; + wxmax = selected.Last().X; + + selected = from y in Vertices orderby y.Y select y; + + wymin = selected.First().Y; + wymax = selected.Last().Y; + + PrepareTransformations(wxmin, wxmax, wymin, wymax, dxmin, dxmax, dymax, dymin); + + Canvas da = canvas; + + Label label; + foreach (Foundation item in founds) + { + Point pt = WtoDMatrix.Transform(new Point(item.X, item.Y)); + label = new Label + { + Content = item.Number.ToString(), + VerticalContentAlignment = VerticalAlignment.Center, + HorizontalContentAlignment = HorizontalAlignment.Center + }; + Canvas.SetTop(label, pt.Y); + Canvas.SetLeft(label, pt.X); + da.Children.Add(label); + + //da.Children.Add(new Rectangle() { Width = 80, Height = 80,Stroke=Brushes.Black,StrokeThickness=1,Fill=Brushes.White }); + } + } + + static void PrepareTransformations(double wxmin, double wxmax, double wymin, double wymax, double dxmin, double dxmax, double dymin, double dymax) + { + // Make WtoD. + WtoDMatrix = Matrix.Identity; + WtoDMatrix.Translate(-wxmin, -wymin); + + double xscale = (dxmax - dxmin) / (wxmax - wxmin); + double yscale = (dymax - dymin) / (wymax - wymin); + WtoDMatrix.Scale(xscale, yscale); + + WtoDMatrix.Translate(dxmin, dymin); + + // Make DtoW. + DtoWMatrix = WtoDMatrix; + DtoWMatrix.Invert(); + } + + + } +} diff --git a/Grapfics/RenderVisualService.cs b/Grapfics/RenderVisualService.cs new file mode 100644 index 0000000..fd66f15 --- /dev/null +++ b/Grapfics/RenderVisualService.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace GroundOrganizer +{ + public static class RenderVisualService + { + private const double defaultDpi = 96.0; + + public static ImageSource RenderToPNGImageSource(Visual targetControl) + { + var renderTargetBitmap = GetRenderTargetBitmapFromControl(targetControl); + + var encoder = new PngBitmapEncoder(); + encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap)); + + var result = new BitmapImage(); + + using (var memoryStream = new MemoryStream()) + { + encoder.Save(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + + result.BeginInit(); + result.CacheOption = BitmapCacheOption.OnLoad; + result.StreamSource = memoryStream; + result.EndInit(); + } + + return result; + } + + public static void RenderToPNGFile(Visual targetControl, string filename) + { + var renderTargetBitmap = GetRenderTargetBitmapFromControl(targetControl); + + var encoder = new PngBitmapEncoder(); + encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap)); + + var result = new BitmapImage(); + + try + { + using (var fileStream = new FileStream(filename, FileMode.Create)) + { + encoder.Save(fileStream); + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"There was an error saving the file: {ex.Message}"); + } + } + + private static BitmapSource GetRenderTargetBitmapFromControl(Visual targetControl, double dpi = defaultDpi) + { + if (targetControl == null) return null; + + var bounds = VisualTreeHelper.GetDescendantBounds(targetControl); + var renderTargetBitmap = new RenderTargetBitmap((int)(bounds.Width * dpi / 96.0), + (int)(bounds.Height * dpi / 96.0), + dpi, + dpi, + PixelFormats.Pbgra32); + + var drawingVisual = new DrawingVisual(); + + using (var drawingContext = drawingVisual.RenderOpen()) + { + var visualBrush = new VisualBrush(targetControl); + drawingContext.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size)); + } + + renderTargetBitmap.Render(drawingVisual); + return renderTargetBitmap; + } + } +} diff --git a/GroundOrganizer.csproj b/GroundOrganizer.csproj new file mode 100644 index 0000000..8f3573a --- /dev/null +++ b/GroundOrganizer.csproj @@ -0,0 +1,312 @@ + + + + + Debug + AnyCPU + {82435CCA-41F6-4074-8C93-A3DCDF9BA0E5} + WinExe + GroundOrganizer + GroundOrganizer + v4.7.2 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Resources\business-color_books_icon-icons.com_53474.ico + + + + ..\packages\AForge.2.2.5\lib\AForge.dll + + + ..\packages\AForge.Math.2.2.5\lib\AForge.Math.dll + + + ..\packages\EPPlus.4.5.3.2\lib\net40\EPPlus.dll + + + ..\packages\netDXF.2.2.0.1\lib\net45\netDxf.dll + + + + + + + + + + + + + + + 4.0 + + + ..\..\..\..\OneDrive\Documents\C#\triangle\sourceCode\sourceCode\Triangle.NET\Triangle\bin\Debug\Triangle.dll + + + + + + + + MSBuild:Compile + Designer + + + + + FoundPropWindow.xaml + + + + + + + + + MainPage.xaml + + + TestWindow.xaml + + + + + + CanwasWindow.xaml + + + + ImageWindow.xaml + + + + AlertWindow.xaml + + + + + + + + + + + + + + + + + + + + + FoundationsPage.xaml + + + StructuresPage.xaml + + + + + + + + + + BoresPage.xaml + + + ResultsPage.xaml + + + IGEsPage.xaml + + + PlayGroundsPage.xaml + + + + + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + + MainWindow.xaml + Code + + + Designer + MSBuild:Compile + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GroundOrganizer.sln b/GroundOrganizer.sln new file mode 100644 index 0000000..06ad610 --- /dev/null +++ b/GroundOrganizer.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35303.130 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GroundOrganizer", "GroundOrganizer.csproj", "{82435CCA-41F6-4074-8C93-A3DCDF9BA0E5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {82435CCA-41F6-4074-8C93-A3DCDF9BA0E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {82435CCA-41F6-4074-8C93-A3DCDF9BA0E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {82435CCA-41F6-4074-8C93-A3DCDF9BA0E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {82435CCA-41F6-4074-8C93-A3DCDF9BA0E5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {94A84522-F2BC-4F49-9D2C-711A3AAAD4BA} + EndGlobalSection +EndGlobal diff --git a/Images/Bookmark-add-icon32.png b/Images/Bookmark-add-icon32.png new file mode 100644 index 0000000000000000000000000000000000000000..84ecc4e468942ec073135a5da463d3d08109ae0e GIT binary patch literal 1508 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 UFe_mx6#xJL07*qoM6N<$f+~jNcmMzZ literal 0 HcmV?d00001 diff --git a/Images/Save_as-80_icon-icons.com32.png b/Images/Save_as-80_icon-icons.com32.png new file mode 100644 index 0000000000000000000000000000000000000000..a430f9d5dee618c5d77c679a70433c8230897848 GIT binary patch literal 961 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 literal 0 HcmV?d00001 diff --git a/Images/icons8-export-csv-32.png b/Images/icons8-export-csv-32.png new file mode 100644 index 0000000000000000000000000000000000000000..d251da246039ca0ebd65fd0f1773c303b8844865 GIT binary patch literal 1122 zcmV-o1fBbdP)?^OO+ZUnIzmo3L{Nm2 zqd7uMS7UJ`Nl89ORas_qKT24HmZXK2rF)r*a;1rcm8EZci-eV>c#EEDnudCqm~WYj zca54mMNVC5cREE(x$NWPPuYhP9af|NeA=kYAj4`u+M}op=2G z{c@;>fwGjBzox?3%V(i}w9&uj^yh!DlEmB1g|wHs!_4>l_prmlW}$syo_VIov$Dy; z{{H@tx}Rd7dTFD8X`_GP?dHGO$(gCSlA*G#xx5-R$pvn zpnJyL&alqBbE$}%!K%5#%j4(jbAXR-ri4ygWj8`kgS3^Wudwj;^2y%Oz1qc6Txk0I z`+TmC)8yIP>EMXAnsR}Hez1{ws*Plydz8JTfU%RW$-Mpk{g9urVxD=JsJX}8(8b%% zy41vklA(>cp2ytJ_WAeGUvzFB5+FfaPR9m`TZO4 z2lMc$$ISlv@c7_}^ug6~8u+x=fumv3THOEu0mn&1K~y-)V_+Z*xY&__iUNiLjzB#m zke4cjp+H|73Fs%XvEo-?VS}y$U4b^b3ZMdOLqjudZ8Jk404hLN0aV~(WMrxD;q>Tbr6% zYir9R6eu?uU;&B<1)MrMI!z%uAP}-#M`uG!s7_RjD&`noJ$%xCrfaYgTHn z(wRS_14V(Kc5}71r_N06W$x=&=&X*@nKe-dMS+91y>pJYPJni#j(fDul33RXVHgTP zE^wXh78|x!XMvlac1fBH76m#w(Mz=#>3F+&m02ZAGchqCDKH52@z81UiPBj-Pe-S= zD$B~w$;n9!uE4#`zsJ!-ry*j}RL4FYooww~D?43XT^2+*1ax;r0&S@C@Am{!_T`1> z3NQeQ0;N`C3{X*oqyRO#f$7G?#7sK_RRL0h(bf(sEv`&Y0V)t-VG-oRNOIcRzJ~P$ zx)315EQ(dZl*zqd`2>DptX3EqZJyf>l#k~Tz>@4CVB?%lU0rcrY*`NiwrrZMD<^?9 o^Fn~8mWCQLH{LwYt*#2D0X7Poj()p(Bme*a07*qoM6N<$f)2AxjsO4v literal 0 HcmV?d00001 diff --git a/Images/icons8-import-csv-32.png b/Images/icons8-import-csv-32.png new file mode 100644 index 0000000000000000000000000000000000000000..3a1c8a4f0a66bcaa6f1dac3f4882124897be9f2b GIT binary patch literal 1021 zcmV>NBR#u#tKdv&U{!H}(|o~VzGo~(GLkGH|f ze5aJwczV=WSg*aw|NsA9oObt*kAAO_)$G^t`SQQl$m8?n$mYuQ`t{!M-{k1)>GkT! z(AVzx@8ye&)9ck=oOgY%kcPCF{Qdpv?eFIF=jrV4`u+O%`}cvelwX~9{{Q}Iqkm$a zd2gnLvCqA3ri8-T%YU$v#M{lr+|FmAe%a>W$K20ho_W96$#bcQ)8*M@pL@F1#BHU5 z{Qdm)jg94jf#;c--j$KpkB9Y*jq!+w(ypTEf`H_LfZ&3G?(F8qkATLfn$LiD$;!0N z)Y@yMfRDJAda;Yi-qD-Es<6(ydaaJ|_VW7t``hW@rO30P#jmQ%w)Xk=(BjvRx}UVs zzjCODe6EkW)Wp-|*_6Gcg|wHKzove$k!GQNn82s``})h@)AsuJg0hulpnIpuw4lYV z_xkzN<=Vc-&yTvGVxM~9?dF}stmNEWBgs&%S~@%HnK zxSfBolBfdT)c^nhD0EUzQvjni;Na5pg{0d|)BU*v@`&qa6qIGqA>Q8p&-4Dwy84jm z!qD!;qR1GSBme*br%6OXR5;6()Av&oK^VsI1QV1dDyV=Wh^X(g+<7S&3B*8psDT7X zR6r3G5Cy?PvtS2Qs-W2ZR`=pK#}y{S_otiL&&=)YzH2gNF883SvpR5yRF$2`04`s( zW&orWI-nICxCFsLM{}$S(5IKrJ|^wb|;3>TEn(amtOJQUSXp)p92B zs4>>v9dkO*>4LS0x31+sSocS|t%atX<=N&ke^!v9T^aq=9e3^j?G*G=e(Shi%NI21h-u1xr6CIFu5ZOs>{{~h) zt@Owc06*JP&FJv7OuBLUqzcq@&H3@}6a2IYJf3QYyRziC0_Ht!FM@tNd%xWIF$7G| zIL6A^fh^@57TP*zfxy!b@mBt$`iIRAh6fnSD^dx3G5c^+xqneQ;@2&p68`t^jQM1{6#0Ut2m#%PNF`h~CiK0&n r^z9319&fsf=XU|aE?6vgxRd)A4KgIJ_sawCMNj-f1gcm$&i0r=5q(4RgO#|MUZ~Zbu(g zo@)wJyv(&Fty5%LcG$@{)k1?@@%pcmT!WW}8{Lsgvbr>TN!9se%i=301v}OWiGDnO zS28rRqubPZ#=;k?`t}{%nsSlX-XURI#>3~bSz`OMY%V9O1jSdYI zXlpONQM#-9-Me>rnT*UlA-j$&U}-kUcmou8_ijf0<6G<@A1-oVyL#q(-TAo9*UvEc zJbt4Wtp6%L>GnJ`iC_F#5AXL_ovYjHcS=#~&;Mh3q04U^U7aYqHD~Rt&Fh!%c)m5b zVwaQL1l7&}MawJf4Her8G)jf?ol2@}>f^pooU|?C%oCS;PV3KvZZ0)X!sfL?{^=2`q z)z?`442q}AzkaYrQFzoWOCT2z+uF+FvWl`jMrt?{w!&N#yu@hJV-w1b}+v!=VRyl9an z?zF_VuFbcil_k_Mjqhy=S11m@{fvgs)4d^ zUpRcm zFDAX?{1Do8vhg{qOQEY{it5Z=JE!R9?`WP~6mwCz{6%-i?-h=Jr#(7r)VWF|p^QCj z_UxZcse5NIWj(3hW*A>#nI(3#>*9-TjZP`gX0A7>$gHyXW5{E0VA;pDaScV!Cv5dR z9sEYD?|byhYxT}i#%c|F%()LPnwWc0?MGB|f70{y6HiY|5l!o;K66dvEQ0y7>{y<(m~h ZIOlyl-5c7hwhdI&c)I$ztaD0e0syNu06G8w literal 0 HcmV?d00001 diff --git a/Images/icons8-mesh-32.png b/Images/icons8-mesh-32.png new file mode 100644 index 0000000000000000000000000000000000000000..ad9e40f5a63c05c9084084bfb856f74931d988ee GIT binary patch literal 1321 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabRA=0VEh!|6XNP#-~$vH1tTW}4xY06 z2=wi;k|4ie21Bk8HiKwJW~O=(z0;!Hyjsq|%C3^~;#r{*7P4-vN> zt(H3|r0yxE60^%($J;A%7JH|yzD?~0-vv$;nRbDkc?rwZj>O9NDIATfTg zYR|d(4i~fq&rdV*KTzjmy04(I{P4f1h%F7m7p<4?4l`S2yvV&|(#=H8v{RRFRUL1d zsX_;~as7`}6P53rO0wVr}!iw$|;|3=B*To-U3d7N^$+hej(q3amMiR{l8e zNGpf9^P~ryD($;>ThG~D`0m}i@Amm-oa{1pY%lU(z8w7ZYmIFvvrNVZ=CG&r3EOJl z?fu_;-MVi7;tczkzbnd|R)72%#BS^j8hfqC7VjvE?& zSE9R_v~1Wz^y6E2tqWgvGO|u@oy9u!@5-~8A}WtAAGYR5*Ey4@XU|e1bGhZ%v0EQ= z_v}oba4hhF&dt}ii`}nYJz=rEz$!*e`K|A!n9x(YNgW2!dtD9g9}%6jLM^UaE@QFa zF5V1B|IeQ*Hl8`LtTAvkhs4Wn$NO&;mfsXPvdBj9qU&a%7`t|%JU-7)DgR_QzgT@j zIOd(u&W2YDPaaiqYV(qr-aVz~-14H`MJ==HHVeEmT+qVSGiBjS_9~;7AIvkt?mvyL zFnscClLN$&c~=$e+MDEB=)+x#wmh?rY^^WDS1*!m-<{Br;N*yos1U@+&~(fmuHe|A~_-Fv%e z-CvoNUbiFHw0jt4YU(PpmCe8R@_PQ$#XdR<4j<>xi3(rM_Q!j9S)|{-8A{n3rq2p@ z?M!~>wQSWtqqlFC&+IW-8Tdo`)K>E<7tyEHIlk7@pJkQW-E-Od^3l%?3HRp*U;gA% nmj5wo@|2(7-*<^TJn-23l4G>z+msV$L3!QN)z4*}Q$iB}D};FI literal 0 HcmV?d00001 diff --git a/Images/icons8-mesh-80_ed1.png b/Images/icons8-mesh-80_ed1.png new file mode 100644 index 0000000000000000000000000000000000000000..f54f55921fa875d7b4bf41c67e6c7d44e8d11050 GIT binary patch literal 1721 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 literal 0 HcmV?d00001 diff --git a/Images/interfaceDXF.png b/Images/interfaceDXF.png new file mode 100644 index 0000000000000000000000000000000000000000..2f225352945bf96ad10c0c4191c547ecddb58401 GIT binary patch literal 855 zcmV-d1E~CoP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0_;gdK~z{rt=C7$ zR96^>@v#s!h!MpG5j7A*5EMjW*(io6A_fIP=2sGV|T}?*0DoV{X6iE$7@bl{)zzFY#Xqi%~fHaS0O& zx(SPzjY6@2qt(emIfu9tQ(e&7?8C|GWTBi#6z~Qk(WO3go7x0)9dq z>@faG=5L`rhT=!q0#X)c3(HMQ1^kUTq0joaWL}feD2H&MI@xj>6<~8pPqrK1W|o~m zqZ~)6JFp$;$?WyaX~eRR7>s%;RX}gNLY(M2+QCdmEZ17pOQ`}DAU(-kM83dX#JYdc z4cQbfz@~Qxaf0Xg5^0tq)@v5BDO^A=yv1vHr5oWR`5Hd&0kvuS{V3oHvMKclY(DSs z6ffXOyc4@H7RFW)1!x@7lqz5v;=qsKi#7~t#vm==4B|yKr3&yp*aHU{evBGr4wlp` zf-h*KQ~_;~rVIE3Wky7e(sWn64G&-;2XUmv19%1UKz@u|pPi5C;C>#H?~+j-aA?kv0uuJdK>iXpHGyWLjgCM}>R`eQE^ z!r1&==NoVQEDypraCv+S=3@ga?gI)H;8oet#QZXtKjAQ}AM6Ef?_Ryztby^rMeG+^ zT|i%am&`}=^d!#z`f0A(>%}(fT|hdZBPJr&6)IpzaU#BoAX1=v(#hxkL`tu#Ik2O|zfP4xdO zKh0Gtf8qD)&3)-&i0%vNfb}+>)TZnG!`_M9{D5c3 h?p&6~oP;Em%Ks3ocGKRvOv(TN002ovPDHLkV1jw2hD87X literal 0 HcmV?d00001 diff --git a/Images/table_1061_32.png b/Images/table_1061_32.png new file mode 100644 index 0000000000000000000000000000000000000000..8569283757357c9a66a2d17e80d09a69f8fb2e62 GIT binary patch literal 1158 zcmV;11bO?3P)=?()D z8bH}P`$EJoh{SL~;)cY9D@VlNLqa*DL4sUH8U&*uFe4Ju=}t142(t8M7YDc9-g*g? zRI*+ET=iDfTc2$qEsp8LfMCkCV?`3@Yry)H&-uVp;Pw9n;3dxIpFaQd+dF1ULzCs7 zFgQQ@<=4+Yd;A4(IYkT^VGptZxa}I3o!&%`H+Me33b1g`pvik@z%y^m!jba9>h8{y zpPS!}4khU`Nv;y+->vZVS6_a!zrX+dKLNPunB0tAQP4U-1>UYYR2`}+kZFMkxCraG zB2K>~mYK4nQc`Z(K93%jV|xm~!aK@l)k8!OkpZauagrw20rUey5IiTedqJ3K5rE`F zlY*=2l)=HN;5h}r4+5%{;dYbb!1q7=NUb(IbgBXfo%S8o+H4#+I(FJ^sH%~U+i0+8gu6qGdE3MptsI0J$T_`WeHA_%CYshb0U+>dmc>AjhSK~)G0 zR71P(8=gu!!=e_n8pk{+I~X`uQACxCvj)|f5~_lT#>Y3WTQp}%F(5xMM1;Su&bgck zCkhezzESoRPyF!!cDGjeXm>Y9su!~*KHS;Kk?^;}3R{~S00d@qdI2RT9353yU0DI3 z+Y3+y&nZX8$D>%<#?PF%+4=0bxY1HNOXh4vDh|C^?Ni zMW9MfQvS!b;OO`m&vU41O8+`(;CWtr9Rd&CeYJ>Mufje(w>ouMjp`^HSkfrQz2 zd)@H>mY3`7Y;UImsVdGnwl+6Y*+(U<*Ov(l%HFV`f-pZHzO6ksw4XE@<6EGa-WG8n zDFy^aIATc|OoYqW$8uoQo?b*a2niNun;UP;h})5hF^L1mCnq@1!(}+oIBnv2E(Inq z!d{EwToR;kc7B12IDy0*==FNz0n`_l*xuZXdmpKDj*a!S6~`uP@Foa07c}GlQ$EH^YyXL1Yo3*YA%9@X6zkQ}Z9`#`;>EVU$S_ z81<#4R91aIKvh^=m@BM6R_^~*91=Pl!OYt=981Y@Vrl@bR*T!)+uZDqk}zB{cvzuH zkDFOMj>)CFdwYAImdoXARm99BbDj#Jn&Pqnh=?VxvvP27@YD76^^>F{2h@PlKr4e| zd7!0?dJO-j1HvEHKF~{OH*xGHu6sZm=x2*1grgZb_cH1ds)h($07*qoM6N<$f&)t#)&Kwi literal 0 HcmV?d00001 diff --git a/Images/text-list-numbers-icon32.png b/Images/text-list-numbers-icon32.png new file mode 100644 index 0000000000000000000000000000000000000000..c6df6870926c152c2723b2b2ddf56d0ba95bce12 GIT binary patch literal 1167 zcmV;A1aSL_P)Kltpbxpd z30?{|kQeD6Ab73Rk{C@$y4ltw?j<|3voquGcXno)$U*5Q8-L;C>}B?x&-tD2_xxrQ z0Q%hA+*gXCJn#EHf*?REgXV#%syxrN$;rv{3VoKDpPw&|kB_%>;(x}%!U85HCbA6B zGdnw5AR4UxzD9(totP6mGCTyzI;N(kdU?9unVFd_dV@dK)AoV0M^zwXn$Ip0^biXG&mp!Sl`%$8m^xI^Gj}=HvfpU>C<3?1O0M zbQQlA9E^6GaQy&BVG!Pef&P?h|r=yW87{ zhGz{V4Mp^>2UH2b^$u?X9^ph+mmFYwXD1esNfST);Rg<#Q?CkEwd#DpY8)-nbR19Cdft9x(f$b^KbVF3L{cCDCERZ@txPXLLtJQ=CI66Bz z-!uB>}+YfCc!%r_0EtO?>k5pb%i)SD~{D!VCoaG7uk=;W>hT z$v`%nkpq-UN1=rWyDfbE+Cy->qtQSnla>RN%as^_>wsoy;e-L|jt8gi zA4xq(r&Dr(N@Xt=5(7N@(M=>th#nQ9#n&H(O;!w=&4AxH12|HtHaWnaT@@S404ze? z&`{X1@x+xI`0er;)awu~xL*XG)^%&BhZ<;0B;^2AQZMH?0(f_E9an$Y#p4eU@$?v7 zs^Q6}&LY#^j%4HjQa{%Pt_9kD7dVZ+T4fg$asB!?LWm5*zm)=r3qk;s&th@rt2le* zJ1o8NC@e##a-cP}1)f)jSNBAEP1BSEaKVTG4AQ`v_r6CiYl_>br8gg=0S=*o&;@)z zaY2&;)M=B&MVxH1f})8Vvrt4nts;_9^T7bRuFC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs new file mode 100644 index 0000000..dfee2f9 --- /dev/null +++ b/MainWindow.xaml.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Runtime.Serialization.Formatters.Binary; +using System.IO; +using System.Collections.ObjectModel; +using System.Windows.Controls.Ribbon; + +namespace GroundOrganizer +{ + /// + /// Логика взаимодействия для MainWindow.xaml + /// + public partial class MainWindow : Window + { + ViewModel vm; + public MainWindow() + { + InitializeComponent(); + vm = DataContext as ViewModel; + Top = 75; + Left = 75; + double ws = SystemParameters.PrimaryScreenWidth; + double hs = SystemParameters.PrimaryScreenHeight; + MaxWidth = ws - Left - 5; + MaxHeight = hs - Top - 40; + //this.SizeToContent = SizeToContent.Height; + Loaded += MainWindow_Loaded; + + } + + private void MainWindow_Loaded(object sender, RoutedEventArgs e) + { + if (File.Exists(Properties.Settings.Default.BasePath) == true) + { + // создаем объект BinaryFormatter + BinaryFormatter formatter = new BinaryFormatter(); + using (FileStream fs = new FileStream(Properties.Settings.Default.BasePath, FileMode.OpenOrCreate)) + { + ViewModel vm = (ViewModel)DataContext; + //ToSerializ ser = (ToSerializ)formatter.Deserialize(fs); + vm.ListPlayGround = formatter.Deserialize(fs) as ObservableCollection; + DataContext = vm; + } + } + } + + private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) + { + vm.ReadDB(); + } + + //private void MainRibbon_SelectionChanged(object sender, SelectionChangedEventArgs e) + //{ + // if(contentFrame!=null) contentFrame.Content = null; + // if (HomeTab.IsSelected && contentFrame != null) contentFrame.Content = new MainPage(); + //} + } +} diff --git a/Pages/BoresPage.xaml b/Pages/BoresPage.xaml new file mode 100644 index 0000000..a57ddea --- /dev/null +++ b/Pages/BoresPage.xaml @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pages/IGEsPage.xaml.cs b/Pages/IGEsPage.xaml.cs new file mode 100644 index 0000000..287381b --- /dev/null +++ b/Pages/IGEsPage.xaml.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace GroundOrganizer +{ + /// + /// Логика взаимодействия для IGEsPage.xaml + /// + public partial class IGEsPage : Page + { + private ViewModel vm; + public IGEsPage() + { + InitializeComponent(); + vm = App.Current.MainWindow.DataContext as ViewModel; + DataContext = vm; + } + + private void ToCSV_Click(object sender, RoutedEventArgs e) + { + vm.SaveIGEsInCsv(); + } + + private void FromCSV_Click(object sender, RoutedEventArgs e) + { + vm.ReadIGEsFromCsv(); + } + } +} diff --git a/Pages/MainPage.xaml b/Pages/MainPage.xaml new file mode 100644 index 0000000..4a1375c --- /dev/null +++ b/Pages/MainPage.xaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pages/MainPage.xaml.cs b/Pages/MainPage.xaml.cs new file mode 100644 index 0000000..9127835 --- /dev/null +++ b/Pages/MainPage.xaml.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace GroundOrganizer +{ + /// + /// Логика взаимодействия для MainPage.xaml + /// + public partial class MainPage : Page + { + public MainPage() + { + InitializeComponent(); + DataContext = App.Current.MainWindow.DataContext; + } + } +} diff --git a/Pages/PlayGroundsPage.xaml b/Pages/PlayGroundsPage.xaml new file mode 100644 index 0000000..361d5a5 --- /dev/null +++ b/Pages/PlayGroundsPage.xaml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pages/PlayGroundsPage.xaml.cs b/Pages/PlayGroundsPage.xaml.cs new file mode 100644 index 0000000..b34d2fd --- /dev/null +++ b/Pages/PlayGroundsPage.xaml.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace GroundOrganizer +{ + /// + /// Логика взаимодействия для PlayGroundsPage.xaml + /// + public partial class PlayGroundsPage : Page + { + private ViewModel vm; + public PlayGroundsPage() + { + InitializeComponent(); + DataContext = App.Current.MainWindow.DataContext; + vm = DataContext as ViewModel; + } + } +} diff --git a/Pages/ResultsPage.cs b/Pages/ResultsPage.cs new file mode 100644 index 0000000..a49cbc3 --- /dev/null +++ b/Pages/ResultsPage.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace GroundOrganizer +{ + /// + /// Логика взаимодействия для CalculationsPage.xaml + /// + public partial class ResultsPage : Page + { + ViewModel vm; + public ResultsPage() + { + InitializeComponent(); + DataContext = App.Current.MainWindow.DataContext; + vm = DataContext as ViewModel; + } + } +} diff --git a/Pages/ResultsPage.xaml b/Pages/ResultsPage.xaml new file mode 100644 index 0000000..be239b0 --- /dev/null +++ b/Pages/ResultsPage.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/Pages/StructuresPage.xaml b/Pages/StructuresPage.xaml new file mode 100644 index 0000000..ddf7bc8 --- /dev/null +++ b/Pages/StructuresPage.xaml @@ -0,0 +1,350 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pages/StructuresPage.xaml.cs b/Pages/StructuresPage.xaml.cs new file mode 100644 index 0000000..59f5400 --- /dev/null +++ b/Pages/StructuresPage.xaml.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace GroundOrganizer +{ + /// + /// Логика взаимодействия для StructuresPage.xaml + /// + public partial class StructuresPage : Page + { + private ViewModel vm; + public StructuresPage() + { + InitializeComponent(); + DataContext = App.Current.MainWindow.DataContext; + vm = DataContext as ViewModel; + } + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8e7085f --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// Общие сведения об этой сборке предоставляются следующим набором +// набор атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("GroundOrganizer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("HP Inc.")] +[assembly: AssemblyProduct("GroundOrganizer")] +[assembly: AssemblyCopyright("Copyright © HP Inc. 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми +// для компонентов COM. Если необходимо обратиться к типу в этой сборке через +// из модели COM, установите атрибут ComVisible для этого типа в значение true. +[assembly: ComVisible(false)] + +//Чтобы начать создание локализуемых приложений, задайте +//CultureYouAreCodingWith в файле .csproj +//в . Например, при использовании английского (США) +//в своих исходных файлах установите в en-US. Затем отмените преобразование в комментарий +//атрибута NeutralResourceLanguage ниже. Обновите "en-US" в +//строка внизу для обеспечения соответствия настройки UICulture в файле проекта. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //где расположены словари ресурсов по конкретным тематикам + //(используется, если ресурс не найден на странице, + // или в словарях ресурсов приложения) + ResourceDictionaryLocation.SourceAssembly //где расположен словарь универсальных ресурсов + //(используется, если ресурс не найден на странице, + // в приложении или в каких-либо словарях ресурсов для конкретной темы) +)] + + +// Сведения о версии для сборки включают четыре следующих значения: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Номер редакции +// +// Можно задать все значения или принять номера сборки и редакции по умолчанию +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs new file mode 100644 index 0000000..712bed2 --- /dev/null +++ b/Properties/Resources.Designer.cs @@ -0,0 +1,140 @@ +//------------------------------------------------------------------------------ +// +// Этот код создан программой. +// Исполняемая версия:4.0.30319.42000 +// +// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае +// повторной генерации кода. +// +//------------------------------------------------------------------------------ + +namespace GroundOrganizer.Properties { + using System; + + + /// + /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д. + /// + // Этот класс создан автоматически классом StronglyTypedResourceBuilder + // с помощью такого средства, как ResGen или Visual Studio. + // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen + // с параметром /str или перестройте свой проект VS. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GroundOrganizer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Перезаписывает свойство CurrentUICulture текущего потока для всех + /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Icon, аналогичного (Значок). + /// + internal static System.Drawing.Icon business_color_books_icon_icons_com_53474 { + get { + object obj = ResourceManager.GetObject("business_color_books_icon_icons_com_53474", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Byte[]. + /// + internal static byte[] IGE { + get { + object obj = ResourceManager.GetObject("IGE", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ShemaFound { + get { + object obj = ResourceManager.GetObject("ShemaFound", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ShemaLoads { + get { + object obj = ResourceManager.GetObject("ShemaLoads", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Ищет локализованную строку, похожую на 0;0;1;3.14 + ///1;0.01;1.06;3.23 + ///2;0.03;1.12;3.32 + ///3;0.04;1.18;3.41 + ///4;0.06;1.25;3.51 + ///5;0.08;1.32;3.61 + ///6;0.1;1.39;3.71 + ///7;0.12;1.47;3.82 + ///8;0.14;1.55;3.93 + ///9;0.16;1.64;4.05 + ///10;0.18;1.73;4.17 + ///11;0.21;1.83;4.29 + ///12;0.23;1.94;4.42 + ///13;0.26;2.05;4.55 + ///14;0.29;2.17;4.69 + ///15;0.32;2.3;4.84 + ///16;0.36;2.43;4.99 + ///17;0.39;2.57;5.15 + ///18;0.43;2.73;5.31 + ///19;0.47;2.89;5.48 + ///20;0.51;3.06;5.66 + ///21;0.56;3.24;5.84 + ///22;0.61;3.44;6.04 + ///23;0.66;3.65;6.24 + ///24;0.72;3.87;6.45 + ///25;0.78;4.11;6.67 + ///26;0.84;4.37;6.9 + ///27;0.91;4.64;7.14 + /// [остаток строки не уместился]";. + /// + internal static string tabl_5_5 { + get { + return ResourceManager.GetString("tabl_5_5", resourceCulture); + } + } + } +} diff --git a/Properties/Resources.resx b/Properties/Resources.resx new file mode 100644 index 0000000..9c1decf --- /dev/null +++ b/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\business-color_books_icon-icons.com_53474.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\tabl_5_5.csv;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + ..\Resources\ShemaFound.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ShemaLoads.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ИГЭ.xlsx;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs new file mode 100644 index 0000000..4f409d0 --- /dev/null +++ b/Properties/Settings.Designer.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// Этот код создан программой. +// Исполняемая версия:4.0.30319.42000 +// +// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае +// повторной генерации кода. +// +//------------------------------------------------------------------------------ + +namespace GroundOrganizer.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.1.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string BasePath { + get { + return ((string)(this["BasePath"])); + } + set { + this["BasePath"] = value; + } + } + } +} diff --git a/Properties/Settings.settings b/Properties/Settings.settings new file mode 100644 index 0000000..f81cf61 --- /dev/null +++ b/Properties/Settings.settings @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Resources/ShemaFound.png b/Resources/ShemaFound.png new file mode 100644 index 0000000000000000000000000000000000000000..89fa0953a4f755738458ca5b89c6be475f9b8ad2 GIT binary patch literal 90517 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 literal 0 HcmV?d00001 diff --git a/Resources/business-color_books_icon-icons.com_53474.ico b/Resources/business-color_books_icon-icons.com_53474.ico new file mode 100644 index 0000000000000000000000000000000000000000..152f80276d29af63ea58d34899088242b32dac92 GIT binary patch literal 67646 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 literal 0 HcmV?d00001 diff --git a/Resources/tabl_5_5.csv b/Resources/tabl_5_5.csv new file mode 100644 index 0000000..136a814 --- /dev/null +++ b/Resources/tabl_5_5.csv @@ -0,0 +1,46 @@ +0;0;1;3.14 +1;0.01;1.06;3.23 +2;0.03;1.12;3.32 +3;0.04;1.18;3.41 +4;0.06;1.25;3.51 +5;0.08;1.32;3.61 +6;0.1;1.39;3.71 +7;0.12;1.47;3.82 +8;0.14;1.55;3.93 +9;0.16;1.64;4.05 +10;0.18;1.73;4.17 +11;0.21;1.83;4.29 +12;0.23;1.94;4.42 +13;0.26;2.05;4.55 +14;0.29;2.17;4.69 +15;0.32;2.3;4.84 +16;0.36;2.43;4.99 +17;0.39;2.57;5.15 +18;0.43;2.73;5.31 +19;0.47;2.89;5.48 +20;0.51;3.06;5.66 +21;0.56;3.24;5.84 +22;0.61;3.44;6.04 +23;0.66;3.65;6.24 +24;0.72;3.87;6.45 +25;0.78;4.11;6.67 +26;0.84;4.37;6.9 +27;0.91;4.64;7.14 +28;0.98;4.93;7.4 +29;1.06;5.25;7.67 +30;1.15;5.59;7.95 +31;1.24;5.95;8.24 +32;1.34;6.34;8.55 +33;1.44;6.76;8.88 +34;1.55;7.22;9.22 +35;1.68;7.71;9.58 +36;1.81;8.24;9.97 +37;1.95;8.81;10.37 +38;2.11;9.44;10.8 +39;2.28;10.11;11.25 +40;2.46;10.85;11.73 +41;2.66;11.64;12.24 +42;2.88;12.51;12.79 +43;3.12;13.46;13.37 +44;3.38;14.5;13.98 +45;3.66;15.64;14.64 diff --git a/Resources/Аннотация 2019-06-14 145047.png b/Resources/Аннотация 2019-06-14 145047.png new file mode 100644 index 0000000000000000000000000000000000000000..c402ed745db5047a7637fd15b0600c9d8abf47dc GIT binary patch literal 14964 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 literal 0 HcmV?d00001 diff --git a/Settings.cs b/Settings.cs new file mode 100644 index 0000000..2b3a565 --- /dev/null +++ b/Settings.cs @@ -0,0 +1,28 @@ +namespace GroundOrganizer.Properties { + + + // Этот класс позволяет обрабатывать определенные события в классе параметров: + // Событие SettingChanging возникает перед изменением значения параметра. + // Событие PropertyChanged возникает после изменения значения параметра. + // Событие SettingsLoaded возникает после загрузки значений параметров. + // Событие SettingsSaving возникает перед сохранением значений параметров. + internal sealed partial class Settings { + + public Settings() { + // // Для добавления обработчиков событий для сохранения и изменения параметров раскомментируйте приведенные ниже строки: + // + // this.SettingChanging += this.SettingChangingEventHandler; + // + // this.SettingsSaving += this.SettingsSavingEventHandler; + // + } + + private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + // Добавьте здесь код для обработки события SettingChangingEvent. + } + + private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + // Добавьте здесь код для обработки события SettingsSaving. + } + } +} diff --git a/TestWindow.xaml b/TestWindow.xaml new file mode 100644 index 0000000..40aaa43 --- /dev/null +++ b/TestWindow.xaml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TestWindow.xaml.cs b/TestWindow.xaml.cs new file mode 100644 index 0000000..f8315b5 --- /dev/null +++ b/TestWindow.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Ribbon; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace GroundOrganizer +{ + /// + /// Логика взаимодействия для TestWindow.xaml + /// + public partial class TestWindow : RibbonWindow + { + public TestWindow() + { + InitializeComponent(); + } + } +} diff --git a/VM/BoresVM.cs b/VM/BoresVM.cs new file mode 100644 index 0000000..2061e52 --- /dev/null +++ b/VM/BoresVM.cs @@ -0,0 +1,208 @@ +using Microsoft.Win32; +using OfficeOpenXml; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TriangleNet.Geometry; +using TriangleNet.Meshing; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + private RelayCommand addBore; + private RelayCommand renumBore; + private RelayCommand updateBore; + private RelayCommand createBoresMesh; + private RelayCommand importBoresFromXLSX; + private RelayCommand exportBoresToXLSX; + + int numBore = 1; + string nameBore; + private string boresNote; + Bore selectedBore; + ObservableCollection listBore = new ObservableCollection(); + public string BoresNote { get => boresNote; set { boresNote = value; OnPropertyChanged(); } } + + public Bore SelectedBore { get => selectedBore; set { selectedBore = value; OnPropertyChanged(); ChangeSelectedBore(); } } + + public string NameBore { get => nameBore; set { nameBore = value; OnPropertyChanged(); } } + + public ObservableCollection ListBore { get => listBore; set { listBore = value; OnPropertyChanged(); } } + public TriangleNet.Mesh MeshBores { get; private set; } + + + public RelayCommand AddBore + { + get { return addBore ?? (addBore = new RelayCommand(obj => { AddBoreToList(); })); } + } + + public RelayCommand UpdateBores + { + get { return updateBore ?? (updateBore = new RelayCommand(obj => { UpdateBoreInList(); })); } + } + + public RelayCommand RenumBores + { + get { return renumBore ?? (renumBore = new RelayCommand(obj => { RenumberingBoreInList(); })); } + } + + public RelayCommand CreateBoresMesh + { + get { return createBoresMesh ?? (createBoresMesh = new RelayCommand(obj => { CreateMeshBores(); })); } + } + + public RelayCommand ExportBoresToXLSX + { + get { return exportBoresToXLSX ?? (exportBoresToXLSX = new RelayCommand(obj => { SaveBoresInXlsx(); })); } + } + + public RelayCommand ImportBoresFromXLSX + { + get { return importBoresFromXLSX ?? (importBoresFromXLSX = new RelayCommand(obj => { ReadBoresFromXlsx(); })); } + } + + //Чтение таблицы набора скважин из файла *.xlsx + internal void ReadBoresFromXlsx() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.xlsx"; + ofd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + ofd.Title = "Заполнение таблицы"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + + //ListIGE.Clear(); + + using (var p = new ExcelPackage(new FileInfo(ofd.FileName))) + { + //A workbook must have at least on cell, so lets add one... + var ws = p.Workbook.Worksheets["Скважины"]; + + object[,] content = ws.Cells.Value as object[,]; + List source; Bore item; + for (int i = 1; i < content.GetLength(0); i++) + { + source = new List(); + for (int j = 0; j < content.GetLength(1); j++) + { + source.Add(content[i, j]); + } + item = new Bore(); item.ListToProps(source); + ListBore.Add(item); + } + } + } + + //Сохранение таблицы набора ИГЭ в файл *.csv + internal void SaveBoresInXlsx() + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.DefaultExt = "*.xlsx"; + sfd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + sfd.Title = "Сохранение таблицы"; + //sfd.AddExtension = true; + sfd.OverwritePrompt = false; + sfd.ShowDialog(); + + if (sfd.FileName == null || sfd.FileName == "") return; + + string path = "ИГЭ.xlsx"; + FileInfo fileInf = new FileInfo(path); + if (fileInf.Exists != true) + { + using (FileStream fstream = new FileStream("ИГЭ.xlsx", FileMode.OpenOrCreate)) + { + byte[] array = Properties.Resources.IGE; + fstream.Write(array, 0, array.Length); + } + } + List content = new List(); + foreach (Bore item in listBore) + { + content.Add(item.PropsToList().ToArray()); + } + + using (var p = new ExcelPackage(new FileInfo(sfd.FileName))) + { + try + { + var ws = p.Workbook.Worksheets["Скважины"]; + + //To set values in the spreadsheet use the Cells indexer. + ws.Cells["A2"].LoadFromArrays(content); + + //Save the new workbook. We haven't specified the filename so use the Save as method. + p.SaveAs(new FileInfo(sfd.FileName)); + } + catch + { + ExcelPackage p1 = new ExcelPackage(new FileInfo("ИГЭ.xlsx")); + ExcelWorksheet ws1 = p1.Workbook.Worksheets["Скважины"]; + p.Workbook.Worksheets.Add("Скважины", ws1); + ExcelWorksheet ws = p.Workbook.Worksheets["Скважины"]; + + //Save the new workbook. We haven't specified the filename so use the Save as method. + ws.Cells["A2"].LoadFromArrays(content); + ws.Select(); + p.SaveAs(new FileInfo(sfd.FileName)); + } + } + } + + private void CreateMeshBores() + { + if (listBore == null || listBore.Count == 0) return; + + Polygon polygon = new Polygon(); + Vertex vrtx; + int i = 1; + foreach (Bore item in listBore) + { + vrtx = new Vertex(item.X, item.Y, item.Number, 2); + polygon.Add(vrtx); + i++; + } + + ConstraintOptions constraint = new ConstraintOptions() { Convex = true }; + MeshBores = (TriangleNet.Mesh)polygon.Triangulate(constraint); + Alert("Триангуляционная сеть скважин создана"); + } + + void AddBoreToList() + { + ListBore.Add(new Bore() { Number = numBore }); numBore++; + //CreateListNumberTypeBet(); + //NameBore = listBore[0].Name; + } + void RenumberingBoreInList() + { + int j = 1; + foreach (Bore item in ListBore) + { + item.Number = j; + j++; + } + numBore = j; + ListBore = new ObservableCollection(ListBore); + } + void UpdateBoreInList() + { + ListBore = new ObservableCollection(ListBore); + SaveDB(); + } + + void ChangeSelectedBore() + { + if (listBore.Count == 0 || selectedBore == null) return; + NameBore = selectedBore.Name; + ListLayer = selectedBore.Layers; + } + } +} diff --git a/VM/CalculationsVM.cs b/VM/CalculationsVM.cs new file mode 100644 index 0000000..ab8d11b --- /dev/null +++ b/VM/CalculationsVM.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Microsoft.Win32; +using netDxf; +using netDxf.Entities; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + private RelayCommand calcFoundsContours; + private RelayCommand calcRinBore; + private RelayCommand calcRinBores; + private RelayCommand calcRinCoords; + private RelayCommand calcSpInBore; + private RelayCommand calcSpInBores; + + private ObservableCollection resR; + private ObservableCollection resS; + private List resSdata; + private List resRdata; + private DataR resRselected; + private List listTypeFounds; + + public DataR ResRselected { get => resRselected; set { resRselected = value; OnPropertyChanged(); ChangeSelectedResults(); } } + public ObservableCollection ResR { get => resR; set { resR = value; OnPropertyChanged(); } } + public ObservableCollection ResS { get => resS; set { resS = value; OnPropertyChanged(); } } + public List ResRdata { get => resRdata; set { resRdata = value; OnPropertyChanged(); } } + public List ResSdata { get => resSdata; set { resSdata = value; OnPropertyChanged(); } } + + public RelayCommand CalcFoundsContours + { + get { return calcFoundsContours ?? (calcFoundsContours = new RelayCommand(obj => { CalculateContoursFounds(); })); } + } + + public RelayCommand CalcRinBore + { + get { return calcRinBore ?? (calcRinBore = new RelayCommand(obj => { CalculateRinBore(); })); } + } + + public RelayCommand CalcRinBores + { + get { return calcRinBores ?? (calcRinBores = new RelayCommand(obj => { CalculateRinBores(); })); } + } + + public RelayCommand CalcRinCoords + { + get { return calcRinCoords ?? (calcRinCoords = new RelayCommand(obj => { CalculateRinCoords(); })); } + } + + public RelayCommand CalcSpInBore + { + get { return calcSpInBore ?? (calcSpInBore = new RelayCommand(obj => { CalculateSpInBore(); })); } + } + + public RelayCommand CalcSpInBores + { + get { return calcSpInBores ?? (calcSpInBores = new RelayCommand(obj => { CalculateSpInBores(); })); } + } + + private void CalculateContoursFounds() + { + if (listFoundation == null || listFoundation.Count == 0) return; + + foreach (Foundation item in listFoundation) item.CalcContour(); + ListFoundation = new ObservableCollection(listFoundation); + } + + void ChangeSelectedResults() + { + if (resR == null || resR.Count == 0) return; + ResRdata = resRselected.SmallData; + } + + void CalculateSpInBore() + { + if (selectedBore == null) { Alert("Не выбрана расчетная скважина"); return; } + if (selectedFoundation == null) { Alert("Не выбран фундамент для расчета"); return; } + if (selectedFoundLoad == null) { Alert("Не выбрана расчетная нагрузка"); return; } + if (resS == null) ResS = new ObservableCollection(); + ResS.Clear(); + DataS s = selectedFoundation.Sp(selectedBore, selectedFoundLoad); + s.Bore = "Скв. " + nameBore; + s.Base = nameFoundation; + ResS.Add(s); + ResultsPage resPage = new ResultsPage(); + MW.ResulsFrame.Content = resPage; + resPage.ResultsDataGrid.ItemsSource = ResS; + MW.MainTabControl.SelectedIndex = 5; + //FoundationsPage foundPage = (FoundationsPage)MW.FoundationsFrame.Content; + //resPage.resultExpander.IsExpanded = true; + } + + void CalculateSpInBores() + { + if (listBore == null) { Alert("Площадка не содержит ни одной скважины"); return; } + if (selectedFoundation == null) { Alert("Не выбран фундамент для расчета"); return; } + if (selectedFoundLoad == null) { Alert("Не выбрана расчетная нагрузка"); return; } + if (resS == null) ResS = new ObservableCollection(); + ResS.Clear(); + foreach (Bore item in listBore) + { + DataS s = selectedFoundation.Sp(item, selectedFoundLoad); + s.Bore = "Скв. " + item.Name; + s.Base = nameFoundation; + ResS.Add(s); + } + ResultsPage resPage = new ResultsPage(); + MW.ResulsFrame.Content = resPage; + resPage.ResultsDataGrid.ItemsSource = ResS; + MW.MainTabControl.SelectedIndex = 5; + //FoundationsPage foundPage = (FoundationsPage)MW.FoundationsFrame.Content; + //foundPage.ResultsDataGrid.ItemsSource = ResS; + //foundPage.resultExpander.IsExpanded = true; + + } + + void CalculateRinBore() + { + if (selectedBore == null) { Alert("Не выбрана расчетная скважина"); return; } + if (selectedFoundation == null) { Alert("Не выбран фундамент для расчета"); return; } + if (resR == null) ResR = new ObservableCollection(); + ResR.Clear(); + DataR r = selectedFoundation.P(selectedBore, selectedStructure.flexStructure, selectedStructure.L, selectedStructure.H); + ResR.Add(r); + ResultsPage resPage = new ResultsPage(); + MW.ResulsFrame.Content = resPage; + //resPage.ResultsDataGrid.ItemsSource = ResR; + //resPage.DetailedResultsDataGrid.ItemsSource = ResRdata; + MW.MainTabControl.SelectedIndex = 5; + //FoundationsPage foundPage = (FoundationsPage)MW.FoundationsFrame.Content; + //foundPage.ResultsDataGrid.ItemsSource = ResR; + //foundPage.resultExpander.IsExpanded = true; + } + + private void CalculateRinBores() + { + if (listBore == null) { Alert("Площадка не содержит ни одной скважины"); return; } + if (selectedFoundation == null) { Alert("Не выбран фундамент для расчета"); return; } + ResR = selectedFoundation.P(ListBore, selectedStructure.flexStructure, selectedStructure.L, selectedStructure.H); + ResultsPage resPage = new ResultsPage(); + MW.ResulsFrame.Content = resPage; + //resPage.ResultsDataGrid.ItemsSource = ResR; + //resPage.DetailedResultsDataGrid.ItemsSource = ResRdata; + MW.MainTabControl.SelectedIndex = 5; + //FoundationsPage foundPage = (FoundationsPage)MW.FoundationsFrame.Content; + //foundPage.ResultsDataGrid.ItemsSource = ResR; + //foundPage.resultExpander.IsExpanded = true; + } + + private void CalculateRinCoords() + { + if (selectedBore == null) return; + if (resR == null) ResR = new ObservableCollection(); + ResR.Clear(); + DataR r = SelectedFoundation.P(selectedBore, selectedStructure.flexStructure, selectedStructure.L, selectedStructure.H); + r.Bore = "По координатам"; + r.Base = nameFoundation; + ResR.Add(r); + //FoundationsPage foundPage = (FoundationsPage)MW.FoundationsFrame.Content; + //foundPage.ResultsDataGrid.ItemsSource = ResR; + //foundPage.resultExpander.IsExpanded = true; + } + } +} diff --git a/VM/DrawingVM.cs b/VM/DrawingVM.cs new file mode 100644 index 0000000..d7d3aaf --- /dev/null +++ b/VM/DrawingVM.cs @@ -0,0 +1,81 @@ +using netDxf; +using netDxf.Entities; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Interop; +using System.Windows.Media.Imaging; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + + private RelayCommand drowFoundations; + private RelayCommand showFoundProps; + + CanwasWindow cw; + + public RelayCommand DrowFoundations + { + get { return drowFoundations ?? (drowFoundations = new RelayCommand(obj => { DrowFounds(); })); } + } + + public RelayCommand ShowFoundProps + { + get { return showFoundProps ?? (showFoundProps = new RelayCommand(obj => { ShowFoundPropsWindow(); })); } + } + + internal void ShowFoundPropsWindow() + { + if (listFoundation.Count == 0) return; + if (listFoundation == null) return; + + FoundPropWindow fpw = new FoundPropWindow(); + fpw.Owner = MW; + fpw.DataContext = MW.DataContext; + fpw.Top = 75; + fpw.Left = 75; + fpw.ShowDialog(); + } + + internal void DrowFounds() + { + if (listFoundation.Count == 0) return; + if (listFoundation == null) return; + + CalculateContoursFounds(); + CreateSmallPropsFounds(); + int t = 75; + int l = 75; + double ws = SystemParameters.PrimaryScreenWidth; + double hs = SystemParameters.PrimaryScreenHeight; + cw = new CanwasWindow(); + cw.Top = t; + cw.Left = l; + cw.MaxHeight= hs - t - 37; + cw.MaxWidth= ws - l - 5; + cw.CanvasScrollViewer.MaxWidth = cw.MaxWidth; + cw.CanvasScrollViewer.MaxHeight = cw.MaxHeight-60; + cw.Owner = MW; + CanvasDrafter.DrawFoundations(listFoundation, cw.drawArea, cw.MaxHeight - 120); + cw.drawArea.MinHeight = cw.drawArea.Height; + cw.drawArea.MinWidth = cw.drawArea.Width; + cw.EventMouseEnter(); + cw.Show(); + } + + internal void DrowFoundsNums() + { + if (cw == null || cw.IsActive == false) return; + CanvasDrafter.DrawFoundationsNumbers(listFoundation, cw.drawArea); + } + } +} diff --git a/VM/FoundLoadsVM.cs b/VM/FoundLoadsVM.cs new file mode 100644 index 0000000..02ca0da --- /dev/null +++ b/VM/FoundLoadsVM.cs @@ -0,0 +1,188 @@ +using Microsoft.Win32; +using OfficeOpenXml; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + private RelayCommand addFoundLoad; + private RelayCommand updateFoundLoad; + private RelayCommand renumFoundLoad; + private RelayCommand exportFoundLoadsToCSV; + private RelayCommand importFoundLoadsFromCSV; + + int numFoundLoad = 1; + string nameFoundLoad; + FoundLoad selectedFoundLoad; + ObservableCollection listFoundLoad = new ObservableCollection(); + + public ObservableCollection ListFoundLoad { get => listFoundLoad; set { listFoundLoad = value; OnPropertyChanged(); } } + + + public RelayCommand AddFoundLoad + { + get { return addFoundLoad ?? (addFoundLoad = new RelayCommand(obj => { AddFoundLoadToList(); })); } + } + + public RelayCommand UpdateFoundLoads + { + get { return updateFoundLoad ?? (updateFoundLoad = new RelayCommand(obj => { UpdateFoundLoadInList(); })); } + } + + public RelayCommand RenumFoundLoads + { + get { return renumFoundLoad ?? (renumFoundLoad = new RelayCommand(obj => { RenumberingFoundLoadInList(); })); } + } + + public RelayCommand ExportFoundLoadsToCSV + { + get { return exportFoundLoadsToCSV ?? (exportFoundLoadsToCSV = new RelayCommand(obj => { SaveLoadsInXlsx(); })); } + } + + public RelayCommand ImportFoundLoadsFromCSV + { + get { return importFoundLoadsFromCSV ?? (importFoundLoadsFromCSV = new RelayCommand(obj => { ReadLoadsFromXlsx(); })); } + } + public FoundLoad SelectedFoundLoad { get => selectedFoundLoad; set { selectedFoundLoad = value; OnPropertyChanged(); ChangeSelectedFoundLoad(); } } + + public string NameFoundLoad { get => nameFoundLoad; set { nameFoundLoad = value; OnPropertyChanged(); } } + + void AddFoundLoadToList() + { + ListFoundLoad.Add(new FoundLoad() { Number = numFoundLoad }); numFoundLoad++; + //CreateListNumberTypeBet(); + //NameFoundLoad = listFoundLoad[0].Name; + } + void RenumberingFoundLoadInList() + { + int j = 1; + foreach (FoundLoad item in ListFoundLoad) + { + item.Number = j; + j++; + } + numFoundLoad = j; + ListFoundLoad = new ObservableCollection(ListFoundLoad); + SaveDB(); + } + internal void UpdateFoundLoadInList() + { + ListFoundLoad = new ObservableCollection(ListFoundLoad); + SaveDB(); + } + + void ChangeSelectedFoundLoad() + { + if (listFoundLoad.Count == 0 || selectedFoundLoad == null) return; + NameFoundLoad = SelectedFoundLoad.Number.ToString(); + } + + //Сохранение таблицы нагрузок в файл *.xlsx + internal void SaveLoadsInXlsx() + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.DefaultExt = "*.xlsx"; + sfd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + sfd.Title = "Сохранение таблицы"; + //sfd.AddExtension = true; + sfd.OverwritePrompt = true; + sfd.ShowDialog(); + + if (sfd.FileName == null || sfd.FileName == "") return; + + try + { + string path = "ИГЭ.xlsx"; + FileInfo fileInf = new FileInfo(path); + if (fileInf.Exists != true) + { + using (FileStream fstream = new FileStream("ИГЭ.xlsx", FileMode.OpenOrCreate)) + { + byte[] array = Properties.Resources.IGE; + fstream.Write(array, 0, array.Length); + } + } + + + using (var p = new ExcelPackage(new FileInfo(sfd.FileName))) + { + for (int i = 0; i < listFoundation.Count; i++) + { + List content = new List(); + foreach (FoundLoad fli in listFoundation[i].Loads) + { + content.Add(fli.PropsToList().ToArray()); + } + ExcelPackage p1 = new ExcelPackage(new FileInfo("ИГЭ.xlsx")); + //A workbook must have at least on cell, so lets add one... + var ws = p1.Workbook.Worksheets["Нагрузки"]; + p.Workbook.Worksheets.Add((i + 1).ToString(), ws); + var wsi = p.Workbook.Worksheets[i + 1]; + //To set values in the spreadsheet use the Cells indexer. + wsi.Cells["D1"].Value = listFoundation[i].Number; + wsi.Cells["F1"].Value = listFoundation[i].Name; + wsi.Cells["A3"].LoadFromArrays(content); + } + + //Save the new workbook. We haven't specified the filename so use the Save as method. + p.SaveAs(new FileInfo(sfd.FileName)); + } + } + catch (Exception e) + { + Alert(e.Message); + } + } + + //Чтение нагрузок из файла *.xlsx + internal void ReadLoadsFromXlsx() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.xlsx"; + ofd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + ofd.Title = "Заполнение таблиц"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + + //ListFoundLoad.Clear(); + try + { + using (var p = new ExcelPackage(new FileInfo(ofd.FileName))) + { + int k = 0; + foreach (ExcelWorksheet wsi in p.Workbook.Worksheets) + { + listFoundation[k].Loads = new ObservableCollection(); + + object[,] content = wsi.Cells.Value as object[,]; + List source; FoundLoad item; + for (int i = 2; i < content.GetLength(0); i++) + { + source = new List(); + for (int j = 0; j < content.GetLength(1); j++) + { + source.Add(content[i, j]); + } + item = new FoundLoad(); item.ListToProps(source); + listFoundation[k].Loads.Add(item); + } + k++; + } + } + } + catch (Exception e) + { + Alert(e.Message); + } + } + } +} diff --git a/VM/FoundationsVM.cs b/VM/FoundationsVM.cs new file mode 100644 index 0000000..38e9a4c --- /dev/null +++ b/VM/FoundationsVM.cs @@ -0,0 +1,401 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Geo; +using Microsoft.Win32; +using netDxf; +using netDxf.Entities; +using OfficeOpenXml; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + private RelayCommand addFoundation; + private RelayCommand updateFoundation; + private RelayCommand renumFoundation; + private RelayCommand importFoundationsFromDXF; + private RelayCommand replaceD1Found; + private RelayCommand replaceDLFound; + private RelayCommand replaceFLFound; + private RelayCommand replaceDLFoundfromNULL; + private RelayCommand calculateDLFound; + private RelayCommand calculateLevelsFounds; + private RelayCommand exportFoundationsToCSV; + private RelayCommand importFoundationsFromCSV; + + private double d1; + private double dL; + private double fL; + + int numFoundation = 1; + string nameFoundation; + Foundation selectedFoundation; + ObservableCollection listFoundation = new ObservableCollection(); + List bufferFoundations = new List(); + + public double D1 { get => d1; set { d1 = value; OnPropertyChanged(); /*ChangeD1();*/ } } + public double DL { get => dL; set { dL = value; OnPropertyChanged(); /*ChangeDL();*/ } } + public double FL { get => fL; set { fL = value; OnPropertyChanged(); /*ChangeFL();*/ } } + + + public ObservableCollection ListFoundation { get => listFoundation; set { listFoundation = value; OnPropertyChanged(); } } + public Foundation SelectedFoundation { get => selectedFoundation; set { selectedFoundation = value; OnPropertyChanged(); ChangeSelectedFoundation(); } } + public string NameFoundation { get => nameFoundation; set { nameFoundation = value; OnPropertyChanged(); ChangeMark(); } } + public List ListTypeFounds { get => listTypeFounds; set { listTypeFounds = value; OnPropertyChanged(); } } + public List BufferFoundations { get => bufferFoundations; set => bufferFoundations = value; } + + #region Команды + + public RelayCommand AddFoundation + { + get { return addFoundation ?? (addFoundation = new RelayCommand(obj => { AddFoundationToList(); })); } + } + + public RelayCommand UpdateFoundations + { + get { return updateFoundation ?? (updateFoundation = new RelayCommand(obj => { UpdateFoundationInList(); })); } + } + + public RelayCommand RenumFoundations + { + get { return renumFoundation ?? (renumFoundation = new RelayCommand(obj => { RenumberingFoundationInList(); })); } + } + + public RelayCommand ImportFoundationsFromDXF + { + get { return importFoundationsFromDXF ?? (importFoundationsFromDXF = new RelayCommand(obj => { ReadFondationsFromDXF(); })); } + } + + public RelayCommand ReplaceD1Found + { + get { return replaceD1Found ?? (replaceD1Found = new RelayCommand(obj => { ChangeD1(); })); } + } + + public RelayCommand ReplaceDLFound + { + get { return replaceDLFound ?? (replaceDLFound = new RelayCommand(obj => { ChangeDL(); })); } + } + + public RelayCommand ReplaceFLFound + { + get { return replaceFLFound ?? (replaceFLFound = new RelayCommand(obj => { ChangeFL(); })); } + } + + + public RelayCommand ReplaceDLFoundfromNULL + { + get { return replaceDLFoundfromNULL ?? (replaceDLFoundfromNULL = new RelayCommand(obj => { ChangeDLfromNULL(); })); } + } + + public RelayCommand CalculateDLFound + { + get { return calculateDLFound ?? (calculateDLFound = new RelayCommand(obj => { CalcDLFound(); })); } + } + + public RelayCommand CalculateLevelsFounds + { + get { return calculateLevelsFounds ?? (calculateLevelsFounds = new RelayCommand(obj => { CalcDLFoundsAll(); CalcNLFoundsAll(); })); } + } + + public RelayCommand ExportFoundationsToCSV + { + get { return exportFoundationsToCSV ?? (exportFoundationsToCSV = new RelayCommand(obj => { SaveFoundationsInCsv(); })); } + } + + public RelayCommand ImportFoundationsFromCSV + { + get { return importFoundationsFromCSV ?? (importFoundationsFromCSV = new RelayCommand(obj => { ReadFoundationsFromCsv(); })); } + } + + #endregion + + void AddFoundationToList() + { + ListFoundation.Add(new Foundation() { Number = numFoundation }); numFoundation++; + //CreateListNumberTypeBet(); + //NameFoundation = listFoundation[0].Name; + } + void RenumberingFoundationInList() + { + int j = 1; + foreach (Foundation item in ListFoundation) + { + item.Number = j; + j++; + } + numFoundation = j; + ListFoundation = new ObservableCollection(ListFoundation); + } + internal void UpdateFoundationInList() + { + ListFoundation = new ObservableCollection(ListFoundation); + SaveDB(); + } + + void ChangeSelectedFoundation() + { + if (listFoundation.Count == 0 || selectedFoundation == null) return; + NameFoundation = selectedFoundation.Name; + ListFoundLoad = selectedFoundation.Loads; + D1 = selectedFoundation.D1; + FL = selectedFoundation.FL; + DL = selectedFoundation.DL; + } + + void CreateListTypeFoundations() + { + if (listFoundation == null || listPlayGround == null) return; + ListTypeFounds = new List { TypeFound.Прямоугольный, TypeFound.Круглый, TypeFound.Ленточный }; + try + { + FoundationsPage foundationsPage = (FoundationsPage)MW.FoundationsFrame.Content; + foundationsPage.typeFondsListCbxCol.ItemsSource = ListTypeFounds; + } + catch (Exception) + { + return; + } + } + private void ReadFondationsFromDXF() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.dxf"; + ofd.Filter = "Чертеж (*.dxf)|*.dxf"; + ofd.Title = "Импорт чертежа"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + + DxfDocument dxfDocument = DxfDocument.Load(ofd.FileName); + IEnumerable dxfLwPolylines = dxfDocument.LwPolylines; + IEnumerable dxfLwPolylinesVertexes = null; + Foundation fnd; + Quadrangle countFound; int i = 0; + Point2d[] ptColl = new Point2d[4]; + foreach (LwPolyline item in dxfLwPolylines) + { + if (item.Layer.Name == "Foundations") + { + dxfLwPolylinesVertexes = item.Vertexes; + int j = 0; + foreach (LwPolylineVertex itemVrtx in dxfLwPolylinesVertexes) + { + ptColl[j] = new Point2d(itemVrtx.Position.X * 0.001, itemVrtx.Position.Y * 0.001); + j++; if (j == 4) break; + } + countFound = new Quadrangle(ptColl[0], ptColl[1], ptColl[2], ptColl[3]); + countFound.Units = UnitsLin.м; + fnd = new Foundation(countFound) { Number = i + 1 }; + ListFoundation.Add(fnd); + i++; + } + } + + if (dxfLwPolylinesVertexes == null) return; + } + + //Сохранение таблицы фундаментов в файл *.csv + internal void SaveFoundationsInCsv() + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.DefaultExt = "*.xlsx"; + sfd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + sfd.Title = "Сохранение таблицы"; + //sfd.AddExtension = true; + sfd.OverwritePrompt = false; + sfd.ShowDialog(); + + if (sfd.FileName == null || sfd.FileName == "") return; + + string path = "ИГЭ.xlsx"; + FileInfo fileInf = new FileInfo(path); + if (fileInf.Exists != true) + { + using (FileStream fstream = new FileStream("ИГЭ.xlsx", FileMode.OpenOrCreate)) + { + byte[] array = Properties.Resources.IGE; + fstream.Write(array, 0, array.Length); + } + } + List content = new List(); + foreach (Foundation item in listFoundation) + { + content.Add(item.PropsToList().ToArray()); + } + + using (var p = new ExcelPackage(new FileInfo(sfd.FileName))) + { + try + { + //A workbook must have at least on cell, so lets add one... + var ws = p.Workbook.Worksheets["Фундаменты"]; + + //To set values in the spreadsheet use the Cells indexer. + ws.Cells["A2"].LoadFromArrays(content); + + //Save the new workbook. We haven't specified the filename so use the Save as method. + p.SaveAs(new FileInfo(sfd.FileName)); + } + catch + { + ExcelPackage p1 = new ExcelPackage(new FileInfo("ИГЭ.xlsx")); + ExcelWorksheet ws1 = p1.Workbook.Worksheets["Фундаменты"]; + p.Workbook.Worksheets.Add("Фундаменты", ws1); + + //A workbook must have at least on cell, so lets add one... + var ws = p.Workbook.Worksheets["Фундаменты"]; + + //To set values in the spreadsheet use the Cells indexer. + ws.Cells["A2"].LoadFromArrays(content); + ws.Select(); + //Save the new workbook. We haven't specified the filename so use the Save as method. + p.SaveAs(new FileInfo(sfd.FileName)); + } + } + } + + //Чтение таблицы фундаментов из файла *.xlsx + internal void ReadFoundationsFromCsv() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.xlsx"; + ofd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + ofd.Title = "Заполнение таблицы"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + + //ListIGE.Clear(); + + try + { + using (var p = new ExcelPackage(new FileInfo(ofd.FileName))) + { + //A workbook must have at least on cell, so lets add one... + var ws = p.Workbook.Worksheets["Фундаменты"]; + + object[,] content = ws.Cells.Value as object[,]; + List source; Foundation item; + for (int i = 1; i < content.GetLength(0); i++) + { + source = new List(); + for (int j = 0; j < content.GetLength(1); j++) + { + source.Add(content[i, j]); + } + item = new Foundation(); item.ListToProps(source); + ListFoundation.Add(item); + } + } + } + catch (Exception e) + { + Alert(e.Message); + } + } + + private void ChangeMark() + { + if (selectedFoundation == null) return; + SelectedFoundation.Name = nameFoundation; + } + + void ChangeD1() + { + if (selectedFoundation == null || selectedStructure == null) return; + SelectedFoundation.D1 = d1; + SelectedFoundation.D1toFL(selectedStructure.Null); + DL = selectedFoundation.DL; + //FL = selectedFoundation.FL; + } + + void ChangeDL() + { + if (selectedFoundation == null || selectedStructure == null) return; + SelectedFoundation.DL = dL; + SelectedFoundation.DLtoD1(selectedStructure.Null); + D1 = selectedFoundation.D1; + //FL = selectedFoundation.FL; + } + + void ChangeFL() + { + if (selectedFoundation == null || selectedStructure == null) return; + SelectedFoundation.FL = fL; + SelectedFoundation.FLtoD1(selectedStructure.Null); + D1 = selectedFoundation.D1; + //DL = selectedFoundation.DL; + } + + private void ChangeDLfromNULL() + { + if (selectedFoundation == null || selectedStructure == null) return; + SelectedFoundation.DL = selectedStructure.Null; + DL = SelectedFoundation.DL; + SelectedFoundation.DLtoD1(selectedStructure.Null); + D1 = selectedFoundation.D1; + } + + private void CalcDLFound() + { + if (selectedFoundation == null || selectedStructure == null) return; + if (MeshRedPlanning == null) CreateRedMesh(); + selectedFoundation.CalcDL(MeshRedPlanning); + DL = SelectedFoundation.DL; + SelectedFoundation.DLtoD1(selectedStructure.Null); + D1 = selectedFoundation.D1; + } + + internal void CalcDLFoundsAll() + { + if (listFoundation == null || listFoundation.Count == 0) return; + if (MeshRedPlanning == null) CreateRedMesh(); + if (MeshRedPlanning == null) + { + Alert("Сооружение не содержит планировочных отметок"); + return; + } + + foreach (Foundation item in ListFoundation) + { + item.CalcDL(MeshRedPlanning); + item.DLtoD1(selectedStructure.Null); + } + + Alert("Уровни планировки для всех фундаментов \nвычислены по триангуляционной сети"); + } + + internal void CalcNLFoundsAll() + { + if (listFoundation == null || listFoundation.Count == 0) return; + if (MeshBlackPlanning == null) CreateBlackMesh(); + if (MeshBlackPlanning == null) + { + Alert("Сооружение не содержит планировочных отметок"); + return; + } + foreach (Foundation item in ListFoundation) + { + item.CalcNL(MeshBlackPlanning); + } + + Alert("Отметки естественного рельефа для всех фундаментов \nвычислены по триангуляционной сети"); + } + + internal void CreateSmallPropsFounds() + { + foreach (Foundation item in ListFoundation) item.CreateSmallPropsList(); + } + } +} diff --git a/VM/HelpsVM.cs b/VM/HelpsVM.cs new file mode 100644 index 0000000..84c944f --- /dev/null +++ b/VM/HelpsVM.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media.Imaging; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + + private RelayCommand helpFoundation; + private RelayCommand helpLoads; + public RelayCommand HelpFoundation + { + get { return helpFoundation ?? (helpFoundation = new RelayCommand(obj => { HelpFoundAlert(); })); } + } + public RelayCommand HelpLoads + { + get { return helpLoads ?? (helpLoads = new RelayCommand(obj => { HelpLoadsAlert(); })); } + } + + void HelpFoundAlert() + { + Alert(Properties.Resources.ShemaFound, 500); + if (MW.OwnedWindows.Count > 0) + { + foreach (Window item in MW.OwnedWindows) item.Close(); + Alert(Properties.Resources.ShemaFound, 500); + } + } + + void HelpLoadsAlert() + { + Alert(@"\Images\ShemaLoads.png", 200); + if (MW.OwnedWindows.Count > 0) + { + foreach (Window item in MW.OwnedWindows) item.Close(); + Alert(@"\Images\ShemaLoads.png", 200); + } + } + + void Alert(string alert) + { + AlertWindow aw = new AlertWindow(); + aw.Owner = MW; + aw.alertLabel.Content = alert; + //aw.WindowStyle = WindowStyle.None; + aw.ShowDialog(); + } + void Alert(string alert, string title) + { + AlertWindow aw = new AlertWindow(); + aw.Owner = MW; + aw.alertLabel.Content = alert; + aw.Title = title; + aw.ShowDialog(); + } + void Alert(Bitmap resource, int h = 250) + { + ImageWindow aw = new ImageWindow(); + //BitmapImage b =new BitmapImage(new Uri("pack://application:,,,/Resources/ShemaFound.png")); + Bitmap br = resource; + BitmapSource b = Imaging.CreateBitmapSourceFromHBitmap(br.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); + aw.alertImage.Source = b; + aw.alertImage.Height = h; + aw.Owner = MW; + aw.WindowStartupLocation = WindowStartupLocation.Manual; + aw.Top = MW.Top; + aw.Left = MW.Left + MW.Width; + aw.Show(); + } + + void Alert(string filepath, int h = 250) + { + Uri uri = new Uri(filepath, UriKind.RelativeOrAbsolute); + BitmapImage b = new BitmapImage(uri); + ImageWindow aw = new ImageWindow(); + aw.alertImage.Source = b; + aw.alertImage.Height = h; + aw.Owner = MW; + aw.WindowStartupLocation = WindowStartupLocation.Manual; + aw.Top = MW.Top; + aw.Left = MW.Left + MW.Width; + aw.Show(); + } + } +} diff --git a/VM/IGEsVM.cs b/VM/IGEsVM.cs new file mode 100644 index 0000000..50dcbac --- /dev/null +++ b/VM/IGEsVM.cs @@ -0,0 +1,278 @@ +using Microsoft.Win32; +using OfficeOpenXml; +using OfficeOpenXml.Style; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + int numIGE = 1; + ObservableCollection listIGE = new ObservableCollection(); + + public ObservableCollection ListIGE { get => listIGE; set { listIGE = value; OnPropertyChanged(); } } + + private RelayCommand addIGE; + public RelayCommand AddIGE + { + get { return addIGE ?? (addIGE = new RelayCommand(obj => { AddIGEToList(); })); } + } + + private RelayCommand updateIGE; + public RelayCommand UpdateIGEs + { + get { return updateIGE ?? (updateIGE = new RelayCommand(obj => { UpdateIGEInList(); })); } + } + + private RelayCommand renumIGE; + public RelayCommand RenumIGEs + { + get { return renumIGE ?? (renumIGE = new RelayCommand(obj => { RenumberingIGEInList(); })); } + } + + private RelayCommand exportIGEtoCSV; + public RelayCommand ExportIGEtoCSV + { + get { return exportIGEtoCSV ?? (exportIGEtoCSV = new RelayCommand(obj => { SaveIGEsInCsv(); })); } + } + + private RelayCommand importIGEfromCSV; + public RelayCommand ImportIGEfromCSV + { + get { return importIGEfromCSV ?? (importIGEfromCSV = new RelayCommand(obj => { ReadIGEsFromCsv(); })); } + } + + private RelayCommand saveIGEsTable; + public RelayCommand SaveIGEsTable + { + get { return saveIGEsTable ?? (saveIGEsTable = new RelayCommand(obj => { SaveIGEs(); })); } + } + + private IEnumerable listNumIGEs; + public IEnumerable ListNumIGEs { get => listNumIGEs; set { listNumIGEs = value; OnPropertyChanged(); } } + + void AddIGEToList() + { + ListIGE.Add(new IGE() { Number = numIGE }); numIGE++; + CreateListNumIGEs(); + //CreateListNumberTypeBet(); + //NameIGE = listIGE[0].Name; + } + void RenumberingIGEInList() + { + int j = 1; + foreach (IGE item in ListIGE) + { + item.Number = j; + j++; + } + numIGE = j; + ListIGE = new ObservableCollection(ListIGE); + CreateListNumIGEs(); + } + void UpdateIGEInList() + { + ListIGE = new ObservableCollection(ListIGE); + SaveDB(); + } + + void CreateListNumIGEs() + { + if (listIGE == null || listPlayGround == null) return; + ListNumIGEs = from bet in listIGE select bet.NumIGE; + try + { + BoresPage boresPage = (BoresPage)MW.BoresFrame.Content; + boresPage.IGEsListCbxCol.ItemsSource = listNumIGEs; + } + catch { return; } + } + + //Сохранение таблицы набора ИГЭ в файл *.csv + internal void SaveIGEsInCsv() + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.DefaultExt = "*.xlsx"; + sfd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + sfd.Title = "Сохранение таблицы"; + //sfd.AddExtension = true; + sfd.OverwritePrompt = false; + sfd.ShowDialog(); + + if (sfd.FileName == null || sfd.FileName == "") return; + + string path = "ИГЭ.xlsx"; + FileInfo fileInf = new FileInfo(path); + if (fileInf.Exists != true) + { + using (FileStream fstream = new FileStream("ИГЭ.xlsx", FileMode.OpenOrCreate)) + { + byte[] array = Properties.Resources.IGE; + fstream.Write(array, 0, array.Length); + } + } + List content = new List(); + foreach (IGE item in listIGE) + { + content.Add(item.PropsToList().ToArray()); + } + + using (var p = new ExcelPackage(new FileInfo(sfd.FileName))) + { + try + { + var ws = p.Workbook.Worksheets["ИГЭ"]; + + //To set values in the spreadsheet use the Cells indexer. + ws.Cells["A2"].LoadFromArrays(content); + + //Save the new workbook. We haven't specified the filename so use the Save as method. + p.SaveAs(new FileInfo(sfd.FileName)); + } + catch + { + ExcelPackage p1 = new ExcelPackage(new FileInfo("ИГЭ.xlsx")); + ExcelWorksheet ws1 = p1.Workbook.Worksheets["ИГЭ"]; + p.Workbook.Worksheets.Add("ИГЭ", ws1); + ExcelWorksheet ws = p.Workbook.Worksheets["ИГЭ"]; + + //Save the new workbook. We haven't specified the filename so use the Save as method. + ws.Cells["A2"].LoadFromArrays(content); + ws.Select(); + p.SaveAs(new FileInfo(sfd.FileName)); + } + } + + //try + //{ + // using (StreamWriter sw = new StreamWriter(sfd.FileName, false, System.Text.Encoding.Default)) + // { + // foreach (IGE item in listIGE) + // { + // sw.WriteLine(item.PropsToString()); + // } + // } + //} + //catch (Exception e) + //{ + // Alert(e.Message); + //} + } + + //Чтение таблицы набора ИГЭ из файла *.csv + internal void ReadIGEsFromCsv() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.xlsx"; + ofd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + ofd.Title = "Заполнение таблицы"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + + //ListIGE.Clear(); + + using (var p = new ExcelPackage(new FileInfo(ofd.FileName))) + { + //A workbook must have at least on cell, so lets add one... + var ws = p.Workbook.Worksheets["ИГЭ"]; + + object[,] content = ws.Cells.Value as object[,]; + List source; IGE item; + for (int i = 1; i < content.GetLength(0); i++) + { + source = new List(); + for (int j = 0; j < content.GetLength(1); j++) + { + source.Add(content[i, j]); + } + item = new IGE(); item.ListToProps(source); + ListIGE.Add(item); + } + } + + //OpenFileDialog ofd = new OpenFileDialog(); + //ofd.DefaultExt = "*.*"; + //ofd.Filter = "Текстовый файл (*.csv)|*.csv|Все файлы (*.*)|*.*"; + //ofd.Title = "Заполнение таблицы"; + //ofd.ShowDialog(); + + //if (ofd.FileName == null || ofd.FileName == "") return; + + //ListIGE.Clear(); + //try + //{ + // using (StreamReader sr = new StreamReader(ofd.FileName, System.Text.Encoding.Default)) + // { + // string line; + // IGE ige; + // while ((line = sr.ReadLine()) != null) + // { + // ige = new IGE(); + // ige.StringToProps(line); + // ListIGE.Add(ige); + // } + // } + //} + //catch (Exception e) + //{ + // Alert(e.Message); + //} + } + + internal void SaveIGEs() + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.DefaultExt = "*.igedb"; + sfd.Filter = "Таблица ИГЭ (*.igedb)|*.igedb"; + sfd.Title = "Сохранение таблицы"; + //sfd.AddExtension = true; + sfd.OverwritePrompt = true; + sfd.ShowDialog(); + + if (sfd.FileName == null || sfd.FileName == "") return; + + BinaryFormatter formatter = new BinaryFormatter(); + // получаем поток, куда будем записывать сериализованный объект + using (FileStream fs = new FileStream(sfd.FileName, FileMode.OpenOrCreate)) + { + formatter.Serialize(fs, ListIGE); + } + //Alert("Введенные данные успешно сохранены"); + } + + internal void ReadIGEs() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.igedb"; + ofd.Filter = "Таблица ИГЭ (*.igedb)|*.igedb"; + ofd.Title = "Открытие таблицы"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + + if (File.Exists(ofd.FileName) == true) + { + // создаем объект BinaryFormatter + BinaryFormatter formatter = new BinaryFormatter(); + + using (FileStream fs = new FileStream(ofd.FileName, FileMode.OpenOrCreate)) + { + List tmp = new List(ListIGE); + tmp.AddRange(formatter.Deserialize(fs) as ObservableCollection); + ListIGE = new ObservableCollection(tmp); + } + } + } + } +} diff --git a/VM/LayersVM.cs b/VM/LayersVM.cs new file mode 100644 index 0000000..6b73cca --- /dev/null +++ b/VM/LayersVM.cs @@ -0,0 +1,244 @@ +using Microsoft.Win32; +using OfficeOpenXml; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + private RelayCommand addLayer; + private RelayCommand updateLayer; + private RelayCommand renumLayer; + private RelayCommand recalcLayerH; + private RelayCommand recalcLayerDown; + private RelayCommand exportLayersToXLSX; + private RelayCommand importLayersFromXLSX; + + int numLayer = 1; + ObservableCollection listLayer = new ObservableCollection(); + + public ObservableCollection ListLayer { get => listLayer; set { listLayer = value; OnPropertyChanged(); } } + + public RelayCommand AddLayer + { + get { return addLayer ?? (addLayer = new RelayCommand(obj => { AddLayerToList(); })); } + } + + public RelayCommand UpdateLayers + { + get { return updateLayer ?? (updateLayer = new RelayCommand(obj => { UpdateLayerInList(); })); } + } + + public RelayCommand RenumLayers + { + get { return renumLayer ?? (renumLayer = new RelayCommand(obj => { RenumberingLayerInList(); })); } + } + + public RelayCommand RecalcLayerH + { + get { return recalcLayerH ?? (recalcLayerH = new RelayCommand(obj => { RecalcInLayersH(); })); } + } + + public RelayCommand RecalcLayerDown + { + get { return recalcLayerDown ?? (recalcLayerDown = new RelayCommand(obj => { RecalcInLayersDown(); })); } + } + + public RelayCommand ExportLayersToXLSX + { + get { return exportLayersToXLSX ?? (exportLayersToXLSX = new RelayCommand(obj => { SaveLayersInXlsx(); })); } + } + + public RelayCommand ImportLayersFromXLSX + { + get { return importLayersFromXLSX ?? (importLayersFromXLSX = new RelayCommand(obj => { ReadLayersFromXlsx(); })); } + } + + void AddLayerToList() + { + ListLayer.Add(new Layer() { Number = numLayer }); numLayer++; + //CreateListNumberTypeBet(); + //NameLayer = listLayer[0].Name; + } + void RenumberingLayerInList() + { + int j = 1; + foreach (Layer item in listLayer) + { + item.Number = j; + j++; + } + numLayer = j; + ListLayer = new ObservableCollection(listLayer); + } + void UpdateLayerInList() + { + foreach (Layer lay in listLayer) + { + foreach (IGE ige in listIGE) + { + if (lay.NumIGE==ige.NumIGE) + { + lay.IGE = ige.Clone(); + lay.Description = ige.Description; + break; + } + } + } + ListLayer = new ObservableCollection(listLayer); + selectedBore.Layers = listLayer; + SaveDB(); + } + + void RecalcInLayersH() + { + if (listLayer == null) return; + if (listLayer.Count == 0) return; + if (selectedBore == null) return; + + UpdateLayerInList(); + + double down = 0; + double up = 0; + double z = selectedBore.Z; + foreach (Layer item in listLayer) + { + z -= item.H; + down += item.H; + item.Down = down; + item.Z = z; + item.Up = up; + up += item.H; + } + ListLayer = new ObservableCollection(listLayer); + } + + void RecalcInLayersDown() + { + if (listLayer == null) return; + if (listLayer.Count == 0) return; + if (selectedBore == null) return; + + UpdateLayerInList(); + + double up = 0; + double z = selectedBore.Z; + foreach (Layer item in listLayer) + { + item.Up = up; + item.H = item.Down - item.Up; + z -= item.H; + item.Z = z; + up += item.H; + } + ListLayer = new ObservableCollection(listLayer); + } + + //Сохранение таблиц наборов слоев в файл *.xlsx + internal void SaveLayersInXlsx() + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.DefaultExt = "*.xlsx"; + sfd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + sfd.Title = "Сохранение таблицы"; + //sfd.AddExtension = true; + sfd.OverwritePrompt = true; + sfd.ShowDialog(); + + if (sfd.FileName == null || sfd.FileName == "") return; + + try + { + string path = "ИГЭ.xlsx"; + FileInfo fileInf = new FileInfo(path); + if (fileInf.Exists != true) + { + using (FileStream fstream = new FileStream("ИГЭ.xlsx", FileMode.OpenOrCreate)) + { + byte[] array = Properties.Resources.IGE; + fstream.Write(array, 0, array.Length); + } + } + + using (var p = new ExcelPackage(new FileInfo(sfd.FileName))) + { + for (int i = 0; i < listBore.Count; i++) + { + List content = new List(); + foreach (Layer fli in listBore[i].Layers) + { + content.Add(fli.PropsToList().ToArray()); + } + ExcelPackage p1 = new ExcelPackage(new FileInfo("ИГЭ.xlsx")); + //A workbook must have at least on cell, so lets add one... + var ws = p1.Workbook.Worksheets["Слои"]; + p.Workbook.Worksheets.Add((i + 1).ToString(), ws); + var wsi = p.Workbook.Worksheets[i + 1]; + //To set values in the spreadsheet use the Cells indexer. + wsi.Cells["D1"].Value = listBore[i].Name; + wsi.Cells["A3"].LoadFromArrays(content); + } + + //Save the new workbook. We haven't specified the filename so use the Save as method. + p.SaveAs(new FileInfo(sfd.FileName)); + } + } + catch (Exception e) + { + Alert(e.Message); + } + } + + //Чтение наборов слоев из файла *.xlsx + internal void ReadLayersFromXlsx() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.xlsx"; + ofd.Filter = "Файл Excel (*.xlsx)|*.xlsx"; + ofd.Title = "Заполнение таблиц"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + + //ListFoundLoad.Clear(); + try + { + using (var p = new ExcelPackage(new FileInfo(ofd.FileName))) + { + int k = 0; + foreach (ExcelWorksheet wsi in p.Workbook.Worksheets) + { + listBore[k].Layers = new ObservableCollection(); + + object[,] content = wsi.Cells.Value as object[,]; + List source; Layer item; + for (int i = 2; i < content.GetLength(0); i++) + { + source = new List(); + for (int j = 0; j < content.GetLength(1); j++) + { + source.Add(content[i, j]); + } + item = new Layer(); item.ListToProps(source); + listBore[k].Layers.Add(item); + SelectedBore = listBore[k]; + UpdateLayerInList(); + } + k++; + } + } + } + catch (Exception e) + { + Alert(e.Message); + } + } + } +} diff --git a/VM/PlanningVM.cs b/VM/PlanningVM.cs new file mode 100644 index 0000000..d5db65b --- /dev/null +++ b/VM/PlanningVM.cs @@ -0,0 +1,363 @@ +using Microsoft.Win32; +using netDxf; +using netDxf.Entities; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading.Tasks; +using TriangleNet; +using TriangleNet.Geometry; +using TriangleNet.Meshing; +using TriangleNet.Tools; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + private RelayCommand addRedVertex; + private RelayCommand addBlackVertex; + private RelayCommand updateRedPlanning; + private RelayCommand updateBlackPlanning; + private RelayCommand renumRedVertexes; + private RelayCommand renumBlackVertexes; + private RelayCommand importPlanningsFromDXF; + private RelayCommand importRedPlanningFromCSV; + private RelayCommand importBlackPlanningFromCSV; + private RelayCommand exportRedPlanningToCSV; + private RelayCommand exportBlackPlanningToCSV; + private RelayCommand createRedPlanningMesh; + private RelayCommand createBlackPlanningMesh; + + int numVertex = 1; + PlanningVertex selectedRedVertex; + PlanningVertex selectedBlackVertex; + ObservableCollection redPlanning = new ObservableCollection(); + ObservableCollection blackPlanning = new ObservableCollection(); + + public ObservableCollection RedPlanning { get => redPlanning; set { redPlanning = value; OnPropertyChanged(); } } + public ObservableCollection BlackPlanning { get => blackPlanning; set { blackPlanning = value; OnPropertyChanged(); } } + public PlanningVertex SelectedRedVertex { get => selectedRedVertex; set { selectedRedVertex = value; OnPropertyChanged(); } } + public PlanningVertex SelectedBlackVertex { get => selectedBlackVertex; set { selectedBlackVertex = value; OnPropertyChanged(); } } + public TriangleNet.Mesh MeshRedPlanning { get; private set; } + public TriangleNet.Mesh MeshBlackPlanning { get; private set; } + + + public RelayCommand AddRedVertex + { + get { return addRedVertex ?? (addRedVertex = new RelayCommand(obj => { AddRedVertexToList(); })); } + } + + public RelayCommand UpdateRedPlanning + { + get { return updateRedPlanning ?? (updateRedPlanning = new RelayCommand(obj => { UpdateRedVertexesInList(); })); } + } + + public RelayCommand RenumRedVertexes + { + get { return renumRedVertexes ?? (renumRedVertexes = new RelayCommand(obj => { RenumberingRedVertexesInList(); })); } + } + + public RelayCommand AddBlackVertex + { + get { return addBlackVertex ?? (addBlackVertex = new RelayCommand(obj => { AddBlackVertexToList(); })); } + } + + public RelayCommand UpdateBlackPlanning + { + get { return updateBlackPlanning ?? (updateBlackPlanning = new RelayCommand(obj => { UpdateBlackVertexesInList(); })); } + } + + public RelayCommand RenumBlackVertexes + { + get { return renumBlackVertexes ?? (renumBlackVertexes = new RelayCommand(obj => { RenumberingBlackVertexesInList(); })); } + } + + public RelayCommand ImportPlanningsFromDXF + { + get { return importPlanningsFromDXF ?? (importPlanningsFromDXF = new RelayCommand(obj => { ReadPlanningsDXF(); })); } + } + + public RelayCommand ImportRedPlanningFromCSV + { + get { return importRedPlanningFromCSV ?? (importRedPlanningFromCSV = new RelayCommand(obj => { ReadRedPlanningCSV(); })); } + } + + public RelayCommand ExportRedPlanningToCSV + { + get { return exportRedPlanningToCSV ?? (exportRedPlanningToCSV = new RelayCommand(obj => { SaveRedPlanningInCsv(); })); } + } + + + public RelayCommand ImportBlackPlanningFromCSV + { + get { return importBlackPlanningFromCSV ?? (importBlackPlanningFromCSV = new RelayCommand(obj => { ReadBlackPlanningCSV(); })); } + } + + public RelayCommand ExportBlackPlanningToCSV + { + get { return exportBlackPlanningToCSV ?? (exportBlackPlanningToCSV = new RelayCommand(obj => { SaveBlackPlanningInCsv(); })); } + } + + public RelayCommand CreateRedPlanningMesh + { + get { return createRedPlanningMesh ?? (createRedPlanningMesh = new RelayCommand(obj => { CreateRedMesh(); })); } + } + + public RelayCommand CreateBlackPlanningMesh + { + get { return createBlackPlanningMesh ?? (createBlackPlanningMesh = new RelayCommand(obj => { CreateBlackMesh(); })); } + } + + private void ReadRedPlanningCSV() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.*"; + ofd.Filter = "Текстовый файл (*.csv)|*.csv|Все файлы (*.*)|*.*"; + ofd.Title = "Заполнение таблицы"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + + RedPlanning.Clear(); + try + { + using (StreamReader sr = new StreamReader(ofd.FileName, System.Text.Encoding.Default)) + { + string line; + PlanningVertex vert; + while ((line = sr.ReadLine()) != null) + { + vert = new PlanningVertex(); + vert.StringToProps(line); + RedPlanning.Add(vert); + } + } + } + catch (Exception e) + { + Alert(e.Message); + } + } + + internal void SaveRedPlanningInCsv() + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.DefaultExt = "*.csv"; + sfd.Filter = "Текстовый файл (*.csv)|*.csv"; + sfd.Title = "Сохранение таблицы"; + //sfd.AddExtension = true; + sfd.OverwritePrompt = true; + sfd.ShowDialog(); + + if (sfd.FileName == null || sfd.FileName == "") return; + + try + { + using (StreamWriter sw = new StreamWriter(sfd.FileName, false, System.Text.Encoding.Default)) + { + foreach (PlanningVertex item in RedPlanning) + { + sw.WriteLine(item.PropsToString()); + } + } + } + catch (Exception e) + { + Alert(e.Message); + } + } + + private void ReadBlackPlanningCSV() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.*"; + ofd.Filter = "Текстовый файл (*.csv)|*.csv|Все файлы (*.*)|*.*"; + ofd.Title = "Заполнение таблицы"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + + BlackPlanning.Clear(); + try + { + using (StreamReader sr = new StreamReader(ofd.FileName, System.Text.Encoding.Default)) + { + string line; + PlanningVertex vert; + while ((line = sr.ReadLine()) != null) + { + vert = new PlanningVertex(); + vert.StringToProps(line); + BlackPlanning.Add(vert); + } + } + } + catch (Exception e) + { + Alert(e.Message); + } + } + + internal void SaveBlackPlanningInCsv() + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.DefaultExt = "*.csv"; + sfd.Filter = "Текстовый файл (*.csv)|*.csv"; + sfd.Title = "Сохранение таблицы"; + //sfd.AddExtension = true; + sfd.OverwritePrompt = true; + sfd.ShowDialog(); + + if (sfd.FileName == null || sfd.FileName == "") return; + + try + { + using (StreamWriter sw = new StreamWriter(sfd.FileName, false, System.Text.Encoding.Default)) + { + foreach (PlanningVertex item in BlackPlanning) + { + sw.WriteLine(item.PropsToString()); + } + } + } + catch (Exception e) + { + Alert(e.Message); + } + } + + private void ReadPlanningsDXF() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.DefaultExt = "*.dxf"; + ofd.Filter = "Чертеж (*.dxf)|*.dxf"; + ofd.Title = "Импорт чертежа"; + ofd.ShowDialog(); + + if (ofd.FileName == null || ofd.FileName == "") return; + if (selectedStructure == null) return; + RedPlanning.Clear(); BlackPlanning.Clear(); + DxfDocument dxfDocument = DxfDocument.Load(ofd.FileName); + IEnumerable dxfTexts = dxfDocument.Texts; + PlanningVertex vert; int j = 1; int k = 1; + foreach (Text item in dxfTexts) + { + if (item.Layer.Name == "Red") + { + vert = new PlanningVertex + { + X = Math.Round(item.Position.X * 0.001, 3), + Y = Math.Round(item.Position.Y * 0.001, 3), + Number = j, + Red = double.Parse(item.Value) + }; + RedPlanning.Add(vert); + j++; + } + else if (item.Layer.Name == "Black") + { + vert = new PlanningVertex + { + X = Math.Round(item.Position.X * 0.001, 3), + Y = Math.Round(item.Position.Y * 0.001, 3), + Number = k, + Black = double.Parse(item.Value) + }; + BlackPlanning.Add(vert); + k++; + } + } + } + + void AddRedVertexToList() + { + RedPlanning.Add(new PlanningVertex() { Number = numVertex }); numVertex++; + //NameStructure = listStructure[0].Name; + } + void RenumberingRedVertexesInList() + { + int j = 1; + foreach (PlanningVertex item in RedPlanning) + { + item.Number = j; + j++; + } + numVertex = j; + RedPlanning = new ObservableCollection(RedPlanning); + } + void UpdateRedVertexesInList() + { + RedPlanning = new ObservableCollection(RedPlanning); + SaveDB(); + } + + void AddBlackVertexToList() + { + BlackPlanning.Add(new PlanningVertex() { Number = numVertex }); numVertex++; + //NameStructure = listStructure[0].Name; + } + void RenumberingBlackVertexesInList() + { + int j = 1; + foreach (PlanningVertex item in BlackPlanning) + { + item.Number = j; + j++; + } + numVertex = j; + BlackPlanning = new ObservableCollection(BlackPlanning); + } + void UpdateBlackVertexesInList() + { + BlackPlanning = new ObservableCollection(BlackPlanning); + SaveDB(); + } + + internal void CreateRedMesh() + { + if (selectedStructure == null || selectedStructure.RedPlanning == null || selectedStructure.RedPlanning.Count == 0) return; + + Polygon polygon = new Polygon(); + Vertex vrtx; + int i = 1; + foreach (PlanningVertex item in selectedStructure.RedPlanning) + { + vrtx = new Vertex(item.X, item.Y, item.Number, 1); + vrtx.Attributes[0] = item.Red; + polygon.Add(vrtx); + i++; + } + GenericMesher mesher = new GenericMesher(); + ConstraintOptions constraint = new ConstraintOptions(); + constraint.Convex = true; + MeshRedPlanning = (TriangleNet.Mesh)mesher.Triangulate(polygon, constraint); + Alert("\"Красная\" триангуляционная сеть создана"); + } + + internal void CreateBlackMesh() + { + if (selectedStructure == null || selectedStructure.BlackPlanning == null || selectedStructure.BlackPlanning.Count == 0) return; + + Polygon polygon = new Polygon(); + Vertex vrtx; + int i = 1; + foreach (PlanningVertex item in selectedStructure.BlackPlanning) + { + vrtx = new Vertex(item.X, item.Y, item.Number, 1); + vrtx.Attributes[0] = item.Black; + polygon.Add(vrtx); + i++; + } + GenericMesher mesher = new GenericMesher(); + ConstraintOptions constraint = new ConstraintOptions(); + constraint.Convex = true; + MeshBlackPlanning = (TriangleNet.Mesh)mesher.Triangulate(polygon, constraint); + Alert("\"Черная\" триангуляционная сеть создана"); + } + } +} diff --git a/VM/PlayGroundVM.cs b/VM/PlayGroundVM.cs new file mode 100644 index 0000000..1731d39 --- /dev/null +++ b/VM/PlayGroundVM.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + int numPG = 1; + PlayGround selectedPlayGround; + string namePlayGround; + ObservableCollection listPlayGround = new ObservableCollection(); + + public ObservableCollection ListPlayGround { get => listPlayGround; set { listPlayGround = value; OnPropertyChanged(); } } + public string NamePlayGround { get => namePlayGround; set { namePlayGround = value; OnPropertyChanged(); } } + public PlayGround SelectedPlayGround { get => selectedPlayGround; set { selectedPlayGround = value; OnPropertyChanged(); ChangeSelectedPlayGround(); } } + + private RelayCommand addPlayGround; + public RelayCommand AddPlayGround + { + get { return addPlayGround ?? (addPlayGround = new RelayCommand(obj => { AddPlayGroundToList(); })); } + } + + private RelayCommand updatePlayGround; + public RelayCommand UpdatePlayGrounds + { + get { return updatePlayGround ?? (updatePlayGround = new RelayCommand(obj => { UpdatePlayGroundInList(); })); } + } + + private RelayCommand renumPlayGround; + public RelayCommand RenumPlayGrounds + { + get { return renumPlayGround ?? (renumPlayGround = new RelayCommand(obj => { RenumberingPlayGroundInList(); })); } + } + + void AddPlayGroundToList() + { + ListPlayGround.Add(new PlayGround() { Number = numPG }); numPG++; + //CreateListNumberTypeBet(); + //NamePlayGround = listPlayGround[0].Name; + } + void RenumberingPlayGroundInList() + { + int j = 1; + foreach (PlayGround item in ListPlayGround) + { + item.Number = j; + j++; + } + numPG = j; + ListPlayGround = new ObservableCollection(ListPlayGround); + } + void UpdatePlayGroundInList() + { + ListPlayGround = new ObservableCollection(ListPlayGround); + SaveDB(); + } + + //void ChangeSelClassBet() + //{ + // //if (selectedBet==null) return; + // CreateListNumberTypeBet(); + //} + + //void CreateListNumberTypeBet() + //{ + // //listNumberTypeArm = new List(); + // ListNumberTypeBet = from bet in listBet select bet.Id; + //} + + void ChangeSelectedPlayGround() + { + if (listPlayGround.Count == 0 || selectedPlayGround == null) return; + NamePlayGround = SelectedPlayGround.Name; + ListIGE = selectedPlayGround.IGEs; + ListBore = selectedPlayGround.Bores; + ListStructure = selectedPlayGround.Structures; + CreateListNumIGEs(); + CreateListShemas(); + CreateListTypeFoundations(); + } + } +} diff --git a/VM/RelayCommand.cs b/VM/RelayCommand.cs new file mode 100644 index 0000000..b888336 --- /dev/null +++ b/VM/RelayCommand.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace GroundOrganizer +{ + public class RelayCommand : ICommand + { + private Action execute; + private Func canExecute; + + public event EventHandler CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + public RelayCommand(Action execute, Func canExecute = null) + { + this.execute = execute; + this.canExecute = canExecute; + } + + public bool CanExecute(object parameter) + { + return this.canExecute == null || this.canExecute(parameter); + } + + public void Execute(object parameter) + { + this.execute(parameter); + } + } +} + diff --git a/VM/StructuresVM.cs b/VM/StructuresVM.cs new file mode 100644 index 0000000..dc63a70 --- /dev/null +++ b/VM/StructuresVM.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + int numStructure = 1; + string nameStructure; + private string structureNote; + Structure selectedStructure; + ObservableCollection listStructure = new ObservableCollection(); + + public ObservableCollection ListStructure { get => listStructure; set { listStructure = value; OnPropertyChanged(); } } + + private IEnumerable listShemas; + public IEnumerable ListShemas { get => listShemas; set { listShemas = value; OnPropertyChanged(); } } + public string StructureNote { get => structureNote; set { structureNote = value; OnPropertyChanged(); } } + + private RelayCommand addStructure; + public RelayCommand AddStructure + { + get { return addStructure ?? (addStructure = new RelayCommand(obj => { AddStructureToList(); })); } + } + + private RelayCommand updateStructure; + public RelayCommand UpdateStructures + { + get { return updateStructure ?? (updateStructure = new RelayCommand(obj => { UpdateStructureInList(); })); } + } + + private RelayCommand renumStructure; + + public RelayCommand RenumStructures + { + get { return renumStructure ?? (renumStructure = new RelayCommand(obj => { RenumberingStructureInList(); })); } + } + + public Structure SelectedStructure { get => selectedStructure; set { selectedStructure = value; OnPropertyChanged(); ChangeSelectedStructure(); } } + + public string NameStructure { get => nameStructure; set { nameStructure = value; OnPropertyChanged(); } } + + void AddStructureToList() + { + ListStructure.Add(new Structure() { Number = numStructure }); numStructure++; + //NameStructure = listStructure[0].Name; + } + void RenumberingStructureInList() + { + int j = 1; + foreach (Structure item in ListStructure) + { + item.Number = j; + j++; + } + numStructure = j; + ListStructure = new ObservableCollection(ListStructure); + } + void UpdateStructureInList() + { + ListStructure = new ObservableCollection(ListStructure); + SaveDB(); + } + + void ChangeSelectedStructure() + { + if (listStructure.Count == 0 || selectedStructure == null) return; + NameStructure = selectedStructure.Name; + ListFoundation = selectedStructure.Foundations; + RedPlanning = selectedStructure.RedPlanning; + BlackPlanning = selectedStructure.BlackPlanning; + if (redPlanning == null) RedPlanning = new ObservableCollection(); + if (blackPlanning == null) BlackPlanning = new ObservableCollection(); + } + + void CreateListShemas() + { + if (listStructure == null || listPlayGround == null) return; + ListShemas = new List() { TypeFlexStructure.Гибкая, TypeFlexStructure.Жесткая }; + try + { + StructuresPage structuresPage = (StructuresPage)MW.StructuresFrame.Content; + structuresPage.flexListCbxCol.ItemsSource = listShemas; + } + catch + { + return; + } + } + } +} diff --git a/VM/UnitsViewModel .cs b/VM/UnitsViewModel .cs new file mode 100644 index 0000000..45dea90 --- /dev/null +++ b/VM/UnitsViewModel .cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + UnitsLin[] unitsL = { UnitsLin.м, UnitsLin.см, UnitsLin.мм }; + UnitsArea[] unitsA = { UnitsArea.м, UnitsArea.см, UnitsArea.мм }; + UnitsForce[] unitsF = { UnitsForce.т, UnitsForce.кН, UnitsForce.Н }; + UnitsStress[] unitsS = { UnitsStress.т, UnitsStress.кН, UnitsStress.Н, UnitsStress.МПа, UnitsStress.кПа }; + UnitsLin unitsLId = UnitsLin.м; + UnitsLin unitsSectId = UnitsLin.см; + UnitsLin unitsDarmId = UnitsLin.мм; + UnitsArea unitsAarmId = UnitsArea.см; + UnitsArea unitsAMatId = UnitsArea._; + UnitsLin unitsLForcId = UnitsLin.м; + UnitsArea unitsAStressId = UnitsArea._; + UnitsLin unitsCrackId = UnitsLin.мм; + UnitsStress unitsSMatId = UnitsStress.МПа; + UnitsStress unitsSStressId = UnitsStress.МПа; + UnitsForce unitsFForceId = UnitsForce.кН; + internal double scaleDimLength = 1; + internal double scaleDimSect = 0.01; + internal double scaleDimDarm = 0.001; + internal double scaleDimAarm = 0.0001; + internal double scaleDimLfrc = 1; + internal double scaleDimFfrc = 1; + internal double scaleDimStress = 0.001; + internal double scaleDimMat = 0.001; + internal double scaleDimCrack = 0.001; + + public UnitsLin[] UnitsL { get => unitsL; set => unitsL = value; } + public UnitsArea[] UnitsA { get => unitsA; set => unitsA = value; } + public UnitsForce[] UnitsF { get => unitsF; set => unitsF = value; } + public UnitsStress[] UnitsS { get => unitsS; set => unitsS = value; } + + public UnitsLin UnitsLId { get => unitsLId; set { unitsLId = value; OnPropertyChanged(); ChangeUnits(); } } + public UnitsLin UnitsSectId { get => unitsSectId; set { unitsSectId = value; OnPropertyChanged(); ChangeUnits(); } } + public UnitsLin UnitsDarmId { get => unitsDarmId; set { unitsDarmId = value; OnPropertyChanged(); ChangeUnits(); } } + public UnitsArea UnitsAarmId { get => unitsAarmId; set { unitsAarmId = value; OnPropertyChanged(); ChangeUnits(); } } + public UnitsArea UnitsAMatId { get => unitsAMatId; set { unitsAMatId = value; OnPropertyChanged(); ChangeUnits(); } } + public UnitsLin UnitsLForcId { get => unitsLForcId; set { unitsLForcId = value; OnPropertyChanged(); ChangeUnits(); } } + public UnitsArea UnitsAStressId { get => unitsAStressId; set { unitsAStressId = value; OnPropertyChanged(); ChangeUnits(); } } + public UnitsLin UnitsCrackId { get => unitsCrackId; set { unitsCrackId = value; OnPropertyChanged(); ChangeUnits(); } } + public UnitsForce UnitsFForceId { get => unitsFForceId; set { unitsFForceId = value; OnPropertyChanged(); ChangeUnits(); } } + public UnitsStress UnitsSMatId { get => unitsSMatId; set { unitsSMatId = value; OnPropertyChanged(); ChangeUnits(); + if (value == UnitsStress.МПа || value == UnitsStress.кПа) UnitsAMatId = UnitsArea._; } } + public UnitsStress UnitsSStressId { get => unitsSStressId; set { unitsSStressId = value; OnPropertyChanged(); ChangeUnits(); + if (value == UnitsStress.МПа || value == UnitsStress.кПа) UnitsAStressId = UnitsArea._; } } + + + void ChangeUnits() + { + scaleDimAarm = ScaleAUnits(unitsAarmId); + scaleDimCrack = ScaleLUnits(unitsCrackId); + scaleDimDarm = ScaleLUnits(unitsDarmId); + scaleDimFfrc = ScaleFUnits(unitsFForceId); + scaleDimLength = ScaleLUnits(unitsLId); + scaleDimLfrc = ScaleLUnits(unitsLForcId); + scaleDimSect = ScaleLUnits(unitsSectId); + scaleDimMat = ScaleSUnits(unitsSMatId,unitsAMatId); + scaleDimStress = ScaleSUnits(unitsSStressId, unitsAStressId); + //Bfloat = B / scaleDimSect; + //Hfloat = H / scaleDimSect; + //Dfloat = D / scaleDimSect; + //D1float = D1 / scaleDimSect; + } + + void ChangeValues() + { + //B = bfloat * scaleDimSect; + //H = hfloat * scaleDimSect; + //D = dfloat * scaleDimSect; + //D1 = d1float * scaleDimSect; + } + + double ScaleLUnits(UnitsLin unit) + { + double res = 1; + switch (unit) + { + case UnitsLin.мм: res = 1E-3; break; + case UnitsLin.см: res = 1E-2; break; + } + return res; + } + + double ScaleAUnits(UnitsArea unit) + { + double res = 1; + switch (unit) + { + case UnitsArea.мм: res = 1E-6; break; + case UnitsArea.см: res = 1E-4; break; + } + return res; + } + + double ScaleFUnits(UnitsForce unit) + { + double res = 1; + switch (unit) + { + case UnitsForce.Н: res = 1E+3; break; + case UnitsForce.т: res = 0.10194; break; + } + return res; + } + + double ScaleSUnits(UnitsStress unitS, UnitsArea unitA) + { + double res = 1; + if (unitS == UnitsStress.кН && unitA == UnitsArea.см) res = 1E-4; + if (unitS == UnitsStress.кН && unitA == UnitsArea.мм) res = 1E-6; + if (unitS == UnitsStress.Н && unitA == UnitsArea.м) res = 1E+3; + if (unitS == UnitsStress.Н && unitA == UnitsArea.см) res = 0.1; + if (unitS == UnitsStress.Н && unitA == UnitsArea.мм) res = 1E-3; + if (unitS == UnitsStress.т && unitA == UnitsArea.м) res = 0.10194; + if (unitS == UnitsStress.т && unitA == UnitsArea.см) res = 1E-5; + if (unitS == UnitsStress.т && unitA == UnitsArea.мм) res = 1.01937E-7; + if (unitS == UnitsStress.МПа) res = 1E-3; + return res; + } + } +} diff --git a/VM/ViewModel.cs b/VM/ViewModel.cs new file mode 100644 index 0000000..4ab3af0 --- /dev/null +++ b/VM/ViewModel.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media.Imaging; + +namespace GroundOrganizer +{ + public partial class ViewModel : INotifyPropertyChanged + { + string title; + ToSerializ ser = new ToSerializ(); + MainWindow MW; + //MainPage MP; + private string basePath; + + public string BasePath { get => basePath; set { basePath = value; OnPropertyChanged(); } } + + public ViewModel() + { + title = "GroundOrganizer"; + MW = App.Current.MainWindow as MainWindow; + //MW.contentFrame.Content = MP; + MW.Title = title; + BasePath = Properties.Settings.Default.BasePath; + StructureNote = "к числу зданий и сооружений с жесткой конструктивной схемой относятся:" + + "\n- здания панельные, блочные и кирпичные, в которых междуэтажные" + + "\nперекрытия опираются по всему контуру на поперечные и продольные" + + "\nстены или только на поперечные несущие стены при малом их шаге;" + + "\n- сооружения типа башен, силосных корпусов, дымовых труб, домен и др."; + BoresNote = "* положительное значение отметки уровня грунтовых вод относительно устья скважины"; + + } + + private RelayCommand openGroundBase; + public RelayCommand OpenGroundBase + { + get { return openGroundBase ?? (openGroundBase = new RelayCommand(obj => { ReadDB(); })); } + } + + public string Title { get => title; set => title = value; } + + string GetGroundBaseFile() + { + Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog(); + ofd.DefaultExt = "*.*"; + ofd.Filter = "База данных инженерно-геологических площадок (*.grndb)|*.grndb|Все файлы (*.*)|*.*"; + ofd.Title = "Выбор файла с базой данных инженерно-геологических площадок"; + ofd.ShowDialog(); + return ofd.FileName; + } + + internal void SaveDB() + { + //ser = new ToSerializ { PlayGroundList = ListPlayGround }; + // создаем объект BinaryFormatter + BinaryFormatter formatter = new BinaryFormatter(); + // получаем поток, куда будем записывать сериализованный объект + using (FileStream fs = new FileStream(Properties.Settings.Default.BasePath, FileMode.OpenOrCreate)) + { + formatter.Serialize(fs, ListPlayGround); + } + //Alert("Введенные данные успешно сохранены"); + } + + internal void ReadDB() + { + Properties.Settings.Default.BasePath = GetGroundBaseFile(); + Properties.Settings.Default.Save(); + BasePath = Properties.Settings.Default.BasePath; + if (File.Exists(Properties.Settings.Default.BasePath) == true) + { + // создаем объект BinaryFormatter + BinaryFormatter formatter = new BinaryFormatter(); + + using (FileStream fs = new FileStream(Properties.Settings.Default.BasePath, FileMode.OpenOrCreate)) + { + //ToSerializ ser = (ToSerializ)formatter.Deserialize(fs); + ListPlayGround = formatter.Deserialize(fs) as ObservableCollection; + } + } + + } + + public event PropertyChangedEventHandler PropertyChanged; + public void OnPropertyChanged([CallerMemberName]string prop = "") + { + if (PropertyChanged != null) + PropertyChanged(this, new PropertyChangedEventArgs(prop)); + } + } +} diff --git a/Windows/AlertWindow.xaml b/Windows/AlertWindow.xaml new file mode 100644 index 0000000..01fb967 --- /dev/null +++ b/Windows/AlertWindow.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +