Add import primitives to cross-section

This commit is contained in:
Evgeny Redikultsev
2025-11-02 14:07:06 +05:00
parent ba0d3e580b
commit 871be6cb46
14 changed files with 321 additions and 47 deletions

View File

@@ -0,0 +1,52 @@
using System.Windows;
using System.Windows.Input;
namespace StructureHelper.Infrastructure.Behaviors
{
public static class FileDropBehavior
{
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached(
"Command",
typeof(ICommand),
typeof(FileDropBehavior),
new PropertyMetadata(null, OnCommandChanged));
public static void SetCommand(UIElement element, ICommand value)
{
element.SetValue(CommandProperty, value);
}
public static ICommand GetCommand(UIElement element)
{
return (ICommand)element.GetValue(CommandProperty);
}
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is UIElement element)
{
element.AllowDrop = true;
element.PreviewDragOver += (sender, args) =>
{
args.Effects = args.Data.GetDataPresent(DataFormats.FileDrop)
? DragDropEffects.Copy
: DragDropEffects.None;
args.Handled = true;
};
element.Drop += (sender, args) =>
{
if (args.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] files = (string[])args.Data.GetData(DataFormats.FileDrop);
var command = GetCommand(element);
if (command?.CanExecute(files) == true)
command.Execute(files);
}
};
}
}
}
}

View File

@@ -5,6 +5,7 @@ using StructureHelper.Models.Materials;
using StructureHelper.Windows.PrimitiveTemplates.RCs.Beams;
using StructureHelper.Windows.PrimitiveTemplates.RCs.RectangleBeam;
using StructureHelper.Windows.ViewModels;
using StructureHelper.Windows.ViewModels.Errors;
using StructureHelper.Windows.ViewModels.Forces;
using StructureHelper.Windows.ViewModels.Materials;
using StructureHelper.Windows.ViewModels.NdmCrossSections;
@@ -13,9 +14,12 @@ using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperLogics.Models.CrossSections;
using StructureHelperLogics.Models.Templates.CrossSections.RCs;
using StructureHelperLogics.Models.Templates.RCs;
using StructureHelperLogics.NdmCalculations.Primitives;
using StructureHelperLogics.Services.NdmPrimitives;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
@@ -123,6 +127,42 @@ namespace StructureHelper.Windows.MainWindow
private RelayCommand showVisualProperty;
private RelayCommand selectPrimitive;
private RelayCommand fileDroppedCommand;
private string fileName;
public ICommand FileDroppedCommand => fileDroppedCommand ??= new RelayCommand(OnFileDropped);
private void OnFileDropped(object obj)
{
if (obj is string[] files && files.Length > 0)
{
fileName = files.First();
string extension = Path.GetExtension(fileName).ToLowerInvariant();
if (extension == ".dxf")
{
SafetyProcessor.RunSafeProcess(GetPrimitivesFromFile,"Error of obtaining of primitives, see detail information");
}
else
{
System.Windows.MessageBox.Show($"Unsupported file type: {extension}");
}
}
else
{
System.Windows.MessageBox.Show($"Error of file");
}
}
private void GetPrimitivesFromFile()
{
var importFromFileLogic = new GetPrimitivesByFile() { FileName = fileName };
importFromFileLogic.Import();
var ndmPrimitives = importFromFileLogic.Primitives;
var primitives = PrimitiveOperations.ConvertNdmPrimitivesToPrimitiveBase(ndmPrimitives);
repository.Primitives.AddRange(ndmPrimitives);
PrimitiveLogic.AddItems(primitives);
PrimitiveLogic.Refresh();
}
public CrossSectionViewModel(ICrossSection section)
{

View File

@@ -6,6 +6,7 @@
xmlns:local="clr-namespace:StructureHelper.Windows.Shapes"
xmlns:uc="clr-namespace:StructureHelper.Windows.UserControls"
xmlns:ucwp="clr-namespace:StructureHelper.Windows.UserControls.WorkPlanes"
xmlns:behavior="clr-namespace:StructureHelper.Infrastructure.Behaviors"
d:DataContext="{d:DesignInstance local:PolygonShapeViewModel}"
mc:Ignorable="d"
Title="Polygon" Height="450" Width="800" MinHeight="250" MinWidth="400" MaxHeight="800" MaxWidth="1200" WindowStartupLocation="CenterScreen">
@@ -117,7 +118,7 @@
</Button>
</ToolBar>
</ToolBarTray>
<Grid>
<Grid behavior:FileDropBehavior.Command="{Binding FileDroppedCommand}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" MinWidth="100" MaxWidth="250"/>
<ColumnDefinition/>

View File

@@ -1,11 +1,7 @@
using netDxf;
using netDxf.Entities;
using netDxf.Header;
using netDxf.Tables;
using netDxf.Entities;
using StructureHelper.Infrastructure;
using StructureHelper.Infrastructure.UI.GraphicalPrimitives;
using StructureHelper.Services.Exports;
using StructureHelper.Windows.BeamShears;
using StructureHelper.Windows.Shapes.Logics;
using StructureHelper.Windows.UserControls.WorkPlanes;
using StructureHelper.Windows.ViewModels;
@@ -13,14 +9,14 @@ using StructureHelper.Windows.ViewModels.Errors;
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Models.Shapes;
using StructureHelperCommon.Models.Shapes.Logics;
using StructureHelperCommon.Services.Exports;
using StructureHelperCommon.Services.Exports.Factories;
using StructureHelperLogics.Models.BeamShears;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
namespace StructureHelper.Windows.Shapes
@@ -28,7 +24,8 @@ namespace StructureHelper.Windows.Shapes
public class PolygonShapeViewModel : OkCancelViewModelBase
{
private const int minVertexCount = 3;
private const string ErrorOfUpdatingOfPolygon = "Error of updating of polygon";
private const string ErrorOfObtainigOfPolyline = "Error of obtaining of dxf polyline";
private readonly IPoint2D absoluteCenter;
private readonly IPoint2D localCenter;
private readonly ILinePolygonShape polygonShape;
@@ -67,11 +64,61 @@ namespace StructureHelper.Windows.Shapes
public ICommand FlipHorizontalCommand => flipHorizontalCommand ??= new RelayCommand(FlipHorizontal);
public ICommand ImportFromDxfCommand => importFromDxfCommand ??= new RelayCommand(ImportFromDxf);
public ICommand FileDroppedCommand => fileDroppedCommand ??= new RelayCommand(OnFileDropped);
private void OnFileDropped(object obj)
{
if (obj is string[] files && files.Length > 0)
{
fileName = files.First();
string extension = Path.GetExtension(fileName).ToLowerInvariant();
if (extension == ".dxf")
{
SafetyProcessor.RunSafeProcess(GetPolyline2DFromFile, ErrorOfObtainigOfPolyline);
SafetyProcessor.RunSafeProcess(UpdatePolygon, ErrorOfUpdatingOfPolygon);
}
else
{
MessageBox.Show($"Unsupported file type: {extension}");
}
}
else
{
MessageBox.Show($"Error of file");
}
}
private void GetPolyline2DFromFile()
{
var logic = new SinglePolyline2DImportFromDxfLogic() { FileName = fileName };
logic.Import();
var polylines = logic.Polyline2Ds;
GetPolyline(polylines);
}
private void GetPolyline(List<Polyline2D> polylines)
{
if (polylines.Count > 0)
{
if (polylines.Count == 1)
{
polyline = polylines[0];
}
else
{
MessageBox.Show($"File: {fileName} has {polylines.Count} polylines, but one expected");
}
}
else
{
MessageBox.Show($"File: {fileName} does not has suitable polylines");
}
}
private void ImportFromDxf(object commandParameter)
{
SafetyProcessor.RunSafeProcess(GetPolyline2D, "Error of obtaining of dxf polyline");
SafetyProcessor.RunSafeProcess(UpdatePolygon, "Error of updating of polygon");
SafetyProcessor.RunSafeProcess(GetPolyline2D, ErrorOfObtainigOfPolyline);
SafetyProcessor.RunSafeProcess(UpdatePolygon, ErrorOfUpdatingOfPolygon);
}
private void UpdatePolygon()
@@ -85,13 +132,14 @@ namespace StructureHelper.Windows.Shapes
Redraw(null);
}
private static void GetPolyline2D()
private void GetPolyline2D()
{
FileIOInputData inputData = FileInputDataFactory.GetFileIOInputData(FileInputDataType.Dxf);
var logic = new SinglePolyline2DImportFromDxfLogic();
var importService = new ImportFromFileService(inputData, logic);
importService.Import();
polyline = logic.Polyline2D;
var polylines = logic.Polyline2Ds;
GetPolyline(polylines);
}
public ICommand ExportToDxfCommand => exportToDxfCommand ??= new RelayCommand(ExportToDxf);
@@ -160,11 +208,9 @@ namespace StructureHelper.Windows.Shapes
logic = new PolygonShapeToGraphicPrimitveConvertStrategy(this);
WorkPlaneRoot.PrimitiveCollection.Primitives.Clear();
var polygon = GetPolygonShape();
var updateStrategy = new LinePolygonShapeUpdateStrategy();
updateStrategy.Update(polygonShape, polygon);
WorkPlaneRoot.PrimitiveCollection.Primitives.Add(logic.Convert(polygon)[0]);
//foreach (var item in Vertices)
//{
// item.Refresh();
//}
}
private RelayCommand addVertexBeforeCommand;
@@ -205,16 +251,16 @@ namespace StructureHelper.Windows.Shapes
private RelayCommand flipVerticalCommand;
private RelayCommand flipHorizontalCommand;
private static Polyline2D polyline;
private RelayCommand fileDroppedCommand;
private string fileName;
public ICommand DeleteVertexCommand => deleteVertexCommand ??= new RelayCommand(DeleteVertex,
o => SelectedVertex is not null && Vertices.Count >= minVertexCount);
private void DeleteVertex(object commandParameter)
{
if (SelectedVertex is not null)
{
Vertices.Remove(SelectedVertex);
}
if (SelectedVertex is null) { return; }
Vertices.Remove(SelectedVertex);
Redraw(null);
}
}

View File

@@ -5,6 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:StructureHelper.Windows.UserControls"
xmlns:uc="clr-namespace:StructureHelper.Windows.UserControls"
xmlns:behavior="clr-namespace:StructureHelper.Infrastructure.Behaviors"
xmlns:enums="clr-namespace:StructureHelper.Infrastructure.Enums"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:infrastructure="clr-namespace:StructureHelper.Infrastructure"
@@ -42,12 +43,13 @@
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Visible"
Background="White">
<Grid x:Name="WorkPlaneGrid" Background="White">
<Grid x:Name="WorkPlaneGrid" Background="White"
behavior:FileDropBehavior.Command="{Binding ParentViewModel.FileDroppedCommand}">
<Canvas Name="WorkPlaneName"
ClipToBounds="True"
Width="{Binding Width}"
Height="{Binding Height}"
>
Height="{Binding Height}"
>
<Canvas.ContextMenu>
<ContextMenu>
<MenuItem Header="Add" DataContext="{Binding ParentViewModel.PrimitiveLogic}">

View File

@@ -1,12 +1,6 @@
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Models.Shapes.Logics;
using StructureHelperCommon.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Shapes;
namespace StructureHelperCommon.Models.Shapes
{

View File

@@ -15,9 +15,9 @@ namespace StructureHelperCommon.Models.Shapes
/// <inheritdoc />
public Guid Id { get; }
/// <inheritdoc />
public double X { get; set; }
public double X { get; set; } = 0;
/// <inheritdoc />
public double Y { get; set; }
public double Y { get; set; } = 0;
public Point2D(Guid id)
{
@@ -26,6 +26,12 @@ namespace StructureHelperCommon.Models.Shapes
public Point2D() : this(Guid.NewGuid()) { }
public Point2D(double x, double y) : this()
{
X = x;
Y = y;
}
public object Clone()
{
var newItem = new Point2D();

View File

@@ -1,19 +1,27 @@
using netDxf;
using netDxf.Entities;
using netDxf.Header;
using System;
using StructureHelperCommon.Services.Exports.Factories;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace StructureHelperCommon.Services.Exports
{
public class ShapesAllImportFromDxfLogic : IImportFromFileLogic
public class EntitiesImportFromDxfLogic : IImportFromFileLogic
{
public string FileName { get; set; }
public List<EntityObject> Entities { get; set; } = [];
public void Import()
{
string extension = Path.GetExtension(FileName).ToLowerInvariant();
if (extension == ".dxf")
{
GetEntities();
}
}
private void GetEntities()
{
// this check is optional but recommended before loading a DXF file
DxfVersion dxfVersion = DxfDocument.CheckDxfFileVersion(FileName);

View File

@@ -1,11 +1,6 @@
using netDxf;
using netDxf.Tables;
using StructureHelperCommon.Infrastructures.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperCommon.Services.Exports
{

View File

@@ -8,6 +8,6 @@ namespace StructureHelperCommon.Services.Exports
{
public interface IImportFromFileLogic : IImportLogic
{
string FileName { get; set; }
string? FileName { get; set; }
}
}

View File

@@ -1,18 +1,25 @@
using netDxf.Entities;
using System.Collections.Generic;
using System.Linq;
namespace StructureHelperCommon.Services.Exports
{
public class SinglePolyline2DImportFromDxfLogic : IImportFromFileLogic
{
public string FileName { get; set; }
public Polyline2D Polyline2D { get; private set; }
public string? FileName { get; set; }
public LayerNames LayerName { get; set; } = LayerNames.StructiralPrimitives;
public List<Polyline2D> Polyline2Ds { get; private set; } = [];
public void Import()
{
var importLogic = new ShapesAllImportFromDxfLogic() { FileName = FileName};
var importLogic = new EntitiesImportFromDxfLogic()
{
FileName = FileName
};
importLogic.Import();
var entities = importLogic.Entities;
Polyline2D = entities.Single(x => x is Polyline2D) as Polyline2D;
string layerName = new GetDxfLayerLogic().GetLayerName(LayerName);
var collection = entities.Where(x => x is Polyline2D && x.Layer.Name == layerName).ToList();
collection.ForEach(x => Polyline2Ds.Add(x as Polyline2D));
}
}
}

View File

@@ -0,0 +1,85 @@
using netDxf;
using netDxf.Entities;
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Models.Shapes;
using StructureHelperCommon.Services.Exports;
namespace StructureHelperLogics.NdmCalculations.Primitives
{
public class GetPrimitivesByDxfEntities : IObjectConvertStrategy<List<INdmPrimitive>, IEnumerable<EntityObject>>
{
private const double metresToMillimeters = 1000.0;
private List<INdmPrimitive> primitives = [];
private IGetDxfLayerLogic layerLogic = new GetDxfLayerLogic();
public List<INdmPrimitive> Convert(IEnumerable<EntityObject> source)
{
GetPrimitives(source);
return primitives;
}
private void GetPrimitives(IEnumerable<EntityObject> source)
{
primitives.Clear();
foreach (var dxfEntity in source)
{
if (dxfEntity is Polyline2D polyline2d)
{
primitives.Add(GetShapePolygon(polyline2d));
}
else if (dxfEntity is Circle circle)
{
primitives.Add(GetCirclePrimitive(circle));
}
else
{
throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(dxfEntity));
}
}
}
private INdmPrimitive GetCirclePrimitive(Circle circle)
{
INdmPrimitive primitive = null;
double radius = circle.Radius / metresToMillimeters;
double diameter = radius * 2.0;
if (circle.Layer.Name == layerLogic.GetLayerName(LayerNames.StructuralRebars))
{
RebarNdmPrimitive rebar = new (Guid.NewGuid())
{
Name = "Imported rebar",
Area = Math.PI * radius * radius
};
primitive = rebar;
}
else
{
EllipseNdmPrimitive ellipse = new(Guid.NewGuid())
{
Name = "Imported circle",
Width = diameter,
Height = diameter,
};
primitive = ellipse;
}
primitive.Center = new Point2D(circle.Center.X / metresToMillimeters, circle.Center.Y / metresToMillimeters);
return primitive;
}
private INdmPrimitive GetShapePolygon(Polyline2D polyline2d)
{
ShapeNdmPrimitive shapeNdmPrimitive = new(Guid.NewGuid())
{
Name = $"Imported polygon"
};
var convertLogic = new Polyline2DToLinePoligonConvertLogic();
LinePolygonShape polygonShape = convertLogic.Convert(polyline2d);
shapeNdmPrimitive.SetShape(polygonShape);
return shapeNdmPrimitive;
}
}
}

View File

@@ -0,0 +1,24 @@
using StructureHelperCommon.Services.Exports;
namespace StructureHelperLogics.NdmCalculations.Primitives
{
public class GetPrimitivesByFile : IGetPrimitivesLogic
{
private List<INdmPrimitive> primitives = [];
public string FileName { get; set; }
public List<INdmPrimitive> Primitives => primitives;
public void Import()
{
primitives.Clear();
var importEntitiesLogic = new EntitiesImportFromDxfLogic() { FileName = FileName};
importEntitiesLogic.Import();
if (importEntitiesLogic.Entities.Count != 0)
{
var primitivesLogic = new GetPrimitivesByDxfEntities();
primitives = primitivesLogic.Convert(importEntitiesLogic.Entities);
}
}
}
}

View File

@@ -0,0 +1,14 @@
using StructureHelperCommon.Services.Exports;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.NdmCalculations.Primitives
{
public interface IGetPrimitivesLogic : IImportLogic
{
List<INdmPrimitive> Primitives { get; }
}
}