I'm extending Numerics with a method I call "Boundarize" for lack of better name; I'm sure there are actually real names for this. But its basic purpose is to reset a given point to be within a boundary.
That is, "wrapping" a point around the boundary; if the area is betweeon 0 and 100, if the point goes to -1:
-1.boundarize(0,100) # => 99
(going one too far to the negative "wraps" the point around to one from the max).
102.boundarize(0,100) # => 2
It's a very simple function to implement; when the number is below the minimum, simply add (max-min) until it's in the boundary. If the number is above the maximum, simply subtract (max-min) until it's in the boundary.
One thing I also need to account for is that, there are cases where I don't want to include the minimum in the range, and cases where I don't want to include the maximum in the range. This is specified as an argument.
However, I fear that my current implementation is horribly, terribly, grossly inefficient. And because every time something moves on the screen, it has to re-run this, this is one of the bottlenecks of my application. Anyone have any ideas?
module Boundarizer
def boundarize min=0,max=1,allow_min=true,allow_max=false
raise "Improper boundaries #{min}/#{max}" if min >= max
raise "Cannot have two closed endpoints" if not (allow_min or allow_max)
new_num = self
if allow_min
while new_num < min
new_num += (max-min)
end
else
while new_num <= min
new_num += (max-min)
end
end
if allow_max
while new_num > max
new_num -= (max-min)
end
else
while new_num >= max
new_num -= (max-min)
end
end
return new_num
end
end
class Numeric
include Boundarizer
end
0.boundarize(10,50) # => 40
10.boundarize(0,10) # => 0 (the maximum is by default not allowed)
0.boundarize(0,20,false) # => 20 (the minimum is not allowed)