fix: 部署调整(3/3)

master
Tongg 4 months ago
parent 1c61cf83e1
commit b47f1e83ae
  1. 5
      ViewModel/Grading/DiamondSelectVM.cs
  2. 144
      Views/UserControl/ViewportData/Helper/ObjExporter.cs
  3. 2
      Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs
  4. 8
      Views/UserControl/ViewportData/Helper/ViewportManager.cs

@ -171,7 +171,7 @@ public class DiamondSelectVM : BaseViewModel
} }
// 模拟耗时操作 // 模拟耗时操作
//System.Threading.Thread.Sleep(50); // 休眠50毫秒 //System.Threading.Thread.Sleep(50); // 休眠50毫秒
await Task.Delay(710); await Task.Delay(515);
loading.setValue(i); loading.setValue(i);
progress = i; progress = i;
} }
@ -537,7 +537,8 @@ public class DiamondSelectVM : BaseViewModel
{ {
//WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); //WindowManager.mainViewModel.Content = WindowManager.PreviousVM();
BaseControlVM vm = new BaseControlVM(new GradingResultVM(param), MultilingualHelper.getString("DetectionResult")); BaseControlVM vm = new BaseControlVM(new GradingResultVM(param), MultilingualHelper.getString("DetectionResult"));
vm.WindowTitle = string.IsNullOrWhiteSpace(param.DiamondCode) ? vm.WindowTitle : $"{vm.WindowTitle} - {param.DiamondCode}"; var ct = param.measurements.VOLUME / 57;
vm.WindowTitle = string.IsNullOrWhiteSpace(param.DiamondCode) ? vm.WindowTitle : $"{vm.WindowTitle} - {param.DiamondCode}({ct.ToString("F3")}ct)";
vm.ShowFunctionButton = System.Windows.Visibility.Visible; vm.ShowFunctionButton = System.Windows.Visibility.Visible;
WindowManager.mainViewModel.Content = vm; WindowManager.mainViewModel.Content = vm;
WindowManager.openContent.Add(vm); WindowManager.openContent.Add(vm);

@ -11,90 +11,118 @@ public class ObjExporter
{ {
public static void ExportToObj2(List<Viewport3DTriangleEntity> entities, string outputPath) public static void ExportToObj2(List<Viewport3DTriangleEntity> entities, string outputPath)
{ {
// 分组:按面代码 PlaneCode 分组 string obj = GenerateObj(entities);
var faceGroups = entities // Step 2: 写入 OBJ 文件
.GroupBy(e => e.PlaneCode) using (var writer = new StreamWriter(outputPath))
.ToDictionary(g => g.Key, g => g.ToList()); {
writer.Write(obj);
// 存储每个面的顶点和法线 }
var faceData = new Dictionary<string, FaceData>(); }
// Step 1: 处理每个面,生成顶点列表并计算法线 public static string GenerateObj(IEnumerable<Viewport3DTriangleEntity> triangles)
foreach (var group in faceGroups)
{ {
// 合并所有顶点并去重 var groups = triangles.GroupBy(t => t.PlaneCode);
var vertices = group.Value
.SelectMany(e => new[] { e.Point1, e.Point2, e.Point3 })
.Distinct()
.ToList();
// 按凸包算法排序顶点(避免交叉) List<Vector3> allVertices = new List<Vector3>();
var sortedVertices = ConvexHullSort(vertices); List<Vector3> allNormals = new List<Vector3>();
List<string> faceLines = new List<string>();
// 计算面的法线(基于排序后的顶点) foreach (var group in groups)
var normal = CalculateFaceNormal(sortedVertices, ViewportManager.CenterVector); {
// Step 1: 组内顶点去重
var localVertices = new Dictionary<Vector3, int>();
var groupVertices = new List<Vector3>();
// 存储面数据 foreach (var triangle in group)
faceData[group.Key] = new FaceData
{ {
Vertices = sortedVertices, AddVertex(triangle.Point1);
Normal = normal AddVertex(triangle.Point2);
}; AddVertex(triangle.Point3);
} }
// Step 2: 写入 OBJ 文件 void AddVertex(Vector3 v)
using (var writer = new StreamWriter(outputPath))
{
// 写入顶点
var vertexIndexMap = new Dictionary<Vector3, int>();
int index = 1;
foreach (var face in faceData.Values)
{
foreach (var vertex in face.Vertices)
{ {
if (!vertexIndexMap.ContainsKey(vertex)) if (!localVertices.ContainsKey(v))
{ {
vertexIndexMap[vertex] = index++; localVertices[v] = groupVertices.Count;
writer.WriteLine($"v {vertex.X} {vertex.Y} {vertex.Z}"); groupVertices.Add(v);
} }
} }
// 映射组内索引到全局索引
var vertexMap = new Dictionary<int, int>();
foreach (var v in groupVertices)
{
allVertices.Add(v);
vertexMap[localVertices[v]] = allVertices.Count; // OBJ索引从1开始
} }
// 写入法线(每个面一个法线) // Step 2: 处理法线和面
var normalIndexMap = new Dictionary<Vector3, int>(); Vector3 baseNormal = Vector3.Zero;
index = 1; bool isFirstTriangle = true;
foreach (var face in faceData.Values) int vnIndex = 0;
foreach (var triangle in group)
{ {
if (!normalIndexMap.ContainsKey(face.Normal)) Vector3 p1 = triangle.Point1;
Vector3 p2 = triangle.Point2;
Vector3 p3 = triangle.Point3;
int localI1 = localVertices[p1];
int localI2 = localVertices[p2];
int localI3 = localVertices[p3];
int globalI1 = vertexMap[localI1];
int globalI2 = vertexMap[localI2];
int globalI3 = vertexMap[localI3];
// 计算法线
Vector3 edge1 = p2 - p1;
Vector3 edge2 = p3 - p1;
Vector3 normal = Vector3.Cross(edge1, edge2);
normal.Normalize();
if (isFirstTriangle)
{ {
normalIndexMap[face.Normal] = index++; baseNormal = normal;
// writer.WriteLine($"vn {face.Normal.X} {face.Normal.Y} {face.Normal.Z}"); isFirstTriangle = false;
} allNormals.Add(baseNormal);
vnIndex = allNormals.Count;
} }
// 写入面 // 调整法线方向
foreach (var faceEntry in faceData) float dot = Vector3.Dot(normal, baseNormal);
if (dot < 0)
{ {
var face = faceEntry.Value; (globalI2, globalI3) = (globalI3, globalI2);
var normalIndex = normalIndexMap[face.Normal]; }
// 正面(顺时针) faceLines.Add($"f {globalI1}//{vnIndex} {globalI2}//{vnIndex} {globalI3}//{vnIndex}");
writer.Write("f ");
foreach (var vertex in face.Vertices)
{
writer.Write($"{vertexIndexMap[vertex]}//{normalIndex} ");
} }
writer.WriteLine(); }
// 构建OBJ内容
StringBuilder objBuilder = new StringBuilder();
// 反面(逆时针) // 顶点
writer.Write("f "); foreach (var v in allVertices)
foreach (var vertex in face.Vertices.AsEnumerable().Reverse())
{ {
writer.Write($"{vertexIndexMap[vertex]}//{normalIndex} "); objBuilder.AppendLine($"v {v.X:F6} {v.Y:F6} {v.Z:F6}");
} }
writer.WriteLine();
// 法线
foreach (var vn in allNormals)
{
objBuilder.AppendLine($"vn {vn.X:F6} {vn.Y:F6} {vn.Z:F6}");
} }
// 面
foreach (var face in faceLines)
{
objBuilder.AppendLine(face);
} }
return objBuilder.ToString();
} }
/// <summary> /// <summary>

@ -375,7 +375,7 @@ public class ViewportHelperPro
var facetPoints = VectorClockwiseSort(uniqueVectors.ToList()); var facetPoints = VectorClockwiseSort(uniqueVectors.ToList());
Vector3 center = GetCentroid(uniqueVectors.ToList()); Vector3 center = GetCentroid(uniqueVectors.ToList());
Console.WriteLine($"{yaoFace.Key} \t {center.X} \t {center.Y} \t {center.Z}"); // Console.WriteLine($"{yaoFace.Key} \t {center.X} \t {center.Y} \t {center.Z}");
List<Vector3> leftLine = new List<Vector3>(); List<Vector3> leftLine = new List<Vector3>();
List<Vector3> rightLine = new List<Vector3>(); List<Vector3> rightLine = new List<Vector3>();

@ -361,6 +361,14 @@ public class ViewportManager
//切换相机视角 //切换相机视角
_viewport.Camera = ViewportHelperPro.CalculateCamera(PositiveDirection, ModelBounds); _viewport.Camera = ViewportHelperPro.CalculateCamera(PositiveDirection, ModelBounds);
_viewport.Camera.UpDirection = new Vector3D(0, -1, 0); _viewport.Camera.UpDirection = new Vector3D(0, -1, 0);
var center = ViewportManager.ModelBounds.Center;
var maxDimension = ViewportManager.ModelBounds.Size.Length();
var distance = maxDimension * 1.2; // 调整相机到模型的距离,保证视野范围内
var camera = _viewport.Camera as HelixToolkit.Wpf.SharpDX.OrthographicCamera;
camera.Position = new Point3D(center.X, center.Y - distance, center.Z); // 从底部看,Y轴负方向
camera.UpDirection = new Vector3D(0, 0, -1);
camera.LookDirection = new Vector3D(center.X - camera.Position.X, center.Y - camera.Position.Y, center.Z - camera.Position.Z);
_viewport.RenderHost.MSAA = MSAALevel.Maximum; _viewport.RenderHost.MSAA = MSAALevel.Maximum;
// TODO: // TODO:
InitMeshLines(); InitMeshLines();

Loading…
Cancel
Save