これは、ベクターを使用してPython3.xで動作するはずのリンク先のRDPモジュールの更新です。
import functools
def autocast(function):
@functools.wraps(function)
def wrapper(self, other):
if isinstance(other, self.__class__):
if len(other) != len(self):
raise ValueError('Object dimensions are not equivalent!')
return function(self, other)
return function(self, self.__class__(size=len(self), init=other))
return wrapper
class Vector:
__slots__ = '__data'
def __init__(self, *args, size=0, init=0):
self.__data = list(map(float, args if args else [init] * size))
def __repr__(self):
return self.__class__.__name__ + repr(tuple(self))
@autocast
def __cmp__(self, other):
return (self.__data > other.__data) - (self.__data < other.__data)
def __lt__(self, other):
return self.__cmp__(other) < 0
def __le__(self, other):
return self.__cmp__(other) <= 0
def __eq__(self, other):
return self.__cmp__(other) == 0
def __ne__(self, other):
return self.__cmp__(other) != 0
def __gt__(self, other):
return self.__cmp__(other) > 0
def __ge__(self, other):
return self.__cmp__(other) >= 0
def __bool__(self):
return any(self)
def __len__(self):
return len(self.__data)
def __getitem__(self, key):
return self.__data[key]
def __setitem__(self, key, value):
self.__data[key] = float(value)
def __delitem__(self, key):
self[key] = 0
def __iter__(self):
return iter(self.__data)
def __reversed__(self):
return reversed(self.__data)
def __contains__(self, item):
return item in self.__data
@autocast
def __add__(self, other):
return Vector(*(a + b for a, b in zip(self, other)))
@autocast
def __sub__(self, other):
return Vector(*(a - b for a, b in zip(self, other)))
@autocast
def __mul__(self, other):
return Vector(*(a * b for a, b in zip(self, other)))
@autocast
def __truediv__(self, other):
return Vector(*(a / b for a, b in zip(self, other)))
@autocast
def __floordiv__(self, other):
return Vector(*(a // b for a, b in zip(self, other)))
@autocast
def __mod__(self, other):
return Vector(*(a % b for a, b in zip(self, other)))
@autocast
def __divmod__(self, other):
result = tuple(divmod(a, b) for a, b in zip(self, other))
return Vector(*(a for a, b in result)), Vector(*(b for a, b in result))
@autocast
def __pow__(self, other):
return Vector(*(a ** b for a, b in zip(self, other)))
@autocast
def __radd__(self, other):
return Vector(*(a + b for a, b in zip(other, self)))
@autocast
def __rsub__(self, other):
return Vector(*(a - b for a, b in zip(other, self)))
@autocast
def __rmul__(self, other):
return Vector(*(a * b for a, b in zip(other, self)))
@autocast
def __rtruediv__(self, other):
return Vector(*(a / b for a, b in zip(other, self)))
@autocast
def __rfloordiv__(self, other):
return Vector(*(a // b for a, b in zip(other, self)))
@autocast
def __rmod__(self, other):
return Vector(*(a % b for a, b in zip(other, self)))
@autocast
def __rdivmod__(self, other):
result = tuple(divmod(a, b) for a, b in zip(other, self))
return Vector(*(a for a, b in result)), Vector(*(b for a, b in result))
@autocast
def __rpow__(self, other):
return Vector(*(a ** b for a, b in zip(other, self)))
@autocast
def __iadd__(self, other):
for key in range(len(self)):
self[key] += other[key]
return self
@autocast
def __isub__(self, other):
for key in range(len(self)):
self[key] -= other[key]
return self
@autocast
def __imul__(self, other):
for key in range(len(self)):
self[key] *= other[key]
return self
@autocast
def __itruediv__(self, other):
for key in range(len(self)):
self[key] /= other[key]
return self
@autocast
def __ifloordiv__(self, other):
for key in range(len(self)):
self[key] //= other[key]
return self
@autocast
def __imod__(self, other):
for key in range(len(self)):
self[key] %= other[key]
return self
@autocast
def __ipow__(self, other):
for key in range(len(self)):
self[key] **= other[key]
return self
def __neg__(self):
return Vector(*(-value for value in self))
def __pos__(self):
return Vector(*(+value for value in self))
def __abs__(self):
return Vector(*(abs(value) for value in self))
def __get_magnitude(self):
return sum(value ** 2 for value in self) ** 0.5
def __set_magnitude(self, value):
self *= value / self.magnitude
magnitude = property(__get_magnitude, __set_magnitude)
###############################################################################
def point_line_distance(point, start, end):
if start == end:
return (point - start).magnitude
es, sp = end - start, start - point
return abs(es[0] * sp[1] - es[1] * sp[0]) / es.magnitude
def rdp(points, epsilon):
dmax = index = 0
start, *middle, end = points
for i in range(1, len(points) - 1):
d = point_line_distance(points[i], start, end)
if d > dmax:
index, dmax = i, d
if dmax >= epsilon:
return rdp(points[:index+1], epsilon)[:-1] + \
rdp(points[index:], epsilon)
return start, end
元のモジュールによって提供されたデモンストレーションと同様に、以下は使用シナリオの例です。
>>> from pprint import pprint
>>> line = [Vector(0.0, 0.0),
Vector(1.0, 0.0),
Vector(2.0, 0.0),
Vector(2.0, 1.0),
Vector(2.0, 2.0),
Vector(1.0, 2.0),
Vector(0.0, 2.0),
Vector(0.0, 1.0),
Vector(0.0, 0.0)]
>>> pprint(rdp(line, 1.0))
(Vector(0.0, 0.0),
Vector(2.0, 0.0),
Vector(2.0, 2.0),
Vector(0.0, 2.0),
Vector(0.0, 0.0))
>>>