PCQRSCANER/venv/Lib/site-packages/pyzbar/locations.py

71 lines
1.9 KiB
Python
Raw Normal View History

2019-12-22 21:51:47 +01:00
from collections import namedtuple
from itertools import chain
from operator import itemgetter
__all__ = ['bounding_box', 'convex_hull', 'Point', 'Rect']
Point = namedtuple('Point', ['x', 'y'])
Rect = namedtuple('Rect', ['left', 'top', 'width', 'height'])
def bounding_box(locations):
"""Computes the bounding box of an iterable of (x, y) coordinates.
Args:
locations: iterable of (x, y) tuples.
Returns:
`Rect`: Coordinates of the bounding box.
"""
x_values = list(map(itemgetter(0), locations))
x_min, x_max = min(x_values), max(x_values)
y_values = list(map(itemgetter(1), locations))
y_min, y_max = min(y_values), max(y_values)
return Rect(x_min, y_min, x_max - x_min, y_max - y_min)
def convex_hull(points):
"""Computes the convex hull of an iterable of (x, y) coordinates.
Args:
points: iterable of (x, y) tuples.
Returns:
`list`: instances of `Point` - vertices of the convex hull in
counter-clockwise order, starting from the vertex with the
lexicographically smallest coordinates.
Andrew's monotone chain algorithm. O(n log n) complexity.
https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain
"""
def is_not_clockwise(p0, p1, p2):
return 0 <= (
(p1[0] - p0[0]) * (p2[1] - p0[1]) -
(p1[1] - p0[1]) * (p2[0] - p0[0])
)
def go(points_):
res = []
for p in points_:
while 1 < len(res) and is_not_clockwise(res[-2], res[-1], p):
res.pop()
res.append(p)
# The last point in each list is the first point in the other list
res.pop()
return res
# Discard duplicates and sort by x then y
points = sorted(set(points))
# Algorithm needs at least two points
hull = (
points if len(points) < 2 else chain(go(points), go(reversed(points)))
)
return list(map(Point._make, hull))