264 lines
9.0 KiB
C#
264 lines
9.0 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;
|
|
|
|
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(@"构建切削力分析模型...");
|
|
|
|
// 1. 先把所有计算步反激活
|
|
var stepList = Self.GetAllSteps().ToList();
|
|
stepList.ForEach(x =>
|
|
{
|
|
Self.ActivateDeactivateStep(x.Name, false);
|
|
});
|
|
|
|
// 2. 加载网格
|
|
var mesh = LoadMesh(surface);
|
|
|
|
List<ProcessingJob> jobs = new List<ProcessingJob>();
|
|
|
|
await Task.Run(() =>
|
|
{
|
|
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[_vertexToNodeMapping[vertId]];
|
|
|
|
// 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);
|
|
|
|
// 6. 添加到 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);
|
|
Self.Form.SetStateReady(@"构建切削力分析模型...");
|
|
}
|
|
}
|
|
|
|
// 计算最接近的点
|
|
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;
|
|
}
|
|
}
|
|
}
|