|
|
|
@ -25,12 +25,16 @@ class Point:
|
|
|
|
|
self.__point_size = point_size |
|
|
|
|
self.__x = x |
|
|
|
|
self.__y = y |
|
|
|
|
self.__selected = False |
|
|
|
|
|
|
|
|
|
self.__viewport_width = viewport_width |
|
|
|
|
self.__viewport_height = viewport_height |
|
|
|
|
|
|
|
|
|
half_point = floor(point_size / 2.0) |
|
|
|
|
|
|
|
|
|
self.__check_window_bounds(x, y) |
|
|
|
|
|
|
|
|
|
self.__selected = False |
|
|
|
|
|
|
|
|
|
self.__top_left_corner = (self.__x - half_point, |
|
|
|
|
self.__y + half_point) |
|
|
|
|
|
|
|
|
@ -52,29 +56,40 @@ class Point:
|
|
|
|
|
def selected(self): |
|
|
|
|
return self.__selected |
|
|
|
|
|
|
|
|
|
def move(self, dx, dy): |
|
|
|
|
def __check_window_bounds(self, x, y): |
|
|
|
|
""" |
|
|
|
|
Adds the deltas dx and dy to the point. |
|
|
|
|
Simple window bound check that raises an exception when |
|
|
|
|
the point (x, y) exceeds the known viewport bounds. |
|
|
|
|
|
|
|
|
|
@param dx The delta in the x direction. |
|
|
|
|
@param dy The delta in the y direction. |
|
|
|
|
@param x The x-coordinate under test. |
|
|
|
|
@param y The y-coordinate under test. |
|
|
|
|
@raises ExceededWindowBoundsError If the viewport bounds are exceeded. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
half_point = floor(self.point_size / 2.0) |
|
|
|
|
|
|
|
|
|
# Screen size in pixels is always positive |
|
|
|
|
# We need to include the half point here because |
|
|
|
|
# the (x, y) for a point is the center of the square and we |
|
|
|
|
# do not want the EDGES to exceed the viewport bounds. |
|
|
|
|
if (self.__x + dx > self.__viewport_width - half_point or |
|
|
|
|
self.__y + dy > self.__viewport_height - half_point or |
|
|
|
|
self.__x + dx < half_point or self.__y + dy < half_point): |
|
|
|
|
if (x > self.__viewport_width - half_point or |
|
|
|
|
y > self.__viewport_height - half_point or |
|
|
|
|
x < half_point or |
|
|
|
|
y < half_point): |
|
|
|
|
|
|
|
|
|
raise ExceededWindowBoundsError |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def move(self, dx, dy): |
|
|
|
|
""" |
|
|
|
|
Adds the deltas dx and dy to the point. |
|
|
|
|
|
|
|
|
|
@param dx The delta in the x direction. |
|
|
|
|
@param dy The delta in the y direction. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
self.__check_window_bounds(self.__x + dx, self.__y + dy) |
|
|
|
|
|
|
|
|
|
self.__x += dx |
|
|
|
|
self.__y += dy |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __eq__(self, other): |
|
|
|
|
""" |
|
|
|
@ -86,7 +101,6 @@ class Point:
|
|
|
|
|
self.__y == other.y and |
|
|
|
|
self.__point_size == other.point_size) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __hash__(self): |
|
|
|
|
""" |
|
|
|
|
Overridden hashing function so it can be used as a dictionary key |
|
|
|
@ -94,7 +108,6 @@ class Point:
|
|
|
|
|
""" |
|
|
|
|
return hash((self.__x, self.__y, self.__point_size)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
|
return "POINT<X :{} Y: {} SIZE: {}>".format(self.__x, |
|
|
|
|
self.__y, |
|
|
|
@ -182,6 +195,22 @@ class PointSet:
|
|
|
|
|
def point_size(self): |
|
|
|
|
return self.__point_size |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def viewport_height(self): |
|
|
|
|
return self.__viewport_height |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def viewport_width(self): |
|
|
|
|
return self.__viewport_width |
|
|
|
|
|
|
|
|
|
@viewport_height.setter |
|
|
|
|
def viewport_height(self, height): |
|
|
|
|
self.__viewport_height = height |
|
|
|
|
|
|
|
|
|
@viewport_width.setter |
|
|
|
|
def viewport_width(self, width): |
|
|
|
|
self.__viewport_width = width |
|
|
|
|
|
|
|
|
|
def clear_selection(self): |
|
|
|
|
""" |
|
|
|
|
Handy helper function to clear all selected points. |
|
|
|
@ -197,6 +226,9 @@ class PointSet:
|
|
|
|
|
@param x The x-coordinate. |
|
|
|
|
@param y The y-coordinate. |
|
|
|
|
@param attr An optional attribute. |
|
|
|
|
@raises ExceededWindowBoundsError If the point could not be constructed |
|
|
|
|
because it would be outside the window |
|
|
|
|
bounds. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
if attrs != [] and not all(isinstance(x, Attribute) for x in attrs): |
|
|
|
|