我需要计算3D空间中两点之间的距离。我正在使用的坐标系是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)));
}
答案 0 :(得分:1)
我假设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
,具体取决于您希望如何看待它。