使用两个坐标层计算 3D space 中两点之间的距离
Calculate distance between two points in 3D space with two coordinate layers
我需要计算 3D 中两点之间的距离 space。我使用的坐标系是 Int64 来获取扇区,在每个扇区内 Int32 用于获取本地位置。所以本质上它是一个 Int96 位坐标系。
不太确定在没有大量 if 语句检查边界的情况下这将如何工作,所以可能有更聪明的方法。
有人可以帮忙吗?
PS! Double 中的精度损失是可以接受的。我不能使用不安全的代码。 BigInteger 不是一个选项,因为 Unity 中的代码必须 运行。
样本可以是:
public struct SectorPos
{
public readonly Int64 X;
public readonly Int64 Y;
public readonly Int64 Z;
public SectorPos(Int64 x, Int64 y, Int64 z)
{
X = x;
Y = y;
Z = z;
}
}
public struct LocalPos
{
public readonly Int32 X;
public readonly Int32 Y;
public readonly Int32 Z;
public LocalPos(Int32 x, Int32 y, Int32 z)
{
X = x;
Y = y;
Z = z;
}
}
struct Pos
{
public readonly SectorPos Sector;
public readonly LocalPos Local;
public Pos(SectorPos sector, LocalPos local)
{
Sector = sector;
Local = local;
}
}
void Test()
{
// Should be 1:
Double d1 = Distance(new Pos(new SectorPos(0, 0, 0),
new LocalPos(Int32.MaxValue, 0, 0)),
new Pos(new SectorPos(0, 1, 0),
new LocalPos(Int32.MinValue, 0, 0)));
// Should be -1: (EDIT: Should be 1 of course)
Double d2 = Distance(new Pos(new SectorPos(0, -2, 0),
new LocalPos(Int32.MaxValue, 0, 0)),
new Pos(new SectorPos(0, -3, 0),
new LocalPos(Int32.MinValue, 0, 0)));
// Should be Int32.MaxValue+1:
Double d3 = Distance(new Pos(new SectorPos(1, 0, 0),
new LocalPos(Int32.MaxValue, 0, 0)),
new Pos(new SectorPos(3, 0, 0),
new LocalPos(Int32.MinValue, 0, 0)));
}
我假设 Sector X=1, Local X=int.MinValue
与 Sector X=0, Local X=int.MaxValue
大致相同。
这意味着1
每个扇区步长的实际大小是int.MaxValue*2
。
要获得绝对 X 位置,您可以执行 secX * int.MaxValue * 2 + locX
。
通过对 double
执行这些操作来避免溢出(而不是在最后尝试转换为 double
)。
所以要将它们放在一起,您可以尝试:
public struct AbsolutePos
{
private const double SEC_FACTOR = int.MaxValue * 2d;
public readonly double X;
public readonly double Y;
public readonly double Z;
public AbsolutePos(SectorPos secPos, LocalPos locPos)
{
X = secPos.X * SEC_FACTOR + locPos.X;
Y = secPos.Y * SEC_FACTOR + locPos.Y;
Z = secPos.Z * SEC_FACTOR + locPos.Z;
}
public double Distance(AbsolutePos pos)
{
// implement 3d distance calculation normally here
}
}
和
struct Pos
{
...
public AbsolutePos GetAbsPos()
{
return new AbsolutePos(this.Sector, this.Local);
}
}
然后您可以将其用作:
var pos1 = new Pos(new SectorPos(0, 0, 0),
new LocalPos(Int32.MaxValue, 0, 0));
var pos2 = new Pos(new SectorPos(0, 1, 0),
new LocalPos(Int32.MinValue, 0, 0));
var distance = pos1.GetAbsolutePos().Distance(pos2.GetAbsolutePos());
您可能希望将最终距离除以 SEC_FACTOR
,具体取决于您希望如何看待它。
我需要计算 3D 中两点之间的距离 space。我使用的坐标系是 Int64 来获取扇区,在每个扇区内 Int32 用于获取本地位置。所以本质上它是一个 Int96 位坐标系。
不太确定在没有大量 if 语句检查边界的情况下这将如何工作,所以可能有更聪明的方法。
有人可以帮忙吗?
PS! Double 中的精度损失是可以接受的。我不能使用不安全的代码。 BigInteger 不是一个选项,因为 Unity 中的代码必须 运行。
样本可以是:
public struct SectorPos
{
public readonly Int64 X;
public readonly Int64 Y;
public readonly Int64 Z;
public SectorPos(Int64 x, Int64 y, Int64 z)
{
X = x;
Y = y;
Z = z;
}
}
public struct LocalPos
{
public readonly Int32 X;
public readonly Int32 Y;
public readonly Int32 Z;
public LocalPos(Int32 x, Int32 y, Int32 z)
{
X = x;
Y = y;
Z = z;
}
}
struct Pos
{
public readonly SectorPos Sector;
public readonly LocalPos Local;
public Pos(SectorPos sector, LocalPos local)
{
Sector = sector;
Local = local;
}
}
void Test()
{
// Should be 1:
Double d1 = Distance(new Pos(new SectorPos(0, 0, 0),
new LocalPos(Int32.MaxValue, 0, 0)),
new Pos(new SectorPos(0, 1, 0),
new LocalPos(Int32.MinValue, 0, 0)));
// Should be -1: (EDIT: Should be 1 of course)
Double d2 = Distance(new Pos(new SectorPos(0, -2, 0),
new LocalPos(Int32.MaxValue, 0, 0)),
new Pos(new SectorPos(0, -3, 0),
new LocalPos(Int32.MinValue, 0, 0)));
// Should be Int32.MaxValue+1:
Double d3 = Distance(new Pos(new SectorPos(1, 0, 0),
new LocalPos(Int32.MaxValue, 0, 0)),
new Pos(new SectorPos(3, 0, 0),
new LocalPos(Int32.MinValue, 0, 0)));
}
我假设 Sector X=1, Local X=int.MinValue
与 Sector X=0, Local X=int.MaxValue
大致相同。
这意味着1
每个扇区步长的实际大小是int.MaxValue*2
。
要获得绝对 X 位置,您可以执行 secX * int.MaxValue * 2 + locX
。
通过对 double
执行这些操作来避免溢出(而不是在最后尝试转换为 double
)。
所以要将它们放在一起,您可以尝试:
public struct AbsolutePos
{
private const double SEC_FACTOR = int.MaxValue * 2d;
public readonly double X;
public readonly double Y;
public readonly double Z;
public AbsolutePos(SectorPos secPos, LocalPos locPos)
{
X = secPos.X * SEC_FACTOR + locPos.X;
Y = secPos.Y * SEC_FACTOR + locPos.Y;
Z = secPos.Z * SEC_FACTOR + locPos.Z;
}
public double Distance(AbsolutePos pos)
{
// implement 3d distance calculation normally here
}
}
和
struct Pos
{
...
public AbsolutePos GetAbsPos()
{
return new AbsolutePos(this.Sector, this.Local);
}
}
然后您可以将其用作:
var pos1 = new Pos(new SectorPos(0, 0, 0),
new LocalPos(Int32.MaxValue, 0, 0));
var pos2 = new Pos(new SectorPos(0, 1, 0),
new LocalPos(Int32.MinValue, 0, 0));
var distance = pos1.GetAbsolutePos().Distance(pos2.GetAbsolutePos());
您可能希望将最终距离除以 SEC_FACTOR
,具体取决于您希望如何看待它。