Wrap distance

I have a few ideas on how to solve this but can’t figure out what to google on.

I want to get the distances between two points but I am using a wrap around world (i.e. when you go off the screen to the right, you appear on the left).

I have about three or so ways to solve and will post a solution when I get one but wanted to know some good search terms. Modular distance didn’t do it. Wraparound map distance etc. etc.

Here is the brute force solution if it helps anyone.


function setup()
    r = vec2(300,300) -- red circle
    b = vec2(400,400) -- blue circle   
end

function draw()
    background(0, 0, 0)
    stroke(0, 255, 0, 255)
    strokeWidth(10)
    line(r.x,r.y,b.x,b.y)
    stroke(255,255,0,255)
    local s = wdist(WIDTH,HEIGHT,r,b)
    line(r.x,r.y,s.v.x,s.v.y)
    noStroke()
    fill(255, 0, 0, 255)
    ellipse(r.x,r.y,100,100)
    fill(0, 0, 255, 255)
    ellipse(b.x,b.y,100,100)
end

function touched(touch)
    if touch.state == BEGAN or touch.state == MOVING then
        if r:dist(vec2(touch.x,touch.y)) < 50 then
            r.x = touch.x
            r.y = touch.y
        elseif b:dist(vec2(touch.x,touch.y)) < 50 then
            b.x = touch.x
            b.y = touch.y
        end
    end
end

function wdist(w,h,v1,v2)
    --wrap distance
    --find the distance between v1 and v2 assuming the boundaries wrap
    --w = map width, h = map height
    local dt = {} -- distance table 
    dt[1] = {d=v1:dist(v2),v=v2} --visible distance on screen
    dt[2] = {d=v1:dist(vec2(v2.x,v2.y+h)),v=vec2(v2.x,v2.y+h)} --distance up off map
    dt[3] = {d=v1:dist(vec2(v2.x,v2.y-h)),v=vec2(v2.x,v2.y-h)} --distance down off map
    dt[4] = {d=v1:dist(vec2(v2.x-w,v2.y)),v=vec2(v2.x-w,v2.y)} --distance left off map
    dt[5] = {d=v1:dist(vec2(v2.x+w,v2.y)),v=vec2(v2.x+w,v2.y)} --distance right off map
    dt[6] = {d=v1:dist(vec2(v2.x+w,v2.y+h)),v=vec2(v2.x+w,v2.y+h)} --distance up right off map
    dt[7] = {d=v1:dist(vec2(v2.x-w,v2.y-h)),v=vec2(v2.x-w,v2.y-h)} --distance down left off map
    dt[8] = {d=v1:dist(vec2(v2.x-w,v2.y+h)),v=vec2(v2.x-w,v2.y+h)} --distance up left off map
    dt[9] = {d=v1:dist(vec2(v2.x+w,v2.y-h)),v=vec2(v2.x+w,v2.y-h)} --distance down right off map
    local i
    local sdi = 1 --shortest distance, 1 is visible distance on screen
    local sd = dt[sdi].d --shortest distance
    for i = 2, 9 do
        if dt[i].d < sd then
            sd = dt[i].d
            sdi = i
        end
    end
    return dt[sdi]
end


1|2|3
-----
4|C|6
-----
7|8|9

In the diagram above the points are on C, and the points are projected to the all 8 of the other numeric zones. The nine distances are compared and the shortest one returned. It would also handle if you have a little border around C to prevent wrap pop.

This was for the living images programs. They respond to food by distance and act real cute but can’t see across the boundary … Yet.

pretty elegant solution

.

Updated all posts with brute force solution.

Then updated again after some testing. Hindsight being 20/20, I should have wikied.

Even bet that someone posts something better within a day.

Heck, that looks like a pretty clean approach to me. Sure, someone who’s a topology ace can probably show a nifty bit of math explaining how vectors map to these kind of closed not-spherical-not-cylindrical spaces, but I’m betting the actual implementation wouldn’t look much nicer or run much more quickly.