332 lines
11 KiB
C#
332 lines
11 KiB
C#
|
|
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<AbstractClass> _fixedSurface;
|
|||
|
|
private List<AbstractClass> _deformedDomain;
|
|||
|
|
private List<AbstractClass> _controlPoint;
|
|||
|
|
|
|||
|
|
public List<AbstractClass> FixedSurface => _fixedSurface;
|
|||
|
|
public List<AbstractClass> DeformedDomain => _deformedDomain;
|
|||
|
|
public List<AbstractClass> ControlPoint => _controlPoint;
|
|||
|
|
|
|||
|
|
// ReSharper disable once ConvertConstructorToMemberInitializers
|
|||
|
|
public MorphManager()
|
|||
|
|
{
|
|||
|
|
_fixedSurface = new List<AbstractClass>();
|
|||
|
|
_deformedDomain = new List<AbstractClass>();
|
|||
|
|
_controlPoint = new List<AbstractClass>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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<Node>
|
|||
|
|
{
|
|||
|
|
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<Node> nodes)
|
|||
|
|
{
|
|||
|
|
using (var writer = new StreamWriter(fullPath))
|
|||
|
|
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
|||
|
|
{
|
|||
|
|
csv.Context.RegisterClassMap<ExportMap>();
|
|||
|
|
|
|||
|
|
csv.WriteRecords(nodes);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private sealed class ImportMap : ClassMap<Node>
|
|||
|
|
{
|
|||
|
|
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<Node> LoadCsvFile(string fullPath)
|
|||
|
|
{
|
|||
|
|
List<Node> nodes = new List<Node>();
|
|||
|
|
|
|||
|
|
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<ImportMap>();
|
|||
|
|
|
|||
|
|
foreach (var record in csv.GetRecords<Node>())
|
|||
|
|
{
|
|||
|
|
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<int> 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<int> sortedSet = new SortedSet<int>();
|
|||
|
|
|
|||
|
|
if (sortedSet == null) throw new ArgumentNullException(nameof(sortedSet));
|
|||
|
|
return sortedSet;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static void WriteWithArrowLibrary(string fullFile, FeMesh mesh, SortedSet<int> sortedSet)
|
|||
|
|
{
|
|||
|
|
List<Node> nodes = new List<Node>();
|
|||
|
|
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<Node> nodes)
|
|||
|
|
{
|
|||
|
|
if(mesh == null || nodes == null)
|
|||
|
|
throw new ArgumentNullException(nameof(mesh));
|
|||
|
|
|
|||
|
|
SortedSet<int> sortedSet = new SortedSet<int>();
|
|||
|
|
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<Node> 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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|