master
sunhonglei 5 months ago
parent 2a9e87d613
commit 818962f13c
  1. 4
      Views/UserControl/Viewport3D.xaml.cs
  2. 60
      Views/UserControl/ViewportData/Helper/LineCalculationHelper.cs
  3. 144
      Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs
  4. 1
      Views/UserControl/ViewportData/Helper/ViewportManager.cs

@ -413,12 +413,14 @@ public partial class Viewport3D
ViewportManager.ResetChooseAddModels();
break;
case "ViewportRightMenuShowMeshLines":
var center = ViewportManager.ModelBounds.Center;
var maxDimension = ViewportManager.ModelBounds.Size.Length();
var distance = maxDimension * 1.2; // 调整相机到模型的距离,保证视野范围内
var center = ViewportManager.ModelBounds.Center;
// 获取当前相机
var camera = Viewport3Dx.Camera as HelixToolkit.Wpf.SharpDX.PerspectiveCamera;
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);
ViewportManager.ShowMeshLines(checkResult);
//camera.LookDirection = new Vector3D(center.X - camera.Position.X, center.Y - camera.Position.Y, center.Z - camera.Position.Z);

@ -12,7 +12,7 @@ namespace SparkClient.Views.UserControl.ViewportData.Helper
{
private readonly float Y = -0.01F;
private Vector3 point1;
private Vector3 point2;
private Vector3 center;
/// <summary>
/// 常数a(y=ax+b)
/// </summary>
@ -21,21 +21,21 @@ namespace SparkClient.Views.UserControl.ViewportData.Helper
/// 常数b(y=ax+b)
/// </summary>
private float b;
public LineCalculationHelper(Vector3 point1, Vector3 point2) {
public LineCalculationHelper(Vector3 point1, Vector3 center) {
this.point1 = point1;
this.point2 = point2;
this.a = calA(point1, point2);
this.center = center;
this.a = calA(point1, center);
this.b = calB(point1, a);
}
/// <summary>
/// 常数a的计算
/// </summary>
/// <param name="point1"></param>
/// <param name="point2"></param>
/// <param name="center"></param>
/// <returns></returns>
private float calA(Vector3 point1, Vector3 point2)
private float calA(Vector3 point1, Vector3 center)
{
return (point1.Z - point2.Z) / (point1.X - point2.X);
return (point1.Z - center.Z) / (point1.X - center.X);
}
/// <summary>
/// 常数b的计算
@ -50,18 +50,20 @@ namespace SparkClient.Views.UserControl.ViewportData.Helper
public Tuple<Vector3, Vector3> calXline(float length)
{
var x1 = 5;
var z1 = calZ(x1);
var x2 = -5;
var z2 = calZ(x2);
var twoPoint = CalculatePointsOnLine(this.a,length);
var x1 = twoPoint.p1.X;
var z1 = twoPoint.p1.Y;
var x2 = twoPoint.p2.X;
var z2 = twoPoint.p2.X;
return new Tuple<Vector3, Vector3>(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2));
}
public Tuple<Vector3, Vector3> calYline(float length)
{
var x1 = 5;
var z1 = calZVertical(x1);
var x2 = -5;
var z2 = calZVertical(x2);
var twoPoint = CalculatePointsOnLine(-(1/a), length);
var x1 = twoPoint.p1.X;
var z1 = twoPoint.p1.Y;
var x2 = twoPoint.p2.X;
var z2 = twoPoint.p2.X;
return new Tuple<Vector3, Vector3>(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2));
}
@ -95,5 +97,33 @@ namespace SparkClient.Views.UserControl.ViewportData.Helper
{
return (-x / a) + b + offset;
}
private ((float X, float Y) p1, (float X, float Y) p2) CalculatePointsOnLine(float k ,float L)
{
float x0 = center.X;
float y0 = center.Z;
// 将距离公式展开并整理为关于 t 的二次方程
float A = 1 + k * k;
float B = -2 * x0 + 2 * k * (b - y0);
float C = x0 * x0 + (b - y0) * (b - y0) - L * L;
// 计算判别式
float discriminant = B * B - 4 * A * C;
if (discriminant < 0)
{
throw new InvalidOperationException("无解:距离 L 太小,无法找到满足条件的点。");
}
// 计算 t 的两个解
float t1 = (float)(-B + Math.Sqrt(discriminant)) / (2 * A);
float t2 = (float)(-B - Math.Sqrt(discriminant)) / (2 * A);
// 计算两点坐标
var p1 = (X: t1, Y: k * t1 + b);
var p2 = (X: t2, Y: k * t2 + b);
return (p1, p2);
}
}
}

@ -1273,6 +1273,12 @@ public class ViewportHelperPro
lights.ForEach(item => viewport.Items.Remove(item));
}
private static Dictionary<Guid, Guid> moveLines = new Dictionary<Guid, Guid>();
/// <summary>
/// 网状参考线
/// </summary>
/// <param name="entities"></param>
/// <param name="thickness"></param>
/// <returns></returns>
public static List<LineGeometryModel3D> ShowMeshLines(List<Viewport3DTriangleEntity> entities, double thickness = 1.0)
{
moveLines = new();
@ -1288,9 +1294,14 @@ public class ViewportHelperPro
var edgeLines = new List<Tuple<Vector3, Vector3>>();
Color4 XlineColor =new Color4(80f, 0f, 0f, 1f);
var x1 = 5;
float r =5;
if(double.TryParse(ViewportManager.DiamondData["M2"].ToString(), out var v))
{
r = (float)(v*0.501);
}
var x1 = r;
var z1 = lineCal.calZ(x1);
var x2 = -5;
var x2 = -r;
var z2 = lineCal.calZ(x2);
edgeLines.Add(new Tuple<Vector3, Vector3>(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2)));
lines.Add(DisplayLineModel3D(edgeLines, XlineColor));
@ -1318,9 +1329,9 @@ public class ViewportHelperPro
bindingMoveLine(lineE, lineF);
Color4 YlineColor = new Color4(0F, 80f, 0f, 1f);
var x3 = 5;
var x3 = r;
var z3 = lineCal.calZVertical(x3);
var x4 = -5;
var x4 = -r;
var z4 = lineCal.calZVertical(x4);
edgeLines = new List<Tuple<Vector3, Vector3>>();
@ -1350,7 +1361,11 @@ public class ViewportHelperPro
bindingMoveLine(lineG, lineH);
return lines;
}
/// <summary>
/// 网状参考线 对向移动绑定
/// </summary>
/// <param name="lineA"></param>
/// <param name="lineB"></param>
private static void bindingMoveLine(LineGeometryModel3D lineA, LineGeometryModel3D lineB)
{
lineA.MouseDown3D += LineA_MouseDown3D;
@ -1386,7 +1401,7 @@ public class ViewportHelperPro
var perpendicularDirection = Vector3D.CrossProduct(lineDirection.ToVector3D(), Vector3D.CrossProduct(moveDirection, lineDirection.ToVector3D()));
perpendicularDirection.Normalize();
double scaleFactor = 0.1; // 缩放因子
double scaleFactor = 0.05; // 缩放因子
// 计算垂直距离
double perpendicularDistance = Vector3D.DotProduct(moveDirection, perpendicularDirection) * scaleFactor;
System.Console.WriteLine("距离:"+ perpendicularDistance);
@ -1436,11 +1451,11 @@ public class ViewportHelperPro
// 创建射线
var ray = new Ray3D(
camera.Position,
new Vector3D(mousePosition.X - Viewport.ActualWidth / 2, -(mousePosition.Y - Viewport.ActualHeight / 2), -camera.Position.Z)
new Vector3D(mousePosition.X - Viewport.ActualWidth / 2, -camera.Position.Y, -(mousePosition.Y - Viewport.ActualHeight / 2) )
);
// 创建平面(假设平面为 Y=0)
var plane = new Plane3D(new Point3D(0, 0, 0), new Vector3D(0, 0, 1));
var plane = new Plane3D(new Point3D(0, 0, 0), new Vector3D(0, 1, 0));
// 计算射线与平面的交点
var intersection = GetIntersection(ray, plane);
@ -1456,13 +1471,23 @@ public class ViewportHelperPro
// 使用 Plane3D.LineIntersection 方法计算交点
return plane.LineIntersection(ray.Origin, rayEnd);
}
private static double initialRadius = 1.0; // 初始半径
private static double endRadius = 1.0; // 拖拽后半径
private static double initDistance = 1.0; // 初始与圆心之间距离
private static double endDistance = 1.0; // 拖拽后与圆心之间距离
private static Point dragStartPoint;
/// <summary>
/// 圆圈参考线
/// </summary>
/// <param name="radius"></param>
/// <param name="thickness"></param>
/// <returns></returns>
public static LineGeometryModel3D ShowCircleLine(double radius = 1.0, double thickness = 1.0)
{
var Y = -0.01F;
var center = ViewportManager.CenterVector;
center.Y = Y;
return UpdateCircleGeometry(center);
return UpdateCircleGeometry(center, initialRadius);
}
private static LineGeometryModel3D UpdateCircleGeometry(Vector3 center, double radius = 1.0)
{
@ -1482,11 +1507,106 @@ public class ViewportHelperPro
indices.Add(i);
indices.Add((i + 1) % segments);
}
var Circle = DisplayLineModel3D(positions, Color4.Black);
Circle.MouseDown3D += Circle_MouseDown3D;
Circle.MouseUp3D += Circle_MouseUp3D;
Circle.MouseMove3D += Circle_MouseMove3D;
// 更新圆形线的几何形状
return DisplayLineModel3D(positions, Color4.Black);
return Circle;
}
private static void Circle_MouseMove3D(object sender, RoutedEventArgs e)
{
if (isDrawing)
{
if (e is HelixToolkit.Wpf.SharpDX.MouseMove3DEventArgs ev)
{
var line = sender as LineGeometryModel3D;
if (line==null)
{
return;
}
var MinRadius = 0.1;
var MaxRadius = (ViewportManager.ModelBounds.Maximum.X - ViewportManager.ModelBounds.Minimum.X) * 0.6;
// 现在鼠标对于3d模型的位置
var mousePosition = ev.Position;
var Y = -0.01F;
var center = ViewportManager.CenterVector;
center.Y = Y;
Point3D mouseWorldPosition = Get3DPointFromMouse(mousePosition);
// 计算鼠标与圆心的距离
double distance = CalculateDistance(mouseWorldPosition, center.ToPoint3D());
double scaleFactor = 0;
if (distance < initDistance)
{
// 鼠标靠近圆心,缩小半径
scaleFactor = -0.01;
}
else
{
// 鼠标远离圆心,扩大半径
scaleFactor = +0.01;
}
// 计算鼠标移动的距离(以屏幕坐标为单位)
double delta = (dragStartPoint - mousePosition).Length;
// 计算新的半径
double newRadius = initialRadius + delta * scaleFactor; // 缩放因子
// 限制半径范围
newRadius = Math.Clamp(newRadius, MinRadius, MaxRadius);
var scaleTransform = new ScaleTransform3D(newRadius, 1, newRadius); // 缩放变换
line.Transform = scaleTransform;
endRadius = newRadius;
endDistance = distance;
}
}
}
// 计算两点之间的距离
private static double CalculateDistance(Point3D p1, Point3D p2)
{
double dx = p2.X - p1.X;
double dy = p2.Y - p1.Y;
double dz = p2.Z - p1.Z;
return Math.Sqrt(dx * dx + dy * dy + dz * dz);
}
private static void Circle_MouseUp3D(object sender, RoutedEventArgs e)
{
isDrawing = false;
var Viewport = ViewportManager.GetViewport3D();
initialRadius = endRadius;
initDistance = endDistance;
// 释放鼠标捕获
Viewport.ReleaseMouseCapture();
}
private static void Circle_MouseDown3D(object sender, RoutedEventArgs e)
{
isDrawing = true;
if (e is HelixToolkit.Wpf.SharpDX.MouseDown3DEventArgs ev)
{
var line = sender as LineGeometryModel3D;
// 获取鼠标点击的位置
dragStartPoint = ev.Position;
Point3D mouseWorldPosition = Get3DPointFromMouse(dragStartPoint);
var Y = -0.01F;
var center = ViewportManager.CenterVector;
center.Y = Y;
initDistance = CalculateDistance(mouseWorldPosition, center.ToPoint3D());
var Viewport = ViewportManager.GetViewport3D();
// 捕获鼠标
Viewport.CaptureMouse();
}
}
#region 私有方法
/// <summary>

@ -278,6 +278,7 @@ public class ViewportManager
_viewport.Camera.UpDirection = new Vector3D(0, -1, 0);
_viewport.RenderHost.MSAA = MSAALevel.Maximum;
// TODO:
MainModelMeshLines.Clear();
MainModelMeshLines.AddRange(ViewportHelperPro.ShowMeshLines(entities));
MainModelCircleLine = ViewportHelperPro.ShowCircleLine();
}

Loading…
Cancel
Save