| # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """This is a simple geometry module containing basic elements.""" |
| |
| |
| # To allow roundoff error |
| TOLERANCE = 0.00000001 |
| |
| |
| def about_eq(f1, f2): |
| """Determine if two numbers are about equal within the TOLERANCE. |
| |
| @param f1: float number 1 |
| @param f2: float number 2 |
| """ |
| return abs(f1 - f2) < TOLERANCE |
| |
| |
| class Point: |
| """A point class.""" |
| def __init__(self, x=None, y=None): |
| """Initialize a point. |
| |
| @param x: x coordinate |
| @param y: y coordinate |
| """ |
| self.x = x if x is None else float(x) |
| self.y = y if y is None else float(y) |
| |
| def __bool__(self): |
| """A boolean indicating if this point is defined.""" |
| return self.x is not None and self.y is not None |
| |
| def __eq__(self, p): |
| """Determine if this point is equal to the specified point, p. |
| |
| @param p: a point |
| """ |
| return about_eq(self.x, p.x) and about_eq(self.y, p.y) |
| |
| def __hash__(self): |
| """Redefine the hash function to meet the consistency requirement. |
| |
| In order to put an item into a set, it needs to be hashable. |
| To make an object hashable, it must meet the consistency requirement: |
| a == b must imply hash(a) == hash(b) |
| """ |
| return hash((self.x, self.y)) |
| |
| def __str__(self): |
| """The string representation of the point value.""" |
| return 'Point: (%.4f, %.4f)' % (self.x, self.y) |
| |
| def distance(self, p): |
| """Calculate the distance between p and this point. |
| |
| @param p: a point |
| """ |
| dist_x = p.x - self.x |
| dist_y = p.y - self.y |
| return (dist_x ** 2 + dist_y ** 2 ) ** 0.5 |
| |
| def value(self): |
| """Return the point coordinates.""" |
| return (self.x, self.y) |
| |
| # __bool__ is used in Python 3.x and __nonzero__ in Python 2.x |
| __nonzero__ = __bool__ |
| |
| |
| class Circle: |
| """A circle class.""" |
| def __init__(self, center, radius): |
| """Initialize a circle. |
| |
| @param center: the center point of the circle |
| @param radius: the radius of the circle |
| """ |
| self.center = center |
| self.radius = radius |
| |
| def __bool__(self): |
| """A boolean indicating if this circle is defined.""" |
| return self.center is not None and self.radius is not None |
| |
| def __contains__(self, p): |
| """Determine if p is enclosed in the circle. |
| |
| @param p: a point |
| """ |
| return self.center.distance(p) <= self.radius + TOLERANCE |
| |
| def __eq__(self, c): |
| """Determine if this circle is equal to the specified circle, c. |
| |
| @param c: a circle |
| """ |
| return self.center == c.center and about_eq(self.radius, c.radius) |
| |
| def __hash__(self): |
| """Redefine the hash function to meet the consistency requirement. |
| |
| In order to put an item into a sets.Set, it needs to be hashable. |
| To make an object hashable, it must meet the consistency requirement: |
| a == b must imply hash(a) == hash(b) |
| """ |
| return hash((self.center, self.radius)) |
| |
| def __str__(self): |
| """The string representation of the circle value.""" |
| return ('Center: %s, %s' % (str(self.center), |
| 'Radius: %.4f' % self.radius) |
| if self else 'Circle is None') |
| |
| # __bool__ is used in Python 3.x and __nonzero__ in Python 2.x |
| __nonzero__ = __bool__ |