Files
wg_cpso/CPSO/Forms/92_Knowledge/FrmStepsManager.cs
2026-03-26 06:50:22 +08:00

266 lines
8.9 KiB
C#

using CaeGlobals;
using CaeKnowledge;
using CaeKnowledge.Data;
using CaeKnowledge.View;
using CaeMesh;
using CaeModel;
using Plankton;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
// ReSharper disable SuggestVarOrType_SimpleTypes
// ReSharper disable SuggestVarOrType_BuiltInTypes
// ReSharper disable SuggestVarOrType_Elsewhere
// ReSharper disable InvertIf
namespace CPSO.Forms._92_Knowledge
{
public partial class FrmStepsManager : UserControls.FrmProperties
{
private readonly Controller Self;
public FrmStepsManager(Controller self)
{
InitializeComponent();
Self = self;
Text = @"分析模型定义";
gbProperties.Text = @"定义";
}
public void PrepareForm()
{
if (propertyGrid.SelectedObject is ViewJobs jobs)
{
}
}
private void FrmAddLoad_Load(object sender, EventArgs e)
{
var jobs = new ViewJobs(Self);
// 初始化下拉菜单
jobs.PopulateDropDownList();
// 初始化刀位文件列表
jobs.ToolPositionList.Clear();
if (Self?.ToolPositions != null)
{
jobs.ToolPositionList.AddRange(Self.ToolPositions);
}
propertyGrid.SelectedObject = jobs;
}
protected override async void OnApply(bool onOkAddNew)
{
try
{
if (!(propertyGrid.SelectedObject is ViewJobs viewSteps)) return;
// 基础计算步
Step baseStep = Self.GetStep(viewSteps.Step);
// Todo: 检查基础计算步
if (baseStep == null)
throw new CaeException($"无法找到对应的计算步:{viewSteps.Step}");
if (!Self.Model.Mesh.Surfaces.TryGetValue(viewSteps.Surface, out var surface))
throw new CaeException($"无法找到对应的曲面集:{viewSteps.Surface}");
Self.Form.SetStateWorking(@"构建切削力分析模型...");
// 先把所有计算步反激活
var stepList = Self.GetAllSteps().ToList();
stepList.ForEach(x =>
{
Self.ActivateDeactivateStep(x.Name, false);
});
List<ProcessingJob> jobs = new List<ProcessingJob>();
await Task.Run(() =>
{
// 加载网格
var mesh = LoadMesh(surface);
foreach (var tp in Self.ToolPositions)
{
// 1. 计算最接近的顶点
int vertId = GetClosedVertex(mesh, tp.Base); // PlanktonMesh中存储的Id
if (vertId < 0)
{
continue;
}
// 2. 最接近节点
int nodeId = _vertexToNodeMapping[vertId]; // 全局网格中的Id
FeNode node = Self.Model.Mesh.Nodes[nodeId];
// 3. 最近节点周围的面单元
List<FeFace> faces = new List<FeFace>();
foreach (var f in mesh.Vertices.GetVertexFaces(vertId))
{
if (_cellToFaceMapping.TryGetValue(f, out var face))
faces.Add(face);
}
// 4. 复制一份基础计算步并激活
var newStep = Self.GetStep(baseStep.Name).DeepClone();
var stepName = viewSteps.NewStepName;
newStep.Name = Self.GetStepNames().GetNextNumberedKey(NamedClass.GetNameWithoutLastValue(stepName));
Self.AddStep(newStep, false, false);
// 激活计算步
Self.ActivateDeactivateStep(newStep.Name, true);
// 5. 添加载荷
// 5.1 新建用于施加载荷的曲面Surface
// 新建User Surface
var userSurface = new FeSurface(Self.Model.Mesh.Surfaces.GetNextNumberedKey("UserSurface"))
{
CreatedFrom = FeSurfaceCreatedFrom.Selection,
FaceIds = faces.Select(x => x.Id).ToArray(),
// ToDo: 未来修改
Internal = false,
};
Self.AddSurface(userSurface);
// 5.2 定义载荷
bool twoD = Self.Model.Properties.ModelSpace.IsTwoD();
bool complex = newStep is SteadyStateDynamicsStep;
var loadName = newStep.Loads.GetNextNumberedKey("Load");
double area = userSurface.Area;
if (area <= 0)
area = 1.0;
double fx = -1.0 * tp.MaxFx / area;
double fy = -1.0 * tp.MaxFx / area;
double fz = -1.0 * tp.MaxFz / area;
var stLoad = new STLoad(loadName, userSurface.Name, RegionTypeEnum.SurfaceName, fx, fy, fz, twoD, complex, 0);
// 5.3 添加载荷
Self.AddLoad(newStep.Name, stLoad);
// 5.4 添加到 List<ProcessingJob> jobs
jobs.Add(new ProcessingJob(tp.Base)
{
StepName = newStep.Name,
SurfaceName = userSurface.Name,
});
}
});
Self.ProcessingJobs.Clear();
jobs.ForEach(x =>
{
Self.ProcessingJobs.Add(new ViewProcessingJob(x));
});
Self.Form.SetStateReady(@"构建切削力分析模型...");
}
catch (Exception ex)
{
ExceptionTools.Show(ex);
}
}
// 计算最接近的点
private static int GetClosedVertex(PlanktonMesh mesh, ToolPosition toolPosition)
{
int closedVertexIndex = -1;
double x1 = toolPosition.X;
double y1 = toolPosition.Y;
double z1 = toolPosition.Z;
double minimumDistance = double.MaxValue;
int id = 0;
foreach (var vertex in mesh.Vertices)
{
double x2 = vertex.X;
double y2 = vertex.Y;
double z2 = vertex.Z;
double dst = MeshTools.Distance(x1, y1, z1, x2, y2, z2);
// 如果距离小于当前最小距离,则更新最近点索引
if (dst < minimumDistance)
{
minimumDistance = dst;
closedVertexIndex = id;
}
id++;
}
return closedVertexIndex;
}
private readonly Dictionary<int, int> _nodeToVertexMapping = new Dictionary<int, int>();
private readonly Dictionary<int, int> _vertexToNodeMapping = new Dictionary<int, int>();
private readonly Dictionary<int, FeFace> _cellToFaceMapping = new Dictionary<int, FeFace>();
private PlanktonMesh LoadMesh(FeSurface surface)
{
// 计算面列表
var faceList = (from faceId in surface.FaceIds
let element = Self.Model.Mesh.Elements[faceId / 10]
let faceName = (FeFaceName)(faceId % 10 + 1)
select new FeFace(element, faceName)).ToList();
// 节点列表
var hashSet = new HashSet<int>();
faceList.ForEach(face =>
{
var ids = face.NodeIds;
hashSet.Add(ids[0]);
hashSet.Add(ids[1]);
hashSet.Add(ids[2]);
});
var mesh = new PlanktonMesh();
foreach (var nodeId in hashSet.OrderBy(x => x))
{
double x = Self.Model.Mesh.Nodes[nodeId].X;
double y = Self.Model.Mesh.Nodes[nodeId].Y;
double z = Self.Model.Mesh.Nodes[nodeId].Z;
int vertId = mesh.Vertices.Add(x, y, z);
_nodeToVertexMapping.Add(nodeId, vertId);
_vertexToNodeMapping.Add(vertId, nodeId);
}
faceList.ForEach(face =>
{
var ids = face.NodeIds;
int i = _nodeToVertexMapping[ids[0]];
int j = _nodeToVertexMapping[ids[1]];
int k = _nodeToVertexMapping[ids[2]];
int cellId = mesh.Faces.AddFace(i, j, k);
_cellToFaceMapping.Add(cellId, face);
});
return mesh;
}
}
}