You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.4 KiB
129 lines
4.4 KiB
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 readonly float Y = -0.01F; |
|
private Vector3 point1; |
|
private Vector3 center; |
|
/// <summary> |
|
/// 常数a(y=ax+b) |
|
/// </summary> |
|
private float a; |
|
/// <summary> |
|
/// 常数b(y=ax+b) |
|
/// </summary> |
|
private float b; |
|
public LineCalculationHelper(Vector3 point1, Vector3 center) { |
|
this.point1 = point1; |
|
this.center = center; |
|
this.a = calA(point1, center); |
|
this.b = calB(point1, a); |
|
} |
|
/// <summary> |
|
/// 常数a的计算 |
|
/// </summary> |
|
/// <param name="point1"></param> |
|
/// <param name="center"></param> |
|
/// <returns></returns> |
|
private float calA(Vector3 point1, Vector3 center) |
|
{ |
|
return (point1.Z - center.Z) / (point1.X - center.X); |
|
} |
|
/// <summary> |
|
/// 常数b的计算 |
|
/// </summary> |
|
/// <param name="point1"></param> |
|
/// <param name="a"></param> |
|
/// <returns></returns> |
|
private float calB(Vector3 point1, float a) |
|
{ |
|
return -(a * point1.X)+point1.Z; |
|
} |
|
|
|
public Tuple<Vector3, Vector3> 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.X; |
|
return new Tuple<Vector3, Vector3>(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2)); |
|
} |
|
public Tuple<Vector3, Vector3> 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.X; |
|
return new Tuple<Vector3, Vector3>(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2)); |
|
} |
|
|
|
public Tuple<Vector3, Vector3> calLineOfOffset(Tuple<Vector3, Vector3> 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<Vector3, Vector3>(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); |
|
} |
|
} |
|
}
|
|
|