Reputation: 12326
I need to calculate the distance between two points in 3D space. The coordinate system I'm using is an Int64 to get the sector, and within each sector Int32 is used to get local position. So in essence its a Int96-bit coordinate system.
Not really sure how this would work without a whole lot of if-statements checking boundaries, so there is probably a much smarter way.
Can anyone help?
PS! The precision loss in Double is acceptable. I can't use unsafe code. BigInteger is not an option as code has to run in Unity.
A sample could be:
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)));
}
Upvotes: 1
Views: 928
Reputation: 14532
I'll assume that Sector X=1, Local X=int.MinValue
is roughly the same as Sector X=0, Local X=int.MaxValue
.
This means the actual size of each sector step of 1
is int.MaxValue*2
.
To get absolute X position, you could do secX * int.MaxValue * 2 + locX
.
Avoid overflowing by performing those actions on double
(instead of trying to cast to double
at the end).
So to put this together, you can try:
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
}
}
And
struct Pos
{
...
public AbsolutePos GetAbsPos()
{
return new AbsolutePos(this.Sector, this.Local);
}
}
Then you can use it as:
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());
You might want to divide the final distance by SEC_FACTOR
, depending on how you wish to look at it.
Upvotes: 1