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 <[email protected]> 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 <[email protected]> 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 > >
