diff --git a/Language/zh_CN.xaml b/Language/zh_CN.xaml
index 4702bef..8a69a87 100644
--- a/Language/zh_CN.xaml
+++ b/Language/zh_CN.xaml
@@ -26,6 +26,13 @@
美化Json
压缩Json
+
+ 平均
+ 圆度
+ 深度
+ 最小值
+ 最大值
+ SYM等级
是否退出程序?
是否退出
diff --git a/Model/Entity/Viewport3DTriangleEntity.cs b/Model/Entity/Viewport3DTriangleEntity.cs
new file mode 100644
index 0000000..d24c1c4
--- /dev/null
+++ b/Model/Entity/Viewport3DTriangleEntity.cs
@@ -0,0 +1,129 @@
+using System.Security.Cryptography;
+using System.Text;
+using SharpDX;
+using SparkClient.Model.Enums;
+
+namespace SparkClient.Model.Entity;
+///
+/// 三角形
+///
+public class Viewport3DTriangleEntity
+{
+ ///
+ /// 点1
+ ///
+ public Vector3 Point1 { get; set; }
+ ///
+ /// 点2
+ ///
+ public Vector3 Point2 { get; set; }
+ ///
+ /// 点3
+ ///
+ public Vector3 Point3 { get; set; }
+ ///
+ /// 三角形代码[生成]
+ /// 按顺序:p1.x,p1.y,p1.z;p2.x,p2.y,p2.z;p3.x,p3.y,p3.z 拼接后使用生成大写16位md5
+ ///
+ public String TriangleCode { get; set; }
+ ///
+ /// 面代码
+ /// 由多个三角形组成的面的代码:entity1、entity2组成了一个正方形,那么他俩的TriangleCode属性值一致
+ ///
+ public String PlaneCode { get; set; }
+ ///
+ /// 面类型
+ /// 比如这个面时钻石的腰部分,那么type统一,当面类型为err时则该面是一个异常面
+ /// 可选值:PlaneType
+ ///
+ public PlaneType PlaneType { get; set; }
+
+ public static Viewport3DTriangleEntity CreateByString(string str)
+ {
+ if (string.IsNullOrWhiteSpace(str))
+ {
+ throw new ArgumentException("Input string cannot be null or empty");
+ }
+
+ // 分割为四段
+ var parts = str.Split('|');
+ if (parts.Length != 4)
+ {
+ throw new ArgumentException("Input string format is incorrect. Expected 4 parts separated by '|'.");
+ }
+
+ // 解析第一段:坐标
+ var coordinates = parts[0].Split(';');
+ if (coordinates.Length != 3)
+ {
+ throw new ArgumentException("Coordinates part must contain exactly 3 points separated by ';'.");
+ }
+
+ var points = coordinates.Select(ParseVector3).ToArray();
+
+ // 解析第二段:TriangleCode [内部标记]
+
+ // 解析第三段:PlaneCode
+ string planeCode = parts[2];
+ if (string.IsNullOrWhiteSpace(planeCode))
+ {
+ throw new ArgumentException("PlaneCode cannot be null or empty");
+ }
+
+ // 解析第四段:PlaneType
+ if (!int.TryParse(parts[3], out int planeTypeValue) || !Enum.IsDefined(typeof(PlaneType), planeTypeValue))
+ {
+ throw new ArgumentException("Invalid PlaneType value");
+ }
+ PlaneType planeType = (PlaneType)planeTypeValue;
+
+ // 生成 TriangleCode 格式:p1.x,p1.y,p1.z;p2.x,p2.y,p2.z;p3.x,p3.y,p3.z 生成 MD5
+ string concatenatedPoints = string.Join(";", points.Select(p => $"{p.X},{p.Y},{p.Z}"));
+ string generatedTriangleCode = GenerateMD5Hash(concatenatedPoints);
+
+ return new Viewport3DTriangleEntity
+ {
+ Point1 = points[0],
+ Point2 = points[1],
+ Point3 = points[2],
+ TriangleCode = generatedTriangleCode,
+ PlaneCode = planeCode,
+ PlaneType = planeType
+ };
+ }
+
+ // public static Viewport3DTriangleEntity CreateByJsonStr(string str)
+ // {
+ //
+ // }
+
+ private static Vector3 ParseVector3(string coordinate)
+ {
+ var values = coordinate.Split(',');
+ if (values.Length != 3)
+ {
+ throw new ArgumentException("Each coordinate must contain exactly 3 values separated by ','");
+ }
+
+ if (!float.TryParse(values[0], out float x) ||
+ !float.TryParse(values[1], out float y) ||
+ !float.TryParse(values[2], out float z))
+ {
+ throw new ArgumentException("Coordinate values must be valid floating-point numbers");
+ }
+
+ return new Vector3(x, y, z);
+ }
+
+ public static string GenerateMD5Hash(string input)
+ {
+ using (var md5 = MD5.Create())
+ {
+ var inputBytes = Encoding.UTF8.GetBytes(input);
+ var hashBytes = md5.ComputeHash(inputBytes);
+
+ // 转换为大写的16位十六进制字符串
+ return string.Concat(hashBytes.Take(8).Select(b => b.ToString("X2")));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Model/Enums/PlaneType.cs b/Model/Enums/PlaneType.cs
new file mode 100644
index 0000000..5468d79
--- /dev/null
+++ b/Model/Enums/PlaneType.cs
@@ -0,0 +1,31 @@
+using System.ComponentModel;
+
+namespace SparkClient.Model.Enums;
+
+public enum PlaneType
+{
+ [Description("瑕疵面")]
+ Error = -1,
+ [Description("腰")]
+ Girdle = 0,
+ [Description("冠部")]
+ Crown = 1,
+ [Description("亭部")]
+ Pavilion = 2,
+ [Description("台面")]
+ TableFacet = 11,
+ [Description("冠部主刻面(风筝面)")]
+ UpperMainFacet = 12,
+ [Description("星刻面")]
+ StarFacet = 13,
+ [Description("上腰面")]
+ UpperGirdleFacet = 14,
+ [Description("亭部主刻面")]
+ PavilionMainFacet = 21,
+ [Description("下腰面")]
+ LowerGirdleFact = 22,
+ [Description("底尖(或底小面)")]
+ Culet = 23,
+ [Description("其他")]
+ Other = 99
+}
\ No newline at end of file
diff --git a/Model/Helper/Viewport3DHelper.cs b/Model/Helper/Viewport3DHelper.cs
new file mode 100644
index 0000000..65399e7
--- /dev/null
+++ b/Model/Helper/Viewport3DHelper.cs
@@ -0,0 +1,825 @@
+using System.IO;
+using System.Windows.Media;
+using System.Windows.Media.Media3D;
+using SharpDX.Direct3D11;
+using SparkClient.Model.Entity;
+
+namespace SparkClient.Model.Helper;
+
+using HelixToolkit.Wpf.SharpDX;
+using SharpDX;
+using System.Collections.Generic;
+
+public class Viewport3DHelper
+{
+ // 加载环境贴图
+ // public static Stream stream =
+ // File.Open("D:\\WorkSpace\\spark\\HelixToolkitSharpDX-Demo\\morning_racing_circuit_16k.dds", FileMode.Open);
+
+ ///
+ /// 生成一个多边形钻石
+ ///
+ /// 控件
+ /// 边数
+ public static void GenerateDiamond(Viewport3DX viewport, int sides)
+ {
+ // 启用法线生成
+ var meshBuilder = new MeshBuilder(true, false);
+
+ //设置抗锯齿
+ viewport.RenderHost.MSAA = MSAALevel.Maximum;
+
+
+ double radius = 3.2915;
+ double smallRadius = radius / 2;
+ double topHeight = 1.67;
+ double bottomHeight = 4.43;
+ double smallOffset = 1.25;
+
+ var largeVertices = new List();
+ var smallVertices = new List();
+
+ var edgeLines = new List>();
+
+ // 生成大八边形顶点
+ for (int i = 0; i < sides; i++)
+ {
+ double angle = i * Math.PI / (sides / 2);
+ largeVertices.Add(new Vector3((float)(radius * Math.Cos(angle)), (float)topHeight,
+ (float)(radius * Math.Sin(angle))));
+ }
+
+ // 生成小八边形顶点
+ for (int i = 0; i < sides; i++)
+ {
+ double angle = i * Math.PI / (sides / 2);
+ smallVertices.Add(new Vector3((float)(smallRadius * Math.Cos(angle)), (float)(topHeight + smallOffset),
+ (float)(smallRadius * Math.Sin(angle))));
+ }
+
+ var bottomPoint = new Vector3(0, (float)(topHeight - bottomHeight), 0);
+ var topPoint = new Vector3(0, (float)topHeight, 0);
+
+ // 生成底部面
+ for (int i = 0; i < sides; i++)
+ {
+ int nextIndex = (i + 1) % sides;
+
+ // 计算法线
+ // Vector3 edge1 = largeVertices[nextIndex] - bottomPoint;
+ // Vector3 edge2 = largeVertices[i] - bottomPoint;
+ // Vector3 normal = Vector3.Cross(edge1, edge2);
+ // normal.Normalize();
+
+
+ List fanPositions2 = new List()
+ { bottomPoint, largeVertices[nextIndex], largeVertices[i] };
+ List fanNormals2 = new List()
+ { new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0) };
+ meshBuilder.AddTriangleFan(fanPositions2, fanNormals2);
+ // meshBuilder.AddTriangle(bottomPoint, largeVertices[nextIndex], largeVertices[i]);
+ // meshBuilder.AddTriangle(topPoint, largeVertices[i], largeVertices[nextIndex]);
+
+
+ // 添加边框线
+ edgeLines.Add(new Tuple(bottomPoint, largeVertices[nextIndex]));
+ edgeLines.Add(new Tuple(largeVertices[nextIndex], largeVertices[i]));
+ edgeLines.Add(new Tuple(largeVertices[i], bottomPoint));
+ }
+
+ // 生成法线并添加小八边形的面
+ var smallNormals = new List();
+ for (int i = 0; i < smallVertices.Count; i++)
+ {
+ smallNormals.Add(new Vector3(0, 1, 0)); // 小八边形法线向上
+ }
+
+ meshBuilder.AddTriangleFan(smallVertices, smallNormals);
+
+ // 生成大八边形和小八边形的连接面
+ for (int i = 0; i < sides; i++)
+ {
+ int nextIndex = (i + 1) % sides;
+
+
+ // 计算法线
+ // Vector3 edge1 = largeVertices[nextIndex] - largeVertices[i];
+ // Vector3 edge2 = smallVertices[nextIndex] - largeVertices[i];
+ // Vector3 normal1 = Vector3.Cross(edge1, edge2);
+ // normal1.Normalize();
+ //
+ // Vector3 edge3 = smallVertices[nextIndex] - largeVertices[i];
+ // Vector3 edge4 = smallVertices[i] - largeVertices[i];
+ // Vector3 normal2 = Vector3.Cross(edge3, edge4);
+ // normal2.Normalize();
+
+
+ List fanPositions1 = new List()
+ { largeVertices[i], largeVertices[nextIndex], smallVertices[nextIndex] };
+ List fanNormals1 = new List()
+ { new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0) };
+ meshBuilder.AddTriangleFan(fanPositions1, fanNormals1);
+
+ //meshBuilder.AddTriangle(largeVertices[i], largeVertices[nextIndex], smallVertices[nextIndex]);
+
+ List fanPositions2 = new List()
+ { largeVertices[i], smallVertices[nextIndex], smallVertices[i] };
+ List fanNormals2 = new List()
+ { new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0) };
+ meshBuilder.AddTriangleFan(fanPositions2, fanNormals2);
+ //meshBuilder.AddTriangle(largeVertices[i], smallVertices[nextIndex], smallVertices[i]);
+
+ // 添加边框线
+ edgeLines.Add(new Tuple(largeVertices[i], largeVertices[nextIndex]));
+ edgeLines.Add(new Tuple(largeVertices[nextIndex], smallVertices[nextIndex]));
+ edgeLines.Add(new Tuple(smallVertices[nextIndex], smallVertices[i]));
+ edgeLines.Add(new Tuple(smallVertices[i], largeVertices[i]));
+ }
+
+ var mesh = meshBuilder.ToMeshGeometry3D();
+
+
+ var material = new PBRMaterial
+ {
+ AlbedoColor = new Color4(0.11f, 0.56f, 1f, 0.6f), // 纯白色
+ MetallicFactor = 0.0,
+ RoughnessFactor = 0.01,
+ ReflectanceFactor = 1.0,
+ ClearCoatStrength = 1.0,
+ ClearCoatRoughness = 0.0,
+ // RenderEnvironmentMap = true,
+ // IrradianceMap = TextureModel.Create(stream), // 环境贴图
+ };
+
+ // 设置材质的采样器状态
+ material.SurfaceMapSampler = new SamplerStateDescription
+ {
+ Filter = Filter.MinMagMipLinear,
+ AddressU = TextureAddressMode.Wrap,
+ AddressV = TextureAddressMode.Wrap,
+ AddressW = TextureAddressMode.Wrap
+ };
+
+ //边框
+ var lineBuilder = new LineBuilder();
+ foreach (var line in edgeLines)
+ {
+ lineBuilder.AddLine(line.Item1, line.Item2);
+ }
+
+ var edgeLinesModel = new LineGeometryModel3D
+ {
+ Geometry = lineBuilder.ToLineGeometry3D(),
+ Color = System.Windows.Media.Colors.Black,
+ Thickness = 1.0
+ };
+
+ viewport.Items.Add(edgeLinesModel);
+
+ var geometryModel = new MeshGeometryModel3D
+ {
+ Geometry = mesh,
+ Material = material
+ };
+
+ viewport.Items.Add(geometryModel);
+
+ viewport.ZoomExtents();
+ }
+
+ public static void GenerateModelByEntity(Viewport3DX viewport, List entities)
+ {
+ var meshBuilder = new MeshBuilder(true, false);
+ viewport.RenderHost.MSAA = MSAALevel.Maximum;
+ foreach (var entity in entities)
+ {
+ List vertices = new List(){entity.Point1, entity.Point2, entity.Point3};
+ meshBuilder.AddPolygon(vertices);
+ }
+
+ var mesh = meshBuilder.ToMeshGeometry3D();
+ var material = new PBRMaterial
+ {
+ AlbedoColor = new Color4(0.11f, 0.56f, 1f, 0.6f),
+ MetallicFactor = 0.0,
+ RoughnessFactor = 0.01,
+ ReflectanceFactor = 1.0,
+ ClearCoatStrength = 1.0,
+ ClearCoatRoughness = 0.0,
+ };
+
+ // 设置材质的采样器状态
+ material.SurfaceMapSampler = new SamplerStateDescription
+ {
+ Filter = Filter.MinMagMipLinear,
+ AddressU = TextureAddressMode.Wrap,
+ AddressV = TextureAddressMode.Wrap,
+ AddressW = TextureAddressMode.Wrap
+ };
+ var geometryModel = new MeshGeometryModel3D
+ {
+ Geometry = mesh,
+ Material = material
+ };
+ viewport.Items.Add(geometryModel);
+ }
+
+ ///
+ /// 传入一个三角形,找到关联面
+ ///
+ /// 控件
+ /// 三角形顶点
+ /// 选择主体颜色
+ /// 选择关联颜色(null不渲染)
+ /// 选择边框颜色(null不渲染)
+ ///
+ public static List HighlightAssociatedFaces(Viewport3DX viewport,
+ Tuple triangleIndex, Color4 selColor, Color4? linkColor = null,
+ Color4? borderColor = null)
+ {
+ List result = new List();
+ //选中平面上的点(实现选中高亮、边框线)
+ List selFaceVector = new List();
+ selFaceVector.Add(triangleIndex.Item1);
+ selFaceVector.Add(triangleIndex.Item2);
+ selFaceVector.Add(triangleIndex.Item3);
+
+ foreach (var item in viewport.Items)
+ {
+ if (item is MeshGeometryModel3D geometryModel)
+ {
+ var geometry = geometryModel.Geometry;
+ if (geometry != null)
+ {
+ var positions = geometry.Positions; // 顶点列表
+ var indices = geometry.Indices; // 索引列表
+
+ // 确保 Indices 是三角形格式
+ for (int i = 0; i < indices.Count; i += 3)
+ {
+ // 获取三角形的三个顶点索引
+ int index0 = indices[i];
+ int index1 = indices[i + 1];
+ int index2 = indices[i + 2];
+
+ // 获取三角形的三个顶点坐标
+ var vertex0 = positions[index0];
+ var vertex1 = positions[index1];
+ var vertex2 = positions[index2];
+
+ List temp = new List() { vertex0, vertex1, vertex2 };
+
+ if (ArePointsOnSamePlane(triangleIndex, temp))
+ {
+ //所有点共面,两种情况,三角形自己,三角形相连在同一个平面
+ if (temp.Count == 3 && temp.Contains(triangleIndex.Item1) &&
+ temp.Contains(triangleIndex.Item2) && temp.Contains(triangleIndex.Item3))
+ continue;
+ foreach (var vector in temp)
+ {
+ // if(!selFaceVector.Contains(vector))
+ selFaceVector.Add(vector);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ //当前选中的平面
+ var meshBuilder = new MeshBuilder(true, false);
+ List fanNormals2 = new List();
+ foreach (var vertex in selFaceVector)
+ fanNormals2.Add(new Vector3(0, 1, 0));
+ meshBuilder.AddTriangleFan(selFaceVector, fanNormals2);
+ var mesh = meshBuilder.ToMeshGeometry3D();
+
+ var material = new PBRMaterial
+ {
+ AlbedoColor = selColor, // 纯白色
+ MetallicFactor = 0,
+ RoughnessFactor = 1,
+ ReflectanceFactor = 0.5,
+ };
+ var geometryModel1 = new MeshGeometryModel3D
+ {
+ Geometry = mesh,
+ Material = material
+ };
+
+ //当前选中平面边框线
+ var edgeLines = new List>();
+ var lengths = new List(); // 长度列表
+ var angles = new List(); // 夹角列表
+ HashSet uniqueVectors = new HashSet(selFaceVector);
+ List sortedVectors = uniqueVectors.ToList();
+ Vector3 center = GetCentroid(sortedVectors);
+ // 按极角顺时针排序
+ sortedVectors.Sort((v1, v2) =>
+ {
+ double angle1 = Math.Atan2(v1.Z - center.Z, v1.X - center.X); // 计算第一个点的角度
+ double angle2 = Math.Atan2(v2.Z - center.Z, v2.X - center.X); // 计算第二个点的角度
+ return angle1.CompareTo(angle2); // 按角度从小到大排序
+ });
+
+ for (int i = 0; i < sortedVectors.Count - 1; i++)
+ {
+ var nowItem = sortedVectors[i];
+ var nextItem = sortedVectors[i + 1];
+ edgeLines.Add(new Tuple(nowItem, nextItem));
+ // 计算当前线段的长度
+ lengths.Add((nextItem - nowItem).Length());
+ }
+
+ edgeLines.Add(new Tuple(sortedVectors.Last(), sortedVectors.First()));
+ lengths.Add((sortedVectors.Last() - sortedVectors.First()).Length());
+ //计算夹角
+ for (int i = 0; i < sortedVectors.Count; i++)
+ {
+ int prevIndex = (i - 1 + sortedVectors.Count) % sortedVectors.Count;
+ int nextIndex = (i + 1) % sortedVectors.Count;
+
+ // 获取三点
+ var p1 = sortedVectors[prevIndex];
+ var p2 = sortedVectors[i];
+ var p3 = sortedVectors[nextIndex];
+
+ // 计算夹角
+ var v1 = p2 - p1;
+ var v2 = p3 - p2;
+ double angle = AngleBetween(v1, v2);
+ angles.Add(angle); // 夹角,单位是度
+ }
+
+ if (sortedVectors.Count == lengths.Count && sortedVectors.Count == angles.Count)
+ {
+ for (int i = 0; i < sortedVectors.Count; i++)
+ {
+ var point = sortedVectors[i];
+ var pointNext = i + 1 >= sortedVectors.Count ? sortedVectors.First() : sortedVectors[i + 1];
+ var lengthText = $"L: {lengths[i]:F2}";
+ var angleText = $"Angle: {angles[i]:F2}°";
+
+ var lengthTextPoint = (pointNext + point) / 2;
+
+ // 在合适位置显示文本
+ var text3DL = DisplayText3D(lengthText,
+ new Vector3(lengthTextPoint.X, lengthTextPoint.Y + 0.5f, lengthTextPoint.Z));
+ var text3DA = DisplayText3D(angleText, new Vector3(point.X, point.Y + 0.5f, point.Z + 0.5f));
+ viewport.Items.Add(text3DL);
+ viewport.Items.Add(text3DA);
+ result.Add(text3DL);
+ result.Add(text3DA);
+ }
+ }
+ else
+ {
+ // 如果列表长度不一致,给出提示信息
+ Console.WriteLine("The lengths or angles list size does not match the sorted vectors list.");
+ }
+
+ var lineBuilder = new LineBuilder();
+ foreach (var line in edgeLines)
+ {
+ lineBuilder.AddLine(line.Item1, line.Item2);
+ }
+
+ var edgeLinesModel = new LineGeometryModel3D
+ {
+ Geometry = lineBuilder.ToLineGeometry3D(),
+ Color = System.Windows.Media.Colors.Red,
+ Thickness = 1.0
+ };
+
+ viewport.Items.Add(edgeLinesModel);
+ viewport.Items.Add(geometryModel1);
+
+
+ result.Add(geometryModel1);
+ result.Add(edgeLinesModel);
+ return result;
+ }
+
+ ///
+ /// 遍历视图中的所有三角形
+ ///
+ ///
+ ///
+ public static List> ForeachViewPortTriangle(Viewport3DX viewport)
+ {
+ List> result = new List>();
+ foreach (var item in viewport.Items)
+ {
+ if (item is MeshGeometryModel3D geometryModel)
+ {
+ var geometry = geometryModel.Geometry;
+ if (geometry != null)
+ {
+ var positions = geometry.Positions; // 顶点列表
+ var indices = geometry.Indices; // 索引列表
+
+ // 确保 Indices 是三角形格式
+ for (int i = 0; i < indices.Count; i += 3)
+ {
+ // 获取三角形的三个顶点索引
+ int index0 = indices[i];
+ int index1 = indices[i + 1];
+ int index2 = indices[i + 2];
+
+ // 获取三角形的三个顶点坐标
+ var vertex0 = positions[index0];
+ var vertex1 = positions[index1];
+ var vertex2 = positions[index2];
+ result.Add(new Tuple(vertex0, vertex1, vertex2));
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private static BillboardTextModel3D DisplayText3D(string text, Vector3 position)
+ {
+ var billboardTextModel = new BillboardTextModel3D();
+ var billboardText = new BillboardText3D();
+ billboardText.TextInfo.Add(new TextInfo(text, position)
+ {
+ Foreground = Color.Green,
+ Scale = 0.5f,
+ });
+ billboardTextModel.Geometry = billboardText;
+ return billboardTextModel;
+ }
+
+ public static float AngleBetween(Vector3 v1, Vector3 v2)
+ {
+ // 计算两个向量的点积
+ float dotProduct = Vector3.Dot(v1, v2);
+
+ // 计算每个向量的模长
+ float magnitudeV1 = v1.Length();
+ float magnitudeV2 = v2.Length();
+
+ // 防止除以零错误
+ if (magnitudeV1 == 0 || magnitudeV2 == 0)
+ {
+ return 0f;
+ }
+
+ // 计算夹角的余弦值
+ float cosTheta = dotProduct / (magnitudeV1 * magnitudeV2);
+
+ // 限制cosTheta的值范围在 -1 到 1 之间,以防计算机浮点误差
+ cosTheta = Math.Max(-1f, Math.Min(1f, cosTheta));
+
+ // 返回角度,单位是度
+ return (float)(Math.Acos(cosTheta) * (180.0 / Math.PI));
+ }
+
+ // 计算点集合的中心点(几何质心)
+ private static Vector3 GetCentroid(List vectors)
+ {
+ float x = vectors.Sum(v => v.X) / vectors.Count;
+ float y = vectors.Sum(v => v.Y) / vectors.Count;
+ float z = vectors.Sum(v => v.Z) / vectors.Count;
+ return new Vector3(x, y, z);
+ }
+
+ ///
+ /// 判断集合元素是狗共面
+ ///
+ ///
+ ///
+ ///
+ public static bool ArePointsOnSamePlane(Tuple triangle, List points)
+ {
+ // 获取三角形的三个点
+ var P1 = triangle.Item1;
+ var P2 = triangle.Item2;
+ var P3 = triangle.Item3;
+
+ // 计算平面的法线
+ Vector3 V1 = P2 - P1; // 向量P1P2
+ Vector3 V2 = P3 - P1; // 向量P1P3
+ Vector3 normal = Vector3.Cross(V1, V2); // 叉积得到平面法线
+
+ // 对每个点进行检查
+ foreach (var point in points)
+ {
+ if (!IsPointInPlane(P1, normal, point))
+ {
+ return false; // 如果有点不在平面上,返回false
+ }
+ }
+
+ return true; // 如果所有点都在平面上,返回true
+ }
+
+ ///
+ /// 判断点是否在平面上
+ ///
+ ///
+ private static bool IsPointInPlane(Vector3 planePoint, Vector3 normal, Vector3 point)
+ {
+ // 计算点到平面的距离
+ // 点到平面的距离公式:d = (point - planePoint) · normal / |normal|
+ float distance = Vector3.Dot(point - planePoint, normal) / normal.Length();
+
+ // 如果距离为0,说明点在平面上
+ return Math.Abs(distance) < 1e-6; // 容忍一个小的误差
+ }
+
+ public static void GenerateLightingForModel(Viewport3DX viewport)
+ {
+ // 移除现有的灯光
+ List lights = new List();
+ foreach (var item in viewport.Items)
+ {
+ if (item is Light3D)
+ {
+ lights.Add(item as Light3D);
+ }
+ }
+ lights.ForEach(item => viewport.Items.Remove(item));
+
+ // 获取场景中最大的模型
+ var models = viewport.Items.OfType();
+ if (!models.Any()) return;
+
+ var largestModel = models
+ .OrderByDescending(m => GetBoundingBoxVolume(m.Geometry.Bound))
+ .FirstOrDefault();
+
+ if (largestModel == null) return;
+
+ // 获取最大模型的边界立方体
+ var boundingBox = largestModel.Geometry.Bound;
+ var size = boundingBox.Size;
+ var center = boundingBox.Center;
+
+ // 计算 Bounding Box 的八个顶点
+ var corners = new List
+ {
+ boundingBox.Minimum.ToPoint3D(), // 左下后
+ new Point3D(boundingBox.Maximum.X, boundingBox.Minimum.Y, boundingBox.Minimum.Z), // 右下后
+ new Point3D(boundingBox.Minimum.X, boundingBox.Maximum.Y, boundingBox.Minimum.Z), // 左上后
+ new Point3D(boundingBox.Minimum.X, boundingBox.Minimum.Y, boundingBox.Maximum.Z), // 左下前
+ boundingBox.Maximum.ToPoint3D(), // 右上前
+ new Point3D(boundingBox.Maximum.X, boundingBox.Maximum.Y, boundingBox.Minimum.Z), // 右上后
+ new Point3D(boundingBox.Minimum.X, boundingBox.Maximum.Y, boundingBox.Maximum.Z), // 左上前
+ new Point3D(boundingBox.Maximum.X, boundingBox.Minimum.Y, boundingBox.Maximum.Z) // 右下前
+ };
+
+ // 在每个顶点处添加光源
+ for (int i = 0; i < corners.Count; i++)
+ {
+ var corner = corners[i];
+
+ // 设置点光源的颜色和强度,使得八个点的光源具有不同效果
+ var color = i % 2 == 0 ? Colors.LightGoldenrodYellow : Colors.LightSkyBlue;
+
+ // 添加点光源
+ var pointLight = new PointLight3D
+ {
+ Position = corner,
+ Color = color,
+ Range = (float)size.Length() * 4 // 光照范围覆盖整个模型
+ };
+
+ viewport.Items.Add(pointLight);
+ }
+
+ // 添加顶部的多处光源(从上向下照射,模拟太阳光)
+ double topLightDistance = size.Y * 1.2; // 适当调整顶部光源的高度
+ var topLightPositions = new List
+ {
+ new Point3D(center.X, boundingBox.Maximum.Y + topLightDistance, center.Z),
+ new Point3D(boundingBox.Minimum.X - size.X / 3, boundingBox.Maximum.Y + topLightDistance, center.Z),
+ new Point3D(boundingBox.Maximum.X + size.X / 3, boundingBox.Maximum.Y + topLightDistance, center.Z)
+ };
+
+ foreach (var position in topLightPositions)
+ {
+ var topLight = new PointLight3D
+ {
+ Position = position,
+ Color = Colors.LightGoldenrodYellow,
+ Range = (float)size.Length() * 0.5, // 增加光的照射范围
+ Attenuation = new Vector3D(1, 0.1f, 0.05f) // 控制光的衰减,使光在距离内更有效
+ };
+ viewport.Items.Add(topLight);
+ }
+ // 添加环境光以柔化整体效果并增加亮度
+ var ambientLight = new AmbientLight3D
+ {
+ Color = Colors.LightGray
+ };
+ viewport.Items.Add(ambientLight);
+
+
+ var ambientLigh1t = new AmbientLight3D
+ {
+ Color = Colors.Gray // 设置环境光颜色
+ };
+ viewport.Items.Add(ambientLigh1t);
+
+
+ // 添加环境光以柔化整体效果并增加亮度
+ // var ambientLight = new AmbientLight3D
+ // {
+ // Color = Colors.LightGray
+ // };
+ // viewport.Items.Add(ambientLight);
+ // 添加底部的光源(从底部中心向上照射)
+ // var bottomLightPosition = new Point3D(center.X, boundingBox.Minimum.Y - 1.0f, center.Z); // 位于底部中心点下方
+ // var bottomLight = new PointLight3D
+ // {
+ // Position = bottomLightPosition,
+ // Color = Colors.White, // 白色光源
+ // Range = (float)size.Length() * 2 // 设置光照范围
+ // };
+ // viewport.Items.Add(bottomLight);
+ }
+
+ // 辅助方法:获取边界体积
+ private static double GetBoundingBoxVolume(BoundingBox bound)
+ {
+ var size = bound.Size;
+ return size.X * size.Y * size.Z;
+ }
+
+ public static List InitDemo(Viewport3DX viewport)
+ {
+ List entities = new List();
+ try
+ {
+ using (FileStream fileStream = new FileStream(AppDomain.CurrentDomain.BaseDirectory + @"Resource\DimDemo.txt", FileMode.Open, FileAccess.Read))
+ using (StreamReader reader = new StreamReader(fileStream))
+ {
+ string line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ if(string.IsNullOrWhiteSpace(line))continue;
+ if(line.StartsWith("-- "))continue;
+ entities.Add(Viewport3DTriangleEntity.CreateByString(line));
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"读取文件时出错:{ex.Message}");
+ }
+ GenerateModelByEntity(viewport, entities);
+ GenerateLightingForModel(viewport);
+
+ return entities;
+ }
+
+ public static List GenerateEmissiveModelByEntity(Viewport3DX viewport, List entities, Color4 emissiveColor)
+ {
+ // 创建 MeshBuilder,启用法线生成
+ var meshBuilder = new MeshBuilder(true, false);
+ viewport.RenderHost.MSAA = MSAALevel.Maximum;
+
+ // 通过实体构建三角形面
+ foreach (var entity in entities)
+ {
+ List vertices = new List() { entity.Point1, entity.Point2, entity.Point3 };
+ meshBuilder.AddPolygon(vertices);
+ }
+
+ // 生成网格
+ var mesh = meshBuilder.ToMeshGeometry3D();
+
+ // 创建自发光材质
+ var material = new PBRMaterial
+ {
+ AlbedoColor = new Color4(0, 0, 0, 1.0f), // 黑色,避免其他光照影响
+ EmissiveColor = emissiveColor, // 自发光颜色
+ MetallicFactor = 0.0, // 非金属
+ RoughnessFactor = 1.0, // 高粗糙度,避免反射效果
+ ReflectanceFactor = 0.0, // 无反射
+ ClearCoatStrength = 0.0, // 无清漆效果
+ ClearCoatRoughness = 1.0, // 高粗糙度
+ };
+
+ // 设置材质的采样器状态
+ material.SurfaceMapSampler = new SamplerStateDescription
+ {
+ Filter = Filter.MinMagMipLinear,
+ AddressU = TextureAddressMode.Wrap,
+ AddressV = TextureAddressMode.Wrap,
+ AddressW = TextureAddressMode.Wrap
+ };
+
+ // 创建几何模型
+ var geometryModel = new MeshGeometryModel3D
+ {
+ Geometry = mesh,
+ Material = material
+ };
+
+ // 将几何模型添加到视图中
+ viewport.Items.Add(geometryModel);
+ List result = new List();
+ result.Add(geometryModel);
+ return result;
+ }
+
+ public static List GenerateLineTextModelByEntity(Viewport3DX viewport, List entities)
+ {
+ List result = new List();
+ List selFaceVector = new List();
+ foreach (var entity in entities)
+ {
+ selFaceVector.Add(entity.Point1);
+ selFaceVector.Add(entity.Point2);
+ selFaceVector.Add(entity.Point3);
+ }
+ var edgeLines = new List>();
+ var lengths = new List(); // 长度列表
+ var angles = new List(); // 夹角列表
+ HashSet uniqueVectors = new HashSet(selFaceVector);
+ List sortedVectors = uniqueVectors.ToList();
+ Vector3 center = GetCentroid(sortedVectors);
+ sortedVectors.Sort((v1, v2) =>
+ {
+ double angle1 = Math.Atan2(v1.Z - center.Z, v1.X - center.X); // 计算第一个点的角度
+ double angle2 = Math.Atan2(v2.Z - center.Z, v2.X - center.X); // 计算第二个点的角度
+ return angle1.CompareTo(angle2); // 按角度从小到大排序
+ });
+ for (int i = 0; i < sortedVectors.Count - 1; i++)
+ {
+ var nowItem = sortedVectors[i];
+ var nextItem = sortedVectors[i + 1];
+ edgeLines.Add(new Tuple(nowItem, nextItem));
+ // 计算当前线段的长度
+ lengths.Add((nextItem - nowItem).Length());
+ }
+ edgeLines.Add(new Tuple(sortedVectors.Last(), sortedVectors.First()));
+ lengths.Add((sortedVectors.Last() - sortedVectors.First()).Length());
+ //计算夹角
+ for (int i = 0; i < sortedVectors.Count; i++)
+ {
+ int prevIndex = (i - 1 + sortedVectors.Count) % sortedVectors.Count;
+ int nextIndex = (i + 1) % sortedVectors.Count;
+
+ // 获取三点
+ var p1 = sortedVectors[prevIndex];
+ var p2 = sortedVectors[i];
+ var p3 = sortedVectors[nextIndex];
+
+ // 计算夹角
+ var v1 = p2 - p1;
+ var v2 = p3 - p2;
+ double angle = AngleBetween(v1, v2);
+ angles.Add(angle); // 夹角,单位是度
+ }
+ if (sortedVectors.Count == lengths.Count && sortedVectors.Count == angles.Count)
+ {
+ for (int i = 0; i < sortedVectors.Count; i++)
+ {
+ var point = sortedVectors[i];
+ var pointNext = i + 1 >= sortedVectors.Count ? sortedVectors.First() : sortedVectors[i + 1];
+ var lengthText = $"L: {lengths[i]:F2}";
+ var angleText = $"Angle: {angles[i]:F2}°";
+
+ var lengthTextPoint = (pointNext + point) / 2;
+
+ // 在合适位置显示文本
+ var text3DL = DisplayText3D(lengthText,
+ new Vector3(lengthTextPoint.X, lengthTextPoint.Y + 0.5f, lengthTextPoint.Z));
+ var text3DA = DisplayText3D(angleText, new Vector3(point.X, point.Y + 0.5f, point.Z + 0.5f));
+ viewport.Items.Add(text3DL);
+ viewport.Items.Add(text3DA);
+ result.Add(text3DL);
+ result.Add(text3DA);
+ }
+ }
+ else
+ {
+ // 如果列表长度不一致,给出提示信息
+ Console.WriteLine("The lengths or angles list size does not match the sorted vectors list.");
+ }
+ var lineBuilder = new LineBuilder();
+ foreach (var line in edgeLines)
+ {
+ lineBuilder.AddLine(line.Item1, line.Item2);
+ }
+
+ var edgeLinesModel = new LineGeometryModel3D
+ {
+ Geometry = lineBuilder.ToLineGeometry3D(),
+ Color = System.Windows.Media.Colors.Red,
+ Thickness = 1.0
+ };
+
+ viewport.Items.Add(edgeLinesModel);
+ result.Add(edgeLinesModel);
+ return result;
+ }
+
+
+}
\ No newline at end of file
diff --git a/Resource/DimDemo.txt b/Resource/DimDemo.txt
new file mode 100644
index 0000000..26d79af
--- /dev/null
+++ b/Resource/DimDemo.txt
@@ -0,0 +1,310 @@
+-- 腰
+-39.660,46.816,-30.448;-43.304,46.817,-24.996;-39.662,48.374,-30.446|0|7dbb404af789839a701aebd8b3b603e1|0
+-48.293,46.816,-12.953;-46.194,49.000,-19.134;-46.194,46.000,-19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+-30.446,48.374,-39.662;-30.442,46.817,-39.665;-35.355,46.000,-35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+19.134,49.000,-46.194;24.992,48.374,-43.306;19.134,46.000,-46.194|0|7dbb404af789839a701aebd8b3b603e1|0
+35.355,49.000,-35.355;35.355,46.000,-35.355;30.448,46.816,-39.660|0|7dbb404af789839a701aebd8b3b603e1|0
+35.355,49.000,-35.355;39.662,48.374,-30.446;35.355,46.000,-35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+30.446,48.374,-39.662;30.448,46.816,-39.660;24.996,46.817,-43.304|0|7dbb404af789839a701aebd8b3b603e1|0
+-12.946,46.817,-48.295;-19.134,46.000,-46.194;-12.950,48.374,-48.294|0|7dbb404af789839a701aebd8b3b603e1|0
+39.665,46.817,-30.442;43.306,48.374,-24.992;43.307,46.816,-24.989|0|7dbb404af789839a701aebd8b3b603e1|0
+48.294,48.374,-12.950;46.194,46.000,-19.134;46.194,49.000,-19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+6.521,46.817,-49.573;-0.000,46.000,-50.000;6.517,48.374,-49.573|0|7dbb404af789839a701aebd8b3b603e1|0
+48.295,46.817,-12.946;49.573,48.374,-6.517;49.574,46.816,-6.513|0|7dbb404af789839a701aebd8b3b603e1|0
+43.307,46.816,-24.989;46.194,49.000,-19.134;46.194,46.000,-19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+24.996,46.817,-43.304;19.134,46.000,-46.194;24.992,48.374,-43.306|0|7dbb404af789839a701aebd8b3b603e1|0
+50.000,46.000,-0.000;49.574,46.816,-6.513;50.000,49.000,0.000|0|7dbb404af789839a701aebd8b3b603e1|0
+48.294,48.374,12.950;48.293,46.816,12.953;49.573,46.817,6.521|0|7dbb404af789839a701aebd8b3b603e1|0
+39.665,46.817,-30.442;35.355,46.000,-35.355;39.662,48.374,-30.446|0|7dbb404af789839a701aebd8b3b603e1|0
+46.194,46.000,19.134;48.293,46.816,12.953;46.194,49.000,19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+50.000,49.000,0.000;49.573,48.374,6.517;50.000,46.000,-0.000|0|7dbb404af789839a701aebd8b3b603e1|0
+48.295,46.817,-12.946;46.194,46.000,-19.134;48.294,48.374,-12.950|0|7dbb404af789839a701aebd8b3b603e1|0
+46.194,46.000,19.134;46.194,49.000,19.134;43.306,48.374,24.992|0|7dbb404af789839a701aebd8b3b603e1|0
+30.446,48.374,39.662;35.355,46.000,35.355;35.355,49.000,35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+49.573,46.817,6.521;50.000,46.000,-0.000;49.573,48.374,6.517|0|7dbb404af789839a701aebd8b3b603e1|0
+39.660,46.816,30.448;35.355,49.000,35.355;35.355,46.000,35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+39.660,46.816,30.448;43.304,46.817,24.996;39.662,48.374,30.446|0|7dbb404af789839a701aebd8b3b603e1|0
+43.304,46.817,24.996;46.194,46.000,19.134;43.306,48.374,24.992|0|7dbb404af789839a701aebd8b3b603e1|0
+19.134,46.000,46.194;19.134,49.000,46.194;12.950,48.374,48.294|0|7dbb404af789839a701aebd8b3b603e1|0
+30.442,46.817,39.665;35.355,46.000,35.355;30.446,48.374,39.662|0|7dbb404af789839a701aebd8b3b603e1|0
+12.946,46.817,48.295;6.517,48.374,49.573;6.513,46.816,49.574|0|7dbb404af789839a701aebd8b3b603e1|0
+19.134,49.000,46.194;19.134,46.000,46.194;24.989,46.816,43.307|0|7dbb404af789839a701aebd8b3b603e1|0
+12.946,46.817,48.295;19.134,46.000,46.194;12.950,48.374,48.294|0|7dbb404af789839a701aebd8b3b603e1|0
+6.513,46.816,49.574;6.517,48.374,49.573;-0.000,49.000,50.000|0|7dbb404af789839a701aebd8b3b603e1|0
+0.000,46.000,50.000;6.513,46.816,49.574;-0.000,49.000,50.000|0|7dbb404af789839a701aebd8b3b603e1|0
+12.953,46.816,-48.293;19.134,49.000,-46.194;19.134,46.000,-46.194|0|7dbb404af789839a701aebd8b3b603e1|0
+6.517,48.374,49.573;12.946,46.817,48.295;12.950,48.374,48.294|0|7dbb404af789839a701aebd8b3b603e1|0
+24.989,46.816,43.307;24.992,48.374,43.306;19.134,49.000,46.194|0|7dbb404af789839a701aebd8b3b603e1|0
+24.992,48.374,43.306;30.442,46.817,39.665;30.446,48.374,39.662|0|7dbb404af789839a701aebd8b3b603e1|0
+24.989,46.816,43.307;30.442,46.817,39.665;24.992,48.374,43.306|0|7dbb404af789839a701aebd8b3b603e1|0
+39.660,46.816,30.448;39.662,48.374,30.446;35.355,49.000,35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+6.521,46.817,-49.573;12.950,48.374,-48.294;12.953,46.816,-48.293|0|7dbb404af789839a701aebd8b3b603e1|0
+39.662,48.374,30.446;43.304,46.817,24.996;43.306,48.374,24.992|0|7dbb404af789839a701aebd8b3b603e1|0
+48.293,46.816,12.953;48.294,48.374,12.950;46.194,49.000,19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+6.517,48.374,-49.573;-0.000,46.000,-50.000;-0.000,49.000,-50.000|0|7dbb404af789839a701aebd8b3b603e1|0
+48.294,48.374,12.950;49.573,46.817,6.521;49.573,48.374,6.517|0|7dbb404af789839a701aebd8b3b603e1|0
+49.574,46.816,-6.513;49.573,48.374,-6.517;50.000,49.000,0.000|0|7dbb404af789839a701aebd8b3b603e1|0
+-0.000,46.000,-50.000;-6.513,46.816,-49.574;-0.000,49.000,-50.000|0|7dbb404af789839a701aebd8b3b603e1|0
+49.573,48.374,-6.517;48.295,46.817,-12.946;48.294,48.374,-12.950|0|7dbb404af789839a701aebd8b3b603e1|0
+43.307,46.816,-24.989;43.306,48.374,-24.992;46.194,49.000,-19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+-6.517,48.374,-49.573;-6.513,46.816,-49.574;-12.946,46.817,-48.295|0|7dbb404af789839a701aebd8b3b603e1|0
+43.306,48.374,-24.992;39.665,46.817,-30.442;39.662,48.374,-30.446|0|7dbb404af789839a701aebd8b3b603e1|0
+30.448,46.816,-39.660;30.446,48.374,-39.662;35.355,49.000,-35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+-19.134,46.000,-46.194;-19.134,49.000,-46.194;-12.950,48.374,-48.294|0|7dbb404af789839a701aebd8b3b603e1|0
+30.446,48.374,-39.662;24.996,46.817,-43.304;24.992,48.374,-43.306|0|7dbb404af789839a701aebd8b3b603e1|0
+12.953,46.816,-48.293;12.950,48.374,-48.294;19.134,49.000,-46.194|0|7dbb404af789839a701aebd8b3b603e1|0
+-24.989,46.816,-43.307;-19.134,49.000,-46.194;-19.134,46.000,-46.194|0|7dbb404af789839a701aebd8b3b603e1|0
+12.950,48.374,-48.294;6.521,46.817,-49.573;6.517,48.374,-49.573|0|7dbb404af789839a701aebd8b3b603e1|0
+-6.513,46.816,-49.574;-6.517,48.374,-49.573;-0.000,49.000,-50.000|0|7dbb404af789839a701aebd8b3b603e1|0
+-24.989,46.816,-43.307;-30.442,46.817,-39.665;-24.992,48.374,-43.306|0|7dbb404af789839a701aebd8b3b603e1|0
+-6.517,48.374,-49.573;-12.946,46.817,-48.295;-12.950,48.374,-48.294|0|7dbb404af789839a701aebd8b3b603e1|0
+-24.989,46.816,-43.307;-24.992,48.374,-43.306;-19.134,49.000,-46.194|0|7dbb404af789839a701aebd8b3b603e1|0
+-39.660,46.816,-30.448;-35.355,49.000,-35.355;-35.355,46.000,-35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+-35.355,49.000,-35.355;-30.446,48.374,-39.662;-35.355,46.000,-35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+-24.992,48.374,-43.306;-30.442,46.817,-39.665;-30.446,48.374,-39.662|0|7dbb404af789839a701aebd8b3b603e1|0
+-43.304,46.817,-24.996;-43.306,48.374,-24.992;-39.662,48.374,-30.446|0|7dbb404af789839a701aebd8b3b603e1|0
+-39.660,46.816,-30.448;-39.662,48.374,-30.446;-35.355,49.000,-35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+-43.304,46.817,-24.996;-46.194,46.000,-19.134;-43.306,48.374,-24.992|0|7dbb404af789839a701aebd8b3b603e1|0
+-43.306,48.374,-24.992;-46.194,46.000,-19.134;-46.194,49.000,-19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+-49.574,46.816,6.513;-49.573,48.374,6.517;-50.000,49.000,-0.000|0|7dbb404af789839a701aebd8b3b603e1|0
+-49.573,46.817,-6.521;-49.573,48.374,-6.517;-48.294,48.374,-12.950|0|7dbb404af789839a701aebd8b3b603e1|0
+-46.194,49.000,19.134;-48.294,48.374,12.950;-46.194,46.000,19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+-49.573,48.374,6.517;-48.295,46.817,12.946;-48.294,48.374,12.950|0|7dbb404af789839a701aebd8b3b603e1|0
+-35.355,49.000,35.355;-39.662,48.374,30.446;-35.355,46.000,35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+-35.355,49.000,35.355;-35.355,46.000,35.355;-30.448,46.816,39.660|0|7dbb404af789839a701aebd8b3b603e1|0
+-43.307,46.816,24.989;-43.306,48.374,24.992;-46.194,49.000,19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+-19.134,49.000,46.194;-19.134,46.000,46.194;-12.953,46.816,48.293|0|7dbb404af789839a701aebd8b3b603e1|0
+-19.134,46.000,46.194;-19.134,49.000,46.194;-24.992,48.374,43.306|0|7dbb404af789839a701aebd8b3b603e1|0
+-30.448,46.816,39.660;-30.446,48.374,39.662;-35.355,49.000,35.355|0|7dbb404af789839a701aebd8b3b603e1|0
+-6.517,48.374,49.573;-6.521,46.817,49.573;0.000,46.000,50.000|0|7dbb404af789839a701aebd8b3b603e1|0
+-6.521,46.817,49.573;-6.517,48.374,49.573;-12.950,48.374,48.294|0|7dbb404af789839a701aebd8b3b603e1|0
+-12.953,46.816,48.293;-12.950,48.374,48.294;-19.134,49.000,46.194|0|7dbb404af789839a701aebd8b3b603e1|0
+-30.446,48.374,39.662;-24.996,46.817,43.304;-24.992,48.374,43.306|0|7dbb404af789839a701aebd8b3b603e1|0
+0.000,46.000,50.000;-0.000,49.000,50.000;-6.517,48.374,49.573|0|7dbb404af789839a701aebd8b3b603e1|0
+-19.134,46.000,46.194;-24.992,48.374,43.306;-24.996,46.817,43.304|0|7dbb404af789839a701aebd8b3b603e1|0
+-6.521,46.817,49.573;-12.950,48.374,48.294;-12.953,46.816,48.293|0|7dbb404af789839a701aebd8b3b603e1|0
+-39.665,46.817,30.442;-35.355,46.000,35.355;-39.662,48.374,30.446|0|7dbb404af789839a701aebd8b3b603e1|0
+-24.996,46.817,43.304;-30.446,48.374,39.662;-30.448,46.816,39.660|0|7dbb404af789839a701aebd8b3b603e1|0
+-39.662,48.374,30.446;-43.306,48.374,24.992;-39.665,46.817,30.442|0|7dbb404af789839a701aebd8b3b603e1|0
+-43.307,46.816,24.989;-46.194,49.000,19.134;-46.194,46.000,19.134|0|7dbb404af789839a701aebd8b3b603e1|0
+-39.665,46.817,30.442;-43.306,48.374,24.992;-43.307,46.816,24.989|0|7dbb404af789839a701aebd8b3b603e1|0
+-48.295,46.817,12.946;-46.194,46.000,19.134;-48.294,48.374,12.950|0|7dbb404af789839a701aebd8b3b603e1|0
+-50.000,49.000,-0.000;-50.000,46.000,-0.000;-49.574,46.816,6.513|0|7dbb404af789839a701aebd8b3b603e1|0
+-48.295,46.817,12.946;-49.573,48.374,6.517;-49.574,46.816,6.513|0|7dbb404af789839a701aebd8b3b603e1|0
+-50.000,49.000,-0.000;-49.573,48.374,-6.517;-50.000,46.000,-0.000|0|7dbb404af789839a701aebd8b3b603e1|0
+-50.000,46.000,-0.000;-49.573,48.374,-6.517;-49.573,46.817,-6.521|0|7dbb404af789839a701aebd8b3b603e1|0
+-49.573,46.817,-6.521;-48.294,48.374,-12.950;-48.293,46.816,-12.953|0|7dbb404af789839a701aebd8b3b603e1|0
+-46.194,49.000,-19.134;-48.293,46.816,-12.953;-48.294,48.374,-12.950|0|7dbb404af789839a701aebd8b3b603e1|0
+-- 台面
+25.058,63.400,-0.000;17.719,63.400,-17.719;-0.000,63.400,-25.058|0|396b3abcea691c830e02a40289596796|11
+-17.719,63.400,-17.719;17.719,63.400,17.719;25.058,63.400,-0.000|0|396b3abcea691c830e02a40289596796|11
+-0.000,63.400,-25.058;-17.719,63.400,-17.719;25.058,63.400,-0.000|0|396b3abcea691c830e02a40289596796|11
+0.000,63.400,25.058;17.719,63.400,17.719;-25.058,63.400,0.000|0|396b3abcea691c830e02a40289596796|11
+-25.058,63.400,0.000;-17.719,63.400,17.719;0.000,63.400,25.058|0|396b3abcea691c830e02a40289596796|11
+-17.719,63.400,-17.719;-25.058,63.400,0.000;17.719,63.400,17.719|0|396b3abcea691c830e02a40289596796|11
+-- 下腰面 22
+-48.295,46.817,12.946;-10.002,9.202,4.100;-46.194,46.000,19.134|0|a4895d6e10f22c829b9d793bd382bafd|22
+-49.574,46.816,6.513;-10.002,9.202,4.100;-48.295,46.817,12.946|0|a4895d6e10f22c829b9d793bd382bafd|22
+-49.574,46.816,6.513;-50.000,46.000,-0.000;-10.002,9.202,4.100|0|a4895d6e10f22c829b9d793bd382bafd|22
+
+-9.972,9.202,-4.173;-39.660,46.816,-30.448;-35.355,46.000,-35.355|0|00dc5045a0aaa20edee44fa48934fe79|22
+-39.660,46.816,-30.448;-9.972,9.202,-4.173;-43.304,46.817,-24.996|0|00dc5045a0aaa20edee44fa48934fe79|22
+-9.972,9.202,-4.173;-46.194,46.000,-19.134;-43.304,46.817,-24.996|0|00dc5045a0aaa20edee44fa48934fe79|22
+
+24.996,46.817,-43.304;4.173,9.202,-9.972;19.134,46.000,-46.194|0|d4bce1a0044d59d475f7c90909c737be|22
+30.448,46.816,-39.660;4.173,9.202,-9.972;24.996,46.817,-43.304|0|d4bce1a0044d59d475f7c90909c737be|22
+4.173,9.202,-9.972;30.448,46.816,-39.660;35.355,46.000,-35.355|0|d4bce1a0044d59d475f7c90909c737be|22
+
+4.173,9.202,-9.972;6.521,46.817,-49.573;12.953,46.816,-48.293|0|2ac8e5af58984a47577a703618d5a05e|22
+4.173,9.202,-9.972;12.953,46.816,-48.293;19.134,46.000,-46.194|0|2ac8e5af58984a47577a703618d5a05e|22
+4.173,9.202,-9.972;-0.000,46.000,-50.000;6.521,46.817,-49.573|0|2ac8e5af58984a47577a703618d5a05e|22
+
+-4.100,9.202,-10.002;-12.946,46.817,-48.295;-6.513,46.816,-49.574|0|78b4ef23c9f365322759fbdfbe2eceac|22
+-0.000,46.000,-50.000;-4.100,9.202,-10.002;-6.513,46.816,-49.574|0|78b4ef23c9f365322759fbdfbe2eceac|22
+-12.946,46.817,-48.295;-4.100,9.202,-10.002;-19.134,46.000,-46.194|0|78b4ef23c9f365322759fbdfbe2eceac|22
+
+-19.134,46.000,-46.194;-4.100,9.202,-10.002;-24.989,46.816,-43.307|0|38c7a333470f49e5c29e1bc691f8aeb5|22
+-24.989,46.816,-43.307;-4.100,9.202,-10.002;-30.442,46.817,-39.665|0|38c7a333470f49e5c29e1bc691f8aeb5|22
+-4.100,9.202,-10.002;-35.355,46.000,-35.355;-30.442,46.817,-39.665|0|38c7a333470f49e5c29e1bc691f8aeb5|22
+
+-10.002,9.202,4.100;-35.355,46.000,35.355;-39.665,46.817,30.442|0|9189072cfbf3cccb1c2ef0eb831cf149|22
+-39.665,46.817,30.442;-43.307,46.816,24.989;-10.002,9.202,4.100|0|9189072cfbf3cccb1c2ef0eb831cf149|22
+-10.002,9.202,4.100;-43.307,46.816,24.989;-46.194,46.000,19.134|0|9189072cfbf3cccb1c2ef0eb831cf149|22
+
+-46.194,46.000,-19.134;-9.972,9.202,-4.173;-48.293,46.816,-12.953|0|08a840488158522766bd3b24fde624da|22
+-48.293,46.816,-12.953;-9.972,9.202,-4.173;-49.573,46.817,-6.521|0|08a840488158522766bd3b24fde624da|22
+-9.972,9.202,-4.173;-50.000,46.000,-0.000;-49.573,46.817,-6.521|0|08a840488158522766bd3b24fde624da|22
+
+10.002,9.202,-4.100;48.295,46.817,-12.946;49.574,46.816,-6.513|0|dd7c41b1fce549f42aeacd7aab372fac|22
+50.000,46.000,-0.000;10.002,9.202,-4.100;49.574,46.816,-6.513|0|dd7c41b1fce549f42aeacd7aab372fac|22
+48.295,46.817,-12.946;10.002,9.202,-4.100;46.194,46.000,-19.134|0|dd7c41b1fce549f42aeacd7aab372fac|22
+
+43.304,46.817,24.996;9.972,9.202,4.173;46.194,46.000,19.134|0|e75da2414a4fa8b60247f78d30ec2e5c|22
+39.660,46.816,30.448;9.972,9.202,4.173;43.304,46.817,24.996|0|e75da2414a4fa8b60247f78d30ec2e5c|22
+9.972,9.202,4.173;39.660,46.816,30.448;35.355,46.000,35.355|0|e75da2414a4fa8b60247f78d30ec2e5c|22
+
+9.972,9.202,4.173;49.573,46.817,6.521;48.293,46.816,12.953|0|c894271128a77e1a047b177ccdbf4607|22
+9.972,9.202,4.173;48.293,46.816,12.953;46.194,46.000,19.134|0|c894271128a77e1a047b177ccdbf4607|22
+9.972,9.202,4.173;50.000,46.000,-0.000;49.573,46.817,6.521|0|c894271128a77e1a047b177ccdbf4607|22
+
+46.194,46.000,-19.134;10.002,9.202,-4.100;43.307,46.816,-24.989|0|4664b8df612337edf03ba928bd73808b|22
+43.307,46.816,-24.989;10.002,9.202,-4.100;39.665,46.817,-30.442|0|4664b8df612337edf03ba928bd73808b|22
+10.002,9.202,-4.100;35.355,46.000,-35.355;39.665,46.817,-30.442|0|4664b8df612337edf03ba928bd73808b|22
+
+-19.134,46.000,46.194;-4.173,9.202,9.972;-12.953,46.816,48.293|0|1d6fc5b123e903da99e2eab57bb260ec|22
+-12.953,46.816,48.293;-4.173,9.202,9.972;-6.521,46.817,49.573|0|1d6fc5b123e903da99e2eab57bb260ec|22
+-4.173,9.202,9.972;0.000,46.000,50.000;-6.521,46.817,49.573|0|1d6fc5b123e903da99e2eab57bb260ec|22
+
+4.100,9.202,10.002;30.442,46.817,39.665;24.989,46.816,43.307|0|aa6881482e26977e69a0984677871631|22
+4.100,9.202,10.002;24.989,46.816,43.307;19.134,46.000,46.194|0|aa6881482e26977e69a0984677871631|22
+4.100,9.202,10.002;35.355,46.000,35.355;30.442,46.817,39.665|0|aa6881482e26977e69a0984677871631|22
+
+12.946,46.817,48.295;4.100,9.202,10.002;19.134,46.000,46.194|0|da3ca69e937333c4995bd186e06e6660|22
+6.513,46.816,49.574;4.100,9.202,10.002;12.946,46.817,48.295|0|da3ca69e937333c4995bd186e06e6660|22
+6.513,46.816,49.574;0.000,46.000,50.000;4.100,9.202,10.002|0|da3ca69e937333c4995bd186e06e6660|22
+
+-19.134,46.000,46.194;-24.996,46.817,43.304;-4.173,9.202,9.972|0|67b54da250ef377dc19356e7603055ff|22
+-30.448,46.816,39.660;-4.173,9.202,9.972;-24.996,46.817,43.304|0|67b54da250ef377dc19356e7603055ff|22
+-30.448,46.816,39.660;-35.355,46.000,35.355;-4.173,9.202,9.972|0|67b54da250ef377dc19356e7603055ff|22
+
+-- 亭部主刻面 21
+0.000,0.000,-0.000;-50.000,46.000,-0.000;-9.766,8.985,-4.045|0|cda6c912b39797c7ba8cf3ffea613640|21
+-50.000,46.000,-0.000;0.000,0.000,-0.000;-9.766,8.985,4.045|0|cda6c912b39797c7ba8cf3ffea613640|21
+
+-4.045,8.985,9.766;-9.766,8.985,4.045;0.000,0.000,-0.000|0|93990da555a0dbdbecda185365def922|21
+-4.173,9.202,9.972;-9.766,8.985,4.045;-4.045,8.985,9.766|0|93990da555a0dbdbecda185365def922|21
+-9.766,8.985,4.045;-4.173,9.202,9.972;-35.355,46.000,35.355|0|93990da555a0dbdbecda185365def922|21
+
+9.972,9.202,4.173;35.355,46.000,35.355;4.045,8.985,9.766|0|d7b0cbd2902f01b69995ac44aa07deff|21
+9.766,8.985,4.045;4.045,8.985,9.766;0.000,0.000,-0.000|0|d7b0cbd2902f01b69995ac44aa07deff|21
+9.766,8.985,4.045;9.972,9.202,4.173;4.045,8.985,9.766|0|d7b0cbd2902f01b69995ac44aa07deff|21
+
+4.173,9.202,-9.972;35.355,46.000,-35.355;9.766,8.985,-4.045|0|44979f9e3066ce33059f50702fcb0c0a|21
+4.045,8.985,-9.766;9.766,8.985,-4.045;0.000,0.000,-0.000|0|44979f9e3066ce33059f50702fcb0c0a|21
+4.045,8.985,-9.766;4.173,9.202,-9.972;9.766,8.985,-4.045|0|44979f9e3066ce33059f50702fcb0c0a|21
+
+-9.766,8.985,-4.045;-4.045,8.985,-9.766;0.000,0.000,-0.000|0|5ccb9023f767a55a8498a2af13084186|21
+-9.972,9.202,-4.173;-4.045,8.985,-9.766;-9.766,8.985,-4.045|0|5ccb9023f767a55a8498a2af13084186|21
+-4.045,8.985,-9.766;-9.972,9.202,-4.173;-35.355,46.000,-35.355|0|5ccb9023f767a55a8498a2af13084186|21
+
+-4.045,8.985,-9.766;-0.000,46.000,-50.000;0.000,0.000,-0.000|0|ee94fca4a7073265020c9d5044dbedb0|21
+0.000,0.000,-0.000;-0.000,46.000,-50.000;4.045,8.985,-9.766|0|ee94fca4a7073265020c9d5044dbedb0|21
+
+9.766,8.985,-4.045;50.000,46.000,-0.000;0.000,0.000,-0.000|0|1493d5a442ff1b307d8cfe6e736a45c2|21
+0.000,0.000,-0.000;50.000,46.000,-0.000;9.766,8.985,4.045|0|1493d5a442ff1b307d8cfe6e736a45c2|21
+
+0.000,0.000,-0.000;0.000,46.000,50.000;-4.045,8.985,9.766|0|f677990350a0533680a5ae5477b48fe3|21
+4.045,8.985,9.766;0.000,46.000,50.000;0.000,0.000,-0.000|0|f677990350a0533680a5ae5477b48fe3|21
+
+-- 亭部缝隙??
+-50.000,46.000,-0.000;-9.766,8.985,4.045;-10.002,9.202,4.100|0|0|99
+-50.000,46.000,-0.000;-9.972,9.202,-4.173;-9.766,8.985,-4.045|0|0|99
+-0.000,46.000,-50.000;-4.045,8.985,-9.766;-4.100,9.202,-10.002|0|0|99
+50.000,46.000,-0.000;9.766,8.985,-4.045;10.002,9.202,-4.100|0|0|99
+4.100,9.202,10.002;0.000,46.000,50.000;4.045,8.985,9.766|0|0|99
+4.045,8.985,-9.766;-0.000,46.000,-50.000;4.173,9.202,-9.972|0|0|99
+-35.355,46.000,-35.355;-4.100,9.202,-10.002;-4.045,8.985,-9.766|0|0|99
+9.766,8.985,4.045;50.000,46.000,-0.000;9.972,9.202,4.173|0|0|99
+35.355,46.000,-35.355;10.002,9.202,-4.100;9.766,8.985,-4.045|0|0|99
+0.000,46.000,50.000;-4.173,9.202,9.972;-4.045,8.985,9.766|0|0|99
+4.100,9.202,10.002;4.045,8.985,9.766;35.355,46.000,35.355|0|0|99
+-10.002,9.202,4.100;-9.766,8.985,4.045;-35.355,46.000,35.355|0|0|99
+-- 冠部主刻面(风筝面) 11
+-25.058,63.400,0.000;-35.315,57.478,-14.626;-50.000,49.000,-0.000|0|0bbf439750922c7f2e219a59d12a99c5|12
+-50.000,49.000,-0.000;-35.316,57.478,14.627;-25.058,63.400,0.000|0|0bbf439750922c7f2e219a59d12a99c5|12
+
+17.719,63.400,17.719;35.355,49.000,35.355;35.315,57.478,14.629|0|dbba6f34125fd5b2c424d907fa689490|12
+35.355,49.000,35.355;17.719,63.400,17.719;14.629,57.478,35.313|0|dbba6f34125fd5b2c424d907fa689490|12
+
+17.719,63.400,-17.719;35.355,49.000,-35.355;14.629,57.478,-35.315|0|99f6930e4b75d96d2def876408192739|12
+35.355,49.000,-35.355;17.719,63.400,-17.719;35.313,57.478,-14.629|0|99f6930e4b75d96d2def876408192739|12
+
+-0.000,63.400,-25.058;-0.000,49.000,-50.000;-14.627,57.478,-35.316|0|08383999f8e7205240c161d03f7dfb84|12
+-0.000,63.400,-25.058;14.629,57.478,-35.315;-0.000,49.000,-50.000|0|08383999f8e7205240c161d03f7dfb84|12
+
+-17.719,63.400,-17.719;-35.355,49.000,-35.355;-35.315,57.478,-14.626|0|e4266b2dd15a1c3da6e58b750c715eed|12
+-17.719,63.400,-17.719;-14.627,57.478,-35.316;-35.355,49.000,-35.355|0|e4266b2dd15a1c3da6e58b750c715eed|12
+
+25.058,63.400,-0.000;50.000,49.000,0.000;35.313,57.478,-14.629|0|c6e1c0df3fffda386444d1d5fcabb530|12
+25.058,63.400,-0.000;35.315,57.478,14.629;50.000,49.000,0.000|0|c6e1c0df3fffda386444d1d5fcabb530|12
+
+0.000,63.400,25.058;-0.000,49.000,50.000;14.629,57.478,35.313|0|71c4bbfd0f33113e25ad5263483c0b1c|12
+0.000,63.400,25.058;-14.626,57.478,35.315;-0.000,49.000,50.000|0|71c4bbfd0f33113e25ad5263483c0b1c|12
+
+-17.719,63.400,17.719;-35.355,49.000,35.355;-14.626,57.478,35.315|0|45f8d52f83c5f7430398b405873a1d92|12
+-17.719,63.400,17.719;-35.316,57.478,14.627;-35.355,49.000,35.355|0|45f8d52f83c5f7430398b405873a1d92|12
+
+-- 星刻面
+-35.315,57.478,-14.626;-25.058,63.400,0.000;-17.719,63.400,-17.719|0|86b6a3c846d148b11bb1a42f80a83609|13
+-14.626,57.478,35.315;0.000,63.400,25.058;-17.719,63.400,17.719|0|96027456fb0953612f46c7407d4d9789|13
+-25.058,63.400,0.000;-35.316,57.478,14.627;-17.719,63.400,17.719|0|65f35d216ac8996693fa14131b5a5e0b|13
+0.000,63.400,25.058;14.629,57.478,35.313;17.719,63.400,17.719|0|6e4c972b21512ab99a14aec93b598f6a|13
+17.719,63.400,17.719;35.315,57.478,14.629;25.058,63.400,-0.000|0|6820ce13dc7f6667dcc4a412afe0f3ac|13
+35.313,57.478,-14.629;17.719,63.400,-17.719;25.058,63.400,-0.000|0|7F343D202CE6C46623B9098993F4F498|13
+-14.627,57.478,-35.316;-17.719,63.400,-17.719;-0.000,63.400,-25.058|0|015DE61BEAE0BB2CE98C05C8D25E07ED|13
+17.719,63.400,-17.719;14.629,57.478,-35.315;-0.000,63.400,-25.058|0|81245B930647AA46C51C4989D41639E4|13
+-- 上腰面
+
+-35.355,49.000,35.355;-35.316,57.478,14.627;-39.662,48.374,30.446|0|d7f46d06662280b465e80e44baaf6656|14
+-46.194,49.000,19.134;-43.306,48.374,24.992;-35.316,57.478,14.627|0|d7f46d06662280b465e80e44baaf6656|14
+-39.662,48.374,30.446;-35.316,57.478,14.627;-43.306,48.374,24.992|0|d7f46d06662280b465e80e44baaf6656|14
+
+-46.194,49.000,19.134;-35.316,57.478,14.627;-48.294,48.374,12.950|0|6273974b7ba6e76f538fc2443e709984|14
+-50.000,49.000,-0.000;-49.573,48.374,6.517;-35.316,57.478,14.627|0|6273974b7ba6e76f538fc2443e709984|14
+-48.294,48.374,12.950;-35.316,57.478,14.627;-49.573,48.374,6.517|0|6273974b7ba6e76f538fc2443e709984|14
+
+14.629,57.478,-35.315;6.517,48.374,-49.573;-0.000,49.000,-50.000|0|03b25c5175e9e4d8619c96fd2780a4c8|14
+14.629,57.478,-35.315;12.950,48.374,-48.294;6.517,48.374,-49.573|0|03b25c5175e9e4d8619c96fd2780a4c8|14
+14.629,57.478,-35.315;19.134,49.000,-46.194;12.950,48.374,-48.294|0|03b25c5175e9e4d8619c96fd2780a4c8|14
+
+-14.627,57.478,-35.316;-30.446,48.374,-39.662;-35.355,49.000,-35.355|0|63b0f0caa3909830e589f01de7b8144f|14
+-30.446,48.374,-39.662;-14.627,57.478,-35.316;-24.992,48.374,-43.306|0|63b0f0caa3909830e589f01de7b8144f|14
+-24.992,48.374,-43.306;-14.627,57.478,-35.316;-19.134,49.000,-46.194|0|63b0f0caa3909830e589f01de7b8144f|14
+
+35.313,57.478,-14.629;39.662,48.374,-30.446;35.355,49.000,-35.355|0|82e6e851718c1e77c4d2872412645ee2|14
+39.662,48.374,-30.446;35.313,57.478,-14.629;43.306,48.374,-24.992|0|82e6e851718c1e77c4d2872412645ee2|14
+43.306,48.374,-24.992;35.313,57.478,-14.629;46.194,49.000,-19.134|0|82e6e851718c1e77c4d2872412645ee2|14
+
+35.315,57.478,14.629;49.573,48.374,6.517;50.000,49.000,0.000|0|cc0526c6c2f54bd71b11be0ca77c72a1|14
+35.315,57.478,14.629;48.294,48.374,12.950;49.573,48.374,6.517|0|cc0526c6c2f54bd71b11be0ca77c72a1|14
+35.315,57.478,14.629;46.194,49.000,19.134;48.294,48.374,12.950|0|cc0526c6c2f54bd71b11be0ca77c72a1|14
+
+14.629,57.478,35.313;19.134,49.000,46.194;24.992,48.374,43.306|0|4b95459cf9f65a489618d114ec9561b1|14
+30.446,48.374,39.662;35.355,49.000,35.355;14.629,57.478,35.313|0|4b95459cf9f65a489618d114ec9561b1|14
+14.629,57.478,35.313;24.992,48.374,43.306;30.446,48.374,39.662|0|4b95459cf9f65a489618d114ec9561b1|14
+
+-14.626,57.478,35.315;-6.517,48.374,49.573;-0.000,49.000,50.000|0|c169ff75fbf71e9d8e52dc1d035618a8|14
+-14.626,57.478,35.315;-19.134,49.000,46.194;-12.950,48.374,48.294|0|c169ff75fbf71e9d8e52dc1d035618a8|14
+-6.517,48.374,49.573;-14.626,57.478,35.315;-12.950,48.374,48.294|0|c169ff75fbf71e9d8e52dc1d035618a8|14
+
+-35.315,57.478,-14.626;-49.573,48.374,-6.517;-50.000,49.000,-0.000|0|3046264364e3284ab25d874dfafc5b13|14
+-35.315,57.478,-14.626;-46.194,49.000,-19.134;-48.294,48.374,-12.950|0|3046264364e3284ab25d874dfafc5b13|14
+-49.573,48.374,-6.517;-35.315,57.478,-14.626;-48.294,48.374,-12.950|0|3046264364e3284ab25d874dfafc5b13|14
+
+-14.626,57.478,35.315;-24.992,48.374,43.306;-19.134,49.000,46.194|0|a9783029b821c23fe8724485645e2067|14
+-24.992,48.374,43.306;-14.626,57.478,35.315;-30.446,48.374,39.662|0|a9783029b821c23fe8724485645e2067|14
+-14.626,57.478,35.315;-35.355,49.000,35.355;-30.446,48.374,39.662|0|a9783029b821c23fe8724485645e2067|14
+
+19.134,49.000,46.194;14.629,57.478,35.313;12.950,48.374,48.294|0|9a48e09f3da15e8ad7f88eb749440fc9|14
+-0.000,49.000,50.000;6.517,48.374,49.573;14.629,57.478,35.313|0|9a48e09f3da15e8ad7f88eb749440fc9|14
+12.950,48.374,48.294;14.629,57.478,35.313;6.517,48.374,49.573|0|9a48e09f3da15e8ad7f88eb749440fc9|14
+
+43.306,48.374,24.992;46.194,49.000,19.134;35.315,57.478,14.629|0|c5c6965a2da976f05d6b2af107edd438|14
+35.355,49.000,35.355;39.662,48.374,30.446;35.315,57.478,14.629|0|c5c6965a2da976f05d6b2af107edd438|14
+43.306,48.374,24.992;35.315,57.478,14.629;39.662,48.374,30.446|0|c5c6965a2da976f05d6b2af107edd438|14
+
+35.313,57.478,-14.629;49.573,48.374,-6.517;48.294,48.374,-12.950|0|e7db2f10bfc06b6bd66626ce54239040|14
+35.313,57.478,-14.629;48.294,48.374,-12.950;46.194,49.000,-19.134|0|e7db2f10bfc06b6bd66626ce54239040|14
+35.313,57.478,-14.629;50.000,49.000,0.000;49.573,48.374,-6.517|0|e7db2f10bfc06b6bd66626ce54239040|14
+
+24.992,48.374,-43.306;19.134,49.000,-46.194;14.629,57.478,-35.315|0|40ad8b5dc3d50fbce654fd1ebdddf174|14
+35.355,49.000,-35.355;30.446,48.374,-39.662;14.629,57.478,-35.315|0|40ad8b5dc3d50fbce654fd1ebdddf174|14
+24.992,48.374,-43.306;14.629,57.478,-35.315;30.446,48.374,-39.662|0|40ad8b5dc3d50fbce654fd1ebdddf174|14
+
+-14.627,57.478,-35.316;-6.517,48.374,-49.573;-12.950,48.374,-48.294|0|513a3ebeecf54327e17972ddac75d4e9|14
+-14.627,57.478,-35.316;-12.950,48.374,-48.294;-19.134,49.000,-46.194|0|513a3ebeecf54327e17972ddac75d4e9|14
+-14.627,57.478,-35.316;-0.000,49.000,-50.000;-6.517,48.374,-49.573|0|513a3ebeecf54327e17972ddac75d4e9|14
+
+-35.315,57.478,-14.626;-43.306,48.374,-24.992;-46.194,49.000,-19.134|0|d7efe8af63a3706f1e8ebe01a7ccac04|14
+-43.306,48.374,-24.992;-35.315,57.478,-14.626;-39.662,48.374,-30.446|0|d7efe8af63a3706f1e8ebe01a7ccac04|14
+-35.315,57.478,-14.626;-35.355,49.000,-35.355;-39.662,48.374,-30.446|0|d7efe8af63a3706f1e8ebe01a7ccac04|14
diff --git a/Resource/Images/Temp/rtop.png b/Resource/Images/Temp/rtop.png
new file mode 100644
index 0000000..cf8c984
Binary files /dev/null and b/Resource/Images/Temp/rtop.png differ
diff --git a/SparkClient.csproj b/SparkClient.csproj
index be710d8..fd168fe 100644
--- a/SparkClient.csproj
+++ b/SparkClient.csproj
@@ -14,6 +14,7 @@
+
@@ -57,6 +58,18 @@
+
+
+ Always
+
+
+ Always
+
+
+
+
+
+
@@ -80,6 +93,11 @@
Wpf
Designer
+
+
+
+
+
diff --git a/ViewModel/BaseWindow/HomeWindowVM.cs b/ViewModel/BaseWindow/HomeWindowVM.cs
index 69274c9..a29e27e 100644
--- a/ViewModel/BaseWindow/HomeWindowVM.cs
+++ b/ViewModel/BaseWindow/HomeWindowVM.cs
@@ -38,7 +38,7 @@ public class HomeWindowVM : BaseViewModel
public void ShowDiamlondSelPage(object parameter)
{
- BaseControlVM vm = new BaseControlVM(new DiamondSelectVM(), MultilingualHelper.getString("DiamondSelect"));
+ BaseControlVM vm = new BaseControlVM(new GradingResultVM(null), MultilingualHelper.getString("DetectionResult"));
WindowManager.mainViewModel.Content = vm;
WindowManager.openContent.Add(vm);
}
diff --git a/ViewModel/Grading/GradingResultVM.cs b/ViewModel/Grading/GradingResultVM.cs
index aeecf58..9140d89 100644
--- a/ViewModel/Grading/GradingResultVM.cs
+++ b/ViewModel/Grading/GradingResultVM.cs
@@ -1,13 +1,27 @@
+using System.Data;
+using System.Windows.Input;
+using HandyControl.Controls;
+
namespace SparkClient.ViewModel.Grading;
-public class GradingResultVM: BaseViewModel
+public class GradingResultVM : BaseViewModel
{
+
+ private DataTable _dtResults;
+
+ public ICommand ChangeNormCommand { get; }
+ public DataTable DtResults{ get { return _dtResults; } set { _dtResults = value; OnPropertyChanged("DtResults"); } }
+
///
/// 构造
///
/// 检测结果
public GradingResultVM(object result)
{
+ ChangeNormCommand = new RelayCommand(ChangeNorm);
+ _dtResults = new DataTable();
+
+
}
@@ -17,6 +31,7 @@ public class GradingResultVM: BaseViewModel
///
public void ChangeNorm(object norm)
{
+
}
#region 钻石操作相关
diff --git a/Views/Grading/GradingResult.xaml b/Views/Grading/GradingResult.xaml
index 33c7015..796c950 100644
--- a/Views/Grading/GradingResult.xaml
+++ b/Views/Grading/GradingResult.xaml
@@ -3,10 +3,85 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:local="clr-namespace:SparkClient.Views.Grading"
+ xmlns:hx="http://helix-toolkit.org/wpf/SharpDX"
mc:Ignorable="d"
+ d:DesignWidth="1000"
+ d:DesignHeight="600"
>
-
- 检测结果
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Views/Grading/GradingResult.xaml.cs b/Views/Grading/GradingResult.xaml.cs
index b4dd005..cd2f562 100644
--- a/Views/Grading/GradingResult.xaml.cs
+++ b/Views/Grading/GradingResult.xaml.cs
@@ -1,11 +1,122 @@
using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media.Media3D;
+using HelixToolkit.Wpf.SharpDX;
+using SharpDX;
+using SparkClient.Model.Entity;
+using SparkClient.Model.Helper;
+using SparkClient.ViewModel.Grading;
+using GeometryModel3D = HelixToolkit.Wpf.SharpDX.GeometryModel3D;
+using MeshGeometry3D = HelixToolkit.Wpf.SharpDX.MeshGeometry3D;
+using PerspectiveCamera = HelixToolkit.Wpf.SharpDX.PerspectiveCamera;
namespace SparkClient.Views.Grading;
public partial class GradingResult
{
+ List triangles = new List();
+ List mouseAddModels = new List();
public GradingResult()
{
InitializeComponent();
+
+ DataContext = new GradingResultVM(null);
+
+ this.Viewport3Dx.EffectsManager = new DefaultEffectsManager();
+ this.Viewport3Dx.Camera = new PerspectiveCamera()
+ {
+ Position = new Point3D(0, 0, 5),
+ LookDirection = new Vector3D(0, 0, -1),
+ UpDirection = new Vector3D(0, 1, 0),
+ FarPlaneDistance = 1000,
+ NearPlaneDistance = 0.1
+ };
+
+ Loaded += (sender, args) =>
+ {
+ var entities = Viewport3DHelper.InitDemo(Viewport3Dx);
+ triangles.AddRange(entities);
+ };
+ }
+
+
+ ///
+ /// 点击模型
+ ///
+ ///
+ ///
+ private void Viewport3Dx_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ // 获取鼠标点击位置
+ var mousePosition = e.GetPosition(Viewport3Dx);
+
+ // 查找鼠标点击的 3D 对象
+ var hits = Viewport3Dx.FindHits(mousePosition);
+
+ // 如果没有命中任何 3D 对象
+ if (hits == null || hits.Count == 0)
+ {
+ Console.WriteLine("未点击到任何模型");
+ foreach (var item in mouseAddModels)
+ {
+ Viewport3Dx.Items.Remove(item);
+ }
+ mouseAddModels.Clear();
+ return;
+ }
+
+ // 获取第一个命中的对象
+ var hit = hits[0];
+
+ // 检查是否是 MeshGeometryModel3D
+ if (hit.ModelHit is MeshGeometryModel3D modelHit)
+ {
+ foreach (var item in mouseAddModels)
+ {
+ Viewport3Dx.Items.Remove(item);
+ }
+ mouseAddModels.Clear();
+ // 获取几何信息
+ var geometry = modelHit.Geometry as MeshGeometry3D;
+ if (geometry != null)
+ {
+ // 获取命中的三角形索引
+ var triangleIndex = hit.TriangleIndices;
+
+ // 获取三角形顶点
+ var vertex1 = geometry.Positions[triangleIndex.Item1];
+ var vertex2 = geometry.Positions[triangleIndex.Item2];
+ var vertex3 = geometry.Positions[triangleIndex.Item3];
+
+ string strPoint = vertex1.X + ","+ vertex1.Y+","+ vertex1.Z + ";"+ vertex2.X + ","+ vertex2.Y + ","+ vertex2.Z+";"+vertex3.X + ","+ vertex3.Y + ","+ vertex3.Z;
+ string triangleCode = Viewport3DTriangleEntity.GenerateMD5Hash(strPoint);
+
+ //命中实体
+ Viewport3DTriangleEntity res = triangles.Find(e => triangleCode.Equals(e.TriangleCode));
+
+ if (res == null)
+ return;
+
+ //命中面
+ List facet = triangles.Where(e => res.PlaneCode.Equals(e.PlaneCode)).ToList();
+ var colorFacet = new Color4(1.0f, 1.0f, 0.0f, 1.0f);
+ var data1 = Viewport3DHelper.GenerateEmissiveModelByEntity(Viewport3Dx,facet,colorFacet);
+ mouseAddModels.AddRange(data1);
+ //命中面标线
+ var data2 = Viewport3DHelper.GenerateLineTextModelByEntity(Viewport3Dx, facet);
+ mouseAddModels.AddRange(data2);
+ //命中同类面
+ List facetType = triangles.Where(e => res.PlaneType.Equals(e.PlaneType)).ToList();
+ //排除自己
+ facet.ForEach(e=>facetType.Remove(e));
+ var colorFacetType = new Color4(0.9f, 0.9f, 0.7f, 1.0f);
+ var data3 = Viewport3DHelper.GenerateEmissiveModelByEntity(Viewport3Dx,facetType,colorFacetType);
+ mouseAddModels.AddRange(data3);
+ }
+ }
+ else
+ {
+ Console.WriteLine("点击的对象不是 MeshGeometryModel3D");
+ }
}
}
\ No newline at end of file