using Apache.Arrow; using Apache.Arrow.Ipc; using Apache.Arrow.Memory; using CaeGlobals; using CaeMesh; using CsvHelper; using CsvHelper.Configuration; using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; using System.Linq; namespace RBFMorphing { [Serializable] public sealed class MorphManager { private List _fixedSurface; private List _deformedDomain; private List _controlPoint; public List FixedSurface => _fixedSurface; public List DeformedDomain => _deformedDomain; public List ControlPoint => _controlPoint; // ReSharper disable once ConvertConstructorToMemberInitializers public MorphManager() { _fixedSurface = new List(); _deformedDomain = new List(); _controlPoint = new List(); } public void Clear() { if (_fixedSurface.Count > 0) { _fixedSurface.Clear(); } if (_deformedDomain.Count > 0) { _deformedDomain.Clear(); } if (_controlPoint.Count > 0) { _controlPoint.Clear(); } } public void ReplaceElementSet(string oldElementSetName, FeElementSet elementSet) { foreach (var dd in DeformedDomain) { if (dd is ElementSet es && es.Name == oldElementSetName) { if (oldElementSetName != elementSet.Name) es.Name = elementSet.Name; es.MakeCache(); break; } } } public void ReplaceNodeSet(string oldNodeSetName, FeNodeSet nodeSet) { foreach (var cp in ControlPoint) { if (cp is NodeSet ns && ns.Name == oldNodeSetName) { if (oldNodeSetName != nodeSet.Name) ns.Name = nodeSet.Name; break; } } } public void ReplaceModelPartProperties(string oldPartName, PartProperties newPartProperties) { foreach (var dd in DeformedDomain) { if (dd is BasePart basePart && basePart.Name == oldPartName) { if (oldPartName != newPartProperties.Name) basePart.Name = newPartProperties.Name; break; } } } public void ReplaceSurface(string oldSurfaceName, FeSurface surface) { foreach (var fs in FixedSurface) { if (fs is Surface surf && surf.Name == oldSurfaceName) { if (oldSurfaceName != surface.Name) surf.Name = surface.Name; surf.MakeCache(); break; } } } private sealed class ExportMap : ClassMap { public ExportMap() { Map(n => n.Id).Index(0).Name("id"); Map(n => n.X).Index(1).Name("x"); Map(n => n.Y).Index(2).Name("y"); Map(n => n.Z).Index(3).Name("z"); } } public void WriteCsvFile(string fullPath, List nodes) { using (var writer = new StreamWriter(fullPath)) using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) { csv.Context.RegisterClassMap(); csv.WriteRecords(nodes); } } private sealed class ImportMap : ClassMap { public ImportMap() { Map(n => n.Id).Index(0).Name("id", "ID", "Id"); Map(n => n.Dx).Index(1).Name("dx", "DX", "Dx"); Map(n => n.Dy).Index(2).Name("dy", "DY", "Dy"); Map(n => n.Dz).Index(3).Name("dz", "DZ", "Dz"); } } public List LoadCsvFile(string fullPath) { List nodes = new List(); if (nodes == null) throw new ArgumentNullException(nameof(nodes)); using (var reader = new StreamReader(fullPath)) using (var csv = new CsvReader(reader, CultureInfo.CurrentCulture)) { csv.Context.RegisterClassMap(); foreach (var record in csv.GetRecords()) { nodes.Add(record); } } return nodes; } private void WriteDeformedDomain(string workDirectory, FeMesh mesh) { var sortedSet = CheckParameters(workDirectory, mesh); foreach (var id in DeformedDomain .Where(dd => dd.Labels != null && dd.Labels.Length > 0) .SelectMany(dd => dd.Labels)) { sortedSet.Add(id); } var fullFile = Path.Combine(workDirectory, "deformed_domain.arrow"); WriteWithArrowLibrary(fullFile, mesh, sortedSet); } private void WriteFixedSurface(string workDirectory, FeMesh mesh) { var sortedSet = CheckParameters(workDirectory, mesh); foreach (var id in FixedSurface .Where(fs => fs.Labels != null && fs.Labels.Length > 0) .SelectMany(fs => fs.Labels)) { sortedSet.Add(id); } var fullFile = Path.Combine(workDirectory, "fixed_surface.arrow"); WriteWithArrowLibrary(fullFile, mesh, sortedSet); } private static SortedSet CheckParameters(string workDirectory, FeMesh mesh) { if (workDirectory.IsNullOrEmptyOrWhiteSpace() || !Directory.Exists(workDirectory)) throw new ArgumentNullException(nameof(workDirectory)); if(mesh == null) throw new ArgumentNullException(nameof(mesh)); SortedSet sortedSet = new SortedSet(); if (sortedSet == null) throw new ArgumentNullException(nameof(sortedSet)); return sortedSet; } private static void WriteWithArrowLibrary(string fullFile, FeMesh mesh, SortedSet sortedSet) { List nodes = new List(); foreach (var key in sortedSet) { if (mesh.Nodes.TryGetValue(key, out var node)) { nodes.Add(new Node(node)); } } if (nodes.Count <= 0) return; var memoryAllocator = new NativeMemoryAllocator(); var recordBatch = new RecordBatch.Builder(memoryAllocator) .Append("id", false, col => col.Int32(array => array.AppendRange(nodes.Select(n => n.Id)))) .Append("x", false, col => col.Double(array => array.AppendRange(nodes.Select(n => n.X)))) .Append("y", false, col => col.Double(array => array.AppendRange(nodes.Select(n => n.Y)))) .Append("z", false, col => col.Double(array => array.AppendRange(nodes.Select(n => n.Z)))) .Build(); using (var stream = File.OpenWrite(fullFile)) using (var writer = new ArrowFileWriter(stream, recordBatch.Schema)) { writer.WriteRecordBatch(recordBatch); writer.WriteEnd(); } } public void ExportToArrow(string workDirectory, FeMesh mesh) { WriteDeformedDomain(workDirectory, mesh); WriteFixedSurface(workDirectory, mesh); } public void LoadControlPoints(FeMesh mesh, BindingList nodes) { if(mesh == null || nodes == null) throw new ArgumentNullException(nameof(mesh)); SortedSet sortedSet = new SortedSet(); if (sortedSet == null) throw new ArgumentNullException(nameof(sortedSet)); if (nodes.Count > 0) { nodes.Clear(); } foreach (var cp in ControlPoint) { if (!(cp is NodeSet nodeSet)) continue; foreach (var id in nodeSet.Labels) { sortedSet.Add(id); } } foreach (var node in sortedSet.Select(i => mesh.Nodes[i])) { nodes.Add(new Node(node)); } } public void WriteControlPoints(string workDirectory, List nodes) { if (workDirectory.IsNullOrEmptyOrWhiteSpace() || !Directory.Exists(workDirectory)) throw new ArgumentNullException(nameof(workDirectory)); if (nodes == null) throw new ArgumentNullException(nameof(nodes)); if (nodes.Count <= 0) return; var memoryAllocator = new NativeMemoryAllocator(); var recordBatch = new RecordBatch.Builder(memoryAllocator) .Append("id", false, col => col.Int32(array => array.AppendRange(nodes.Select(n => n.Id)))) .Append("x", false, col => col.Double(array => array.AppendRange(nodes.Select(n => n.X)))) .Append("y", false, col => col.Double(array => array.AppendRange(nodes.Select(n => n.Y)))) .Append("z", false, col => col.Double(array => array.AppendRange(nodes.Select(n => n.Z)))) .Append("dx", false, col => col.Double(array => array.AppendRange(nodes.Select(n => n.Dx)))) .Append("dy", false, col => col.Double(array => array.AppendRange(nodes.Select(n => n.Dy)))) .Append("dz", false, col => col.Double(array => array.AppendRange(nodes.Select(n => n.Dz)))) .Build(); string fullFile = Path.Combine(workDirectory, "control_points.arrow"); using (var stream = File.OpenWrite(fullFile)) using (var writer = new ArrowFileWriter(stream, recordBatch.Schema)) { writer.WriteRecordBatch(recordBatch); writer.WriteEnd(); } } public void DeformedMesh(string workDirectory, FeMesh mesh) { using (var stream = File.OpenRead(@"D:\WorkSpace\deformed_mesh.arrow")) using (var reader = new ArrowFileReader(stream)) { var recordBatch = reader.ReadNextRecordBatch(); var columnId = (Int32Array) recordBatch.Column(0); var columnX = (DoubleArray) recordBatch.Column(1); var columnY = (DoubleArray) recordBatch.Column(2); var columnZ = (DoubleArray) recordBatch.Column(3); for (int i = 0; i < columnX.Values.Length; i++) { int id = columnId.Values[i]; double dx = columnX.Values[i]; double dy = columnY.Values[i]; double dz = columnZ.Values[i]; FeNode node = mesh.Nodes[id]; node.X += dx; node.Y += dy; node.Z += dz; mesh.Nodes[id] = node; } } } } }