using SharpDX; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Media.Media3D; namespace SparkClient.Views.UserControl.ViewportData.Helper { internal class LineCalculationHelper { private float Y = -0.01F; private Vector3 point1; private Vector3 center; /// /// 常数a(y=ax+b) /// private float a; /// /// 常数b(y=ax+b) /// private float b; public LineCalculationHelper(Vector3 point1, Vector3 center) { this.point1 = point1; this.center = center; this.Y = center.Y; this.a = calA(point1, center); this.b = calB(point1, a); } /// /// 常数a的计算 /// /// /// /// private float calA(Vector3 point1, Vector3 center) { return (point1.Z - center.Z) / (point1.X - center.X); } /// /// 常数b的计算 /// /// /// /// private float calB(Vector3 point1, float a) { return -(a * point1.X)+point1.Z; } public Tuple calXline(float length) { 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.Y; return new Tuple(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2)); } public Tuple calYline(float length) { 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.Y; return new Tuple(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2)); } public Tuple calLineOfOffset(Tuple tuple, float d) { var point1 = tuple.Item1; var point2 = tuple.Item2; var x1 = point1.X - d * (point2.Z - point1.Z)/ (float)Math.Sqrt(Square(point2.X - point1.X) + Square(point2.Z - point1.Z)); var z1 = point1.Z + d * (point2.X - point1.X) / (float)Math.Sqrt(Square(point2.X - point1.X) + Square(point2.Z - point1.Z)); var x2 = point2.X - d * (point2.Z - point1.Z) / (float)Math.Sqrt(Square(point2.X - point1.X) + Square(point2.Z - point1.Z)); var z2 = point2.Z + d * (point2.X - point1.X) / (float)Math.Sqrt(Square(point2.X - point1.X) + Square(point2.Z - point1.Z)); return new Tuple(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2)); } float Square(float number) { return number * number; } public float calZ(float x, float offset = 0) { return a * x + b + offset; } public float calZVertical(float x, float offset = 0) { 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); } } }