
Calculating the Distance Between Points in Wrap Around (Toroidal) Space - Atrix256
https://blog.demofox.org/2017/10/01/calculating-the-distance-between-points-in-wrap-around-toroidal-space/
======
ealloc
A trick for dealing with periodic coordinates, not discussed in the article,
is to convert each periodic coordinate (eg, an angle theta) into a pair of
cartesian coordinates (x,y) on the circle, and then compute the distance in
cartesian space. Ie, convert to x = cos(theta), y = sin(theta).

In the 2d example in the post, you would rescale the coordinates so the unit
cell is from (-pi,pi) in both dimensions, and then the distance formula would
be

    
    
        sqrt(((cos(x1) - cos(x2))**2 + ((sin(x1) - sin(x1))**2 + ((cos(y1) - cos(y2))**2 + ((sin(y1) - sin(y1))**2)
    

This works well for doing things like determining the "nearest" point to
another point, and similar operations, and has some other nice properties.

(I forget the name of this system, but it is commonly used for calculations
involving dihedral angles in MD simulations)

~~~
coherentpony
It depends on how you define "distance". My initial thought when reading your
comment was that you couldn't possibly use the Euclidean distance because
you'd be drawing a path between two points on the circle that involves points
_not_ on the circle.

~~~
taneq
Using the Euclidean distance (Cartesian distance? I dunno) works because it's
a monotonic underestimate of the distance along the circle. So you know if
cartesian_dist(A, B) > cartesian_dist(A, C) then circle_dist(A, B) >
circle_dist(A, C).

~~~
Sniffnoy
The original problem, though, is about computing distance, not about comparing
distances. Comparing distances is just used as an intermediate step in the
initial method given.

------
herbstein
I really enjoy this kind of post. It's short, simple and something most people
could figure out by looking at the problem. Even then, it's still something
that makes you go 'huh, how _would_ you do that?'. Until the intuition about
toroidal space kicks in, that is.

------
phkahler
The may be a simpler way yet. If the coordinates are normalized from [0..1)
and represented as 16bit integers with all bits fractional, you can simply
take the difference x1-x2 and treat the result as signed. The result will be
in the range [-0.5 .. 0.5). If you then square that number to get a 32bit
result it will be correct for that component of the distance formula with no
conditional code at all. Representation can be everything.

~~~
hexane360
x1 = 0.9

x2 = 0

x1-x2 = 0.9 => -0.4

I don't see how this works.

~~~
pdkl95
Add 0.5 to the result to convert the result in [-0.5 .. 0.5) back to [0..1)

    
    
        -0.4 + 0.5 => 0.1

------
yosyp
Isn't the topological manifold of the "wrap around" space described in the
post spherical? A toroidal manifold would more complicated since the two
generalized coordinates do not commute (order matters).

~~~
SomeStupidPoint
I'm not sure what you mean, could you elaborate?

The post says that for a torus, which is a product space of two (or more?)
circles, we can analyze the the distance "along each circle" from a shared
origin for a chosen basis. One circle is our "x" and the other is our "y".
(Contrast with a plane and two lines.)

This seems reasonable if the objects we're looking to measure our distance to
are expressed in terms of those circles as well, since this allows us to
simply put a measure on each circle and get a distance formula for any two
points that behaves the way we would like.

~~~
Atrix256
I'm out of my depth but I believe it's a torus because it's 2 cylinders, not
circles?

~~~
SomeStupidPoint
A cylinder is a circle and a line. The circle goes around and the line is the
height.

A torus is a circle and a circle. One circle goes from the outside to the
inside and back around, and the other goes around the outside, if we're
talking about a donut. We can see that any point on the surface of the donut
is some combination of "go around the outside" and "walk around towards the
center". You can also imagine taking a cylinder and bending it around to make
a torus -- this changes the 'height' line into a second circle.

We're talking about the product space, so what that means is you can describe
the space by (two) coordinates, one drawn from each "shape" (actually,
manifold). A "torus" then differs from a "plane" in that you can wrap around
in the x-direction and wrap around in the y-direction, independently, since
the x-direction on a torus is a circle instead of a line and the y-direction
on a torus is a circle instead of a line. By contrast, a cylinder you can only
wrap around one way, because you can only wrap in the direction that has a
circle for its coordinate space.

------
vog
This article essentially describes a modulo (%) operator for floats, which is
well-defined and completely analogous to the integer modulo operation. I
always wondered why these aren't part of the FPU command set, or at least part
of modern programming languages, e.g.:

    
    
       1.0 % 5.0 = 1.0
       6.0 % 5.0 = 1.0
       7.0 % 5.0 = 2.0
       7.4 % 5.0 = 2.4
       7.4 % 1.0 = 0.4
    

With that in place, the torodial distance becomes a one-liner without any case
distinctions (i.e. without ifs).

~~~
sp332
I couldn't even find an integer modulus operation when I was porting my
fractal code to WebGL.
[https://www.shadertoy.com/view/MdSXWc](https://www.shadertoy.com/view/MdSXWc)

~~~
TrinaryWorksToo
Did the % operator not work? I just tested 1 % 10 and it seemed to compile. I
used the % operator in other shaders. Remember that WebGL is ultimately a sub
and superset of C.

~~~
sp332
It does work! I wonder why I didn't think of it while transliterating from my
older Python codebase.

~~~
FreeFull
It's possible it used to not work with an older version of WebGL/GLSL, and now
it does.

------
hellofunk
This is one of my favorite things to do on the train while on the way to work.
I select two random passing objects out the window, and use a general
assumption about the train's speed. Then I visualize these objects on a
toroidal space, and after a few minutes, I draw the rest of the owl.

------
tomahunt
This type of calculation is used on a very regular basis in molecular dynamics
simulation. The wrap-around space is implemented using periodic boundary
conditions. Calculating the distance between points is most often done using
what is called the minimum image convention. In one dimension for a "box" of
length L the minimum image distance between particles i and j: xij = xj - xi
can be calculated through xij <\- xij - L*nint(xij/L). This avoids any if
statements.

