Files
wg_cpso/RBFMorphing/MorphManager.cs

332 lines
11 KiB
C#
Raw Normal View History

2026-03-25 18:20:24 +08:00
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;
}
}
}
}
}