How to calculate the minimum difference between 2 values in a range that wraps around itself using math nodes?

I made this illustration and used a circle for better visualization of what I mean. Basically you define the Min and Max values in the range (which end up being the same point) and the max possible difference between the 2 points is never more than half the Max of the range - so, in this case where it's from 0 to 1, the maximum possible difference between 2 points there is 0.5, because they can go back if it's closer - ... and then you define the 2 points, A and B, which you want to get the difference of.

I appreciate very much any help given!

• min(B-A, A+1-B), if you know A to be smaller than B ? if min value is not 0, remove it also. Commented Jan 13 at 13:14

This can be the following:

Determinate who is the max and the min from the A, B inputs.

Either the distance is B - A, or it is A - B + V_Max - V_Min: take the smaller between the 2.

For instance:

(Blender 4.0)

• It's exactly this! You even made a node already ha thank you so much!! I appreciate it a lot. Commented Jan 13 at 14:24

It seems pretty straight-forward to:

1. Take the absolute (to get rid of the sign) difference between two values, that's your traditional difference.
2. For each of the two values:
• take distance to (as in p.1. absolute difference) the minimum
• take distance to maximum
• take the minimum of the two distances above
• sum up the both minimums, that's the wrapping difference; obviously you could only consider distance to minimum + distance to maximum vs distance to maximum + distance to minimum, but I think this way doesn't hurt and is simpler...
3. Take the minimum of the two: traditional and wrapping difference.

There is possibly an even simpler way to look at the problem: rotate your circle so that the closer point to the minimum is at the minimum - now if both values were already within range, you now know the bigger value has to either move to the minimum or to maximum in order to touch the smaller value.

Here's Python code to test both approaches and compare with lemon's:

def lemon(a, b, v_min, v_max):
return min(
max(a, b) - min(a, b),
min(a, b) + v_max - max(a, b) - v_min
)

def obvious(a, b, v_min, v_max):
to_boundary = lambda x: min(abs(x-v_min), abs(x-v_max))
a_to_boundary = to_boundary(a)
b_to_boundary = to_boundary(b)
wrapping_difference = a_to_boundary + b_to_boundary

def simple(a, b, v_min, v_max):
a, b = sorted((a, b))
b -= a - v_min
return min(b - v_min, v_max - b)

v_min, v_max = -3, 5
print(f"{v_min=}, {v_max=}")

col_titles = ("a", "b", "obvious", "lemon", "simple", "equal?")
cols = len(col_titles)

row = "| {:>7} " * cols + "|"

print(line)
print(line)

for a in range(v_min, v_max+1):
for b in range(v_min, v_max+1):
args = a, b, v_min, v_max
o, l, s = obvious(*args), lemon(*args), simple(*args)
print(row.format(a, b, o, l, s, "yes" if o==l==s else "no"))
print(line)

v_min=-3, v_max=5
+---------+---------+---------+---------+---------+---------+
|    a    |    b    | obvious |  lemon  | simple  | equal?  |
+---------+---------+---------+---------+---------+---------+
|      -3 |      -3 |       0 |       0 |       0 |     yes |
|      -3 |      -2 |       1 |       1 |       1 |     yes |
|      -3 |      -1 |       2 |       2 |       2 |     yes |
|      -3 |       0 |       3 |       3 |       3 |     yes |
|      -3 |       1 |       4 |       4 |       4 |     yes |
|      -3 |       2 |       3 |       3 |       3 |     yes |
|      -3 |       3 |       2 |       2 |       2 |     yes |
|      -3 |       4 |       1 |       1 |       1 |     yes |
|      -3 |       5 |       0 |       0 |       0 |     yes |
|      -2 |      -3 |       1 |       1 |       1 |     yes |
|      -2 |      -2 |       0 |       0 |       0 |     yes |
|      -2 |      -1 |       1 |       1 |       1 |     yes |
|      -2 |       0 |       2 |       2 |       2 |     yes |
|      -2 |       1 |       3 |       3 |       3 |     yes |
|      -2 |       2 |       4 |       4 |       4 |     yes |
|      -2 |       3 |       3 |       3 |       3 |     yes |
|      -2 |       4 |       2 |       2 |       2 |     yes |
|      -2 |       5 |       1 |       1 |       1 |     yes |
|      -1 |      -3 |       2 |       2 |       2 |     yes |
|      -1 |      -2 |       1 |       1 |       1 |     yes |
|      -1 |      -1 |       0 |       0 |       0 |     yes |
|      -1 |       0 |       1 |       1 |       1 |     yes |
|      -1 |       1 |       2 |       2 |       2 |     yes |
|      -1 |       2 |       3 |       3 |       3 |     yes |
|      -1 |       3 |       4 |       4 |       4 |     yes |
|      -1 |       4 |       3 |       3 |       3 |     yes |
|      -1 |       5 |       2 |       2 |       2 |     yes |
|       0 |      -3 |       3 |       3 |       3 |     yes |
|       0 |      -2 |       2 |       2 |       2 |     yes |
|       0 |      -1 |       1 |       1 |       1 |     yes |
|       0 |       0 |       0 |       0 |       0 |     yes |
|       0 |       1 |       1 |       1 |       1 |     yes |
|       0 |       2 |       2 |       2 |       2 |     yes |
|       0 |       3 |       3 |       3 |       3 |     yes |
|       0 |       4 |       4 |       4 |       4 |     yes |
|       0 |       5 |       3 |       3 |       3 |     yes |
|       1 |      -3 |       4 |       4 |       4 |     yes |
|       1 |      -2 |       3 |       3 |       3 |     yes |
|       1 |      -1 |       2 |       2 |       2 |     yes |
|       1 |       0 |       1 |       1 |       1 |     yes |
|       1 |       1 |       0 |       0 |       0 |     yes |
|       1 |       2 |       1 |       1 |       1 |     yes |
|       1 |       3 |       2 |       2 |       2 |     yes |
|       1 |       4 |       3 |       3 |       3 |     yes |
|       1 |       5 |       4 |       4 |       4 |     yes |
|       2 |      -3 |       3 |       3 |       3 |     yes |
|       2 |      -2 |       4 |       4 |       4 |     yes |
|       2 |      -1 |       3 |       3 |       3 |     yes |
|       2 |       0 |       2 |       2 |       2 |     yes |
|       2 |       1 |       1 |       1 |       1 |     yes |
|       2 |       2 |       0 |       0 |       0 |     yes |
|       2 |       3 |       1 |       1 |       1 |     yes |
|       2 |       4 |       2 |       2 |       2 |     yes |
|       2 |       5 |       3 |       3 |       3 |     yes |
|       3 |      -3 |       2 |       2 |       2 |     yes |
|       3 |      -2 |       3 |       3 |       3 |     yes |
|       3 |      -1 |       4 |       4 |       4 |     yes |
|       3 |       0 |       3 |       3 |       3 |     yes |
|       3 |       1 |       2 |       2 |       2 |     yes |
|       3 |       2 |       1 |       1 |       1 |     yes |
|       3 |       3 |       0 |       0 |       0 |     yes |
|       3 |       4 |       1 |       1 |       1 |     yes |
|       3 |       5 |       2 |       2 |       2 |     yes |
|       4 |      -3 |       1 |       1 |       1 |     yes |
|       4 |      -2 |       2 |       2 |       2 |     yes |
|       4 |      -1 |       3 |       3 |       3 |     yes |
|       4 |       0 |       4 |       4 |       4 |     yes |
|       4 |       1 |       3 |       3 |       3 |     yes |
|       4 |       2 |       2 |       2 |       2 |     yes |
|       4 |       3 |       1 |       1 |       1 |     yes |
|       4 |       4 |       0 |       0 |       0 |     yes |
|       4 |       5 |       1 |       1 |       1 |     yes |
|       5 |      -3 |       0 |       0 |       0 |     yes |
|       5 |      -2 |       1 |       1 |       1 |     yes |
|       5 |      -1 |       2 |       2 |       2 |     yes |
|       5 |       0 |       3 |       3 |       3 |     yes |
|       5 |       1 |       4 |       4 |       4 |     yes |
|       5 |       2 |       3 |       3 |       3 |     yes |
|       5 |       3 |       2 |       2 |       2 |     yes |
|       5 |       4 |       1 |       1 |       1 |     yes |
|       5 |       5 |       0 |       0 |       0 |     yes |
+---------+---------+---------+---------+---------+---------+


Reproducing the formulas in geonodes should be easy...

• in fact, if you also use "a, b = sorted((a, b))" in "lemon", "simple" and "lemon" are the same, isn't it? Commented Jan 13 at 17:42
• @lemon so this was the logic you started with? I didn't work it out backwards... I guess in the end of the day all 3 of them are mathematically equivalent, the same? Commented Jan 13 at 18:30
• maybe the same, yes. That does not matter so much, anyway! Thanks for the comparison! Commented Jan 13 at 18:46