[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Circular number system?



Okay, wow, that's alot simpler than what I was doing. . . and it works
for all the cases I need it to.  Thanks for the suggestions, all!

-Daniel

On Sun, Feb 22, 2009 at 1:52 PM, Brian Fisher <brian@xxxxxxxxxxxxxxxxxxx> wrote:
> I use python's module operator (%) to accomplish what I think those ring
> classes are meant to accomplish.
>
> def AngleDiff(a, b):
>   return (a - b + 180.0) % 360.0 - 180.0
>
> the function above will return a number from -180.0 to 180 that does the
> kind of difference you are talking about. i.e. AngleDiff(370, 20) return
> -10, cause 20 - 10 = 10, and 370 is the same as 10. So to tell what
> "direction" one angle is from another, you'd just look at the sign of the
> AngleDiff
>
> note that the simple code works because python does a mathematically correct
> mod - where the result of the mod op always matches the sign of the modulo.
> So if you are used to other languages, you are probably used to the sign of
> the result matching the left hand side, which is generally less useful and
> needs a bunch of ifs and crap to write a similar function.
>
> ...I've often thought about writing an "Angle" class that is derivied from
> numbers and overrides arithmetic (so I can say diff = Angle(370) - Angle(20)
> and diff will be Angle(-10)) but sometimes doing that stuff leads to extra
> confusion...
>
>
> On Sun, Feb 22, 2009 at 11:51 AM, Daniel Jo <ostsol@xxxxxxxxx> wrote:
>>
>> What I mean by "circular" is sort of like a clock, where passing the
>> upper limit takes one back to the start again.  Two hours passed 11 on
>> a 12-hour clock is 1 o'clock.  Similarily three hours before 2 is 11
>> o'clock.  Another example is a compass.  Forty-five degrees left of
>> north, 0 degrees, is 315 degrees, rather than -45.
>>
>> My need for it is for the latter example.  In such an example,
>> comparisons such as "less-than" and "greater-than" aren't so important
>> as "left-of" and "right-of", respectively.  Anything in the range
>> [180,360) is left of 0 and anything in the range (0, 180] is right of
>> 0.  Similarily, anything in the range [270,360) and [0,90) is left of
>> 0.
>>
>> My implementation is more of a utility class than a data-type:
>>
>> import math
>>
>> class RingBase (object):
>>    def __init__ (self, lower, upper):
>>        self.lower = lower
>>        self.upper = upper
>>        self.span = upper - lower
>>
>>    def __call__ (self, value):
>>        if value > self.upper:
>>            loops = int (value / self.span)
>>            return value - self.span * loops
>>        if value < self.lower:
>>            loops = int (abs (value) / self.span) + 1
>>            return value + self.span * loops
>>        return value
>>
>>    def _lo (self, v1, v2):
>>        v1 = self (v1)
>>        v2 = self (v2)
>>        half = self.span * 0.5
>>
>>        left = v2 - half
>>
>>        if left < self.lower:
>>            if v1 >= self.upper - (v2 - self.lower):
>>                return True
>>            elif v1 < v2:
>>                return True
>>        elif v1 < v2 and v1 > left:
>>            return True
>>
>>        return False
>>
>>    def _ro (self, v1, v2):
>>        v1 = self (v1)
>>        v2 = self (v2)
>>        half = self.span * 0.5
>>
>>        right = v2 + half
>>
>>        if right >= self.upper:
>>            if v1 <= self.lower + (self.upper - v2):
>>                return True
>>            elif v1 > v2:
>>                return True
>>        elif v1 > v2 and v1 < right:
>>            return True
>>
>>        return False
>>
>> class Ring (RingBase):
>>    def __init__ (self, lower, upper):
>>        super (Ring, self).__init__ (lower, upper)
>>
>>    lo = RingBase._lo
>>    ro = RingBase._ro
>>
>> class Radian (RingBase):
>>    def __init__ (self):
>>        super (Radian, self).__init__ (0.0, 2.0 * math.pi)
>>
>>    lo = RingBase._ro
>>    ro = RingBase._lo
>>
>> An instance of Ring is callable and is used to clamp a value within
>> the Ring's limits.  For example. . .
>>
>> ring = Ring (0, 12)
>> print ring (13)
>>
>> . . . yields 1.
>>
>> print ring (-1)
>>
>> . . . yields 11.
>>
>> ring.lo (11, 1)
>>
>> . . . asks if 11 is left of 1 and returns True.
>>
>> So is there anything else like this out there?
>>
>> -Daniel
>
>