Browse Source

Make point inheirit from point in kmeans

pull/1/head
Taylor Bockman 5 years ago
parent
commit
eb56f9af63
  1. 10
      README.md
  2. 155
      clusterview2/points.py
  3. 2
      requirements.txt

10
README.md

@ -6,7 +6,15 @@ to explore k-means.
## Usage ## Usage
TODO First install the necessary packages:
`pip install -r requirements.txt`
Then launch clusterview2 using:
`python clusterview2.py`
from the root directory.
## Development ## Development

155
clusterview2/points.py

@ -1,11 +1,12 @@
from math import floor from math import floor
from .colors import Color from kmeans.clustering.point import Point as BasePoint
from .exceptions import ExceededWindowBoundsError
# TODO: THIS WILL NEED TO BE MODIFIED TO INHEIRIT THE KMEANS POINT CLASS. from clusterview2.colors import Color
from clusterview2.exceptions import ExceededWindowBoundsError
class Point:
class Point(BasePoint):
""" """
A class representing a point. A point A class representing a point. A point
has a point_size bounding box around has a point_size bounding box around
@ -33,71 +34,71 @@ class Point:
raise ValueError("Point must be initialized with a color of " + raise ValueError("Point must be initialized with a color of " +
"type Color.") "type Color.")
self.__point_size = point_size self._point_size = point_size
self.__x = x self._x = x
self.__y = y self._y = y
self.__color = color self._color = color
self.__viewport_width = viewport_width self._viewport_width = viewport_width
self.__viewport_height = viewport_height self._viewport_height = viewport_height
self.__calculate_hitbox() self._calculate_hitbox()
self.__check_window_bounds(x, y) self._check_window_bounds(x, y)
self.__selected = False self._selected = False
self.__attributes = [] self._attributes = []
@property @property
def x(self): def x(self):
return self.__x return self._x
@property @property
def y(self): def y(self):
return self.__y return self._y
@property @property
def point_size(self): def point_size(self):
return self.__point_size return self._point_size
@property @property
def selected(self): def selected(self):
return self.__selected return self._selected
@property @property
def color(self): def color(self):
return self.__color return self._color
@color.setter @color.setter
def color(self, color): def color(self, color):
if not isinstance(color, Color): if not isinstance(color, Color):
raise ValueError('Point color must be of type Color.') raise ValueError('Point color must be of type Color.')
self.__color = color self._color = color
@property @property
def attributes(self): def attributes(self):
return self.__attributes return self._attributes
def add_attribute(self, attr): def add_attribute(self, attr):
self.__attributes.append(attr) self._attributes.append(attr)
def __calculate_hitbox(self): def _calculate_hitbox(self):
""" """
Calculates the hit box for the point given the current Calculates the hit box for the point given the current
position (center) and the point size. position (center) and the point size.
""" """
half_point = floor(self.point_size / 2.0) half_point = floor(self.point_size / 2.0)
self.__top_left_corner = (self.__x - half_point, self._top_left_corner = (self._x - half_point,
self.__y + half_point) self._y + half_point)
self.__bottom_right_corner = (self.__x + half_point, self._bottom_right_corner = (self._x + half_point,
self.__y - half_point) self._y - half_point)
def __check_window_bounds(self, x, y): def _check_window_bounds(self, x, y):
""" """
Simple window bound check that raises an exception when Simple window bound check that raises an exception when
the point (x, y) exceeds the known viewport bounds. the point (x, y) exceeds the known viewport bounds.
@ -112,8 +113,8 @@ class Point:
# We need to include the half point here because # We need to include the half point here because
# the (x, y) for a point is the center of the square and we # the (x, y) for a point is the center of the square and we
# do not want the EDGES to exceed the viewport bounds. # do not want the EDGES to exceed the viewport bounds.
if (x > self.__viewport_width - half_point or if (x > self._viewport_width - half_point or
y > self.__viewport_height - half_point or y > self._viewport_height - half_point or
x < half_point or x < half_point or
y < half_point): y < half_point):
@ -127,14 +128,14 @@ class Point:
@param dy The delta in the y direction. @param dy The delta in the y direction.
""" """
self.__check_window_bounds(self.__x + dx, self.__y + dy) self._check_window_bounds(self._x + dx, self._y + dy)
self.__x += dx self._x += dx
self.__y += dy self._y += dy
# It's important to note as we move the point we need to # It's important to note as we move the point we need to
# make sure we are constantly updating it's hitbox. # make sure we are constantly updating it's hitbox.
self.__calculate_hitbox() self._calculate_hitbox()
def __eq__(self, other): def __eq__(self, other):
""" """
@ -142,22 +143,22 @@ class Point:
@param other The other object. @param other The other object.
""" """
return (self.__x == other.x and return (self._x == other.x and
self.__y == other.y and self._y == other.y and
self.__color == other.color and self._color == other.color and
self.__attributes == other.attributes and self._attributes == other.attributes and
self.__point_size == other.point_size) self._point_size == other.point_size)
def __repr__(self): def __repr__(self):
# For some reason I had to split this instead of using one giant # For some reason I had to split this instead of using one giant
# string chained with `+` inside of `()`. # string chained with `+` inside of `()`.
s = "<POINT " s = "<POINT "
s += f"X: {self.__x} | Y: {self.__y} | " s += f"X: {self._x} | Y: {self._y} | "
s += f"SIZE: {self.__point_size} | " s += f"SIZE: {self._point_size} | "
s += f"COLOR: {self.__color} | " s += f"COLOR: {self._color} | "
s += f"VIEWPORT_WIDTH: {self.__viewport_width} | " s += f"VIEWPORT_WIDTH: {self._viewport_width} | "
s += f"VIEWPORT_HEIGHT: {self.__viewport_height}" s += f"VIEWPORT_HEIGHT: {self._viewport_height}"
s += ">" s += ">"
return s return s
@ -166,13 +167,13 @@ class Point:
""" """
Selects the point. Selects the point.
""" """
self.__selected = True self._selected = True
def unselect(self): def unselect(self):
""" """
Unselects the point. Unselects the point.
""" """
self.__selected = False self._selected = False
def hit(self, x, y): def hit(self, x, y):
""" """
@ -196,10 +197,10 @@ class Point:
This function is necessary for properly deleting and selecting points. This function is necessary for properly deleting and selecting points.
""" """
return (x >= self.__top_left_corner[0] and return (x >= self._top_left_corner[0] and
x <= self.__bottom_right_corner[0] and x <= self._bottom_right_corner[0] and
y <= self.__top_left_corner[1] and y <= self._top_left_corner[1] and
y >= self.__bottom_right_corner[1]) y >= self._bottom_right_corner[1])
class Attribute: class Attribute:
@ -208,8 +209,8 @@ class Attribute:
""" """
Initializes an attribute. Initializes an attribute.
""" """
self.__name = name self._name = name
self.__value = value self._value = value
class PointSet: class PointSet:
@ -230,29 +231,29 @@ class PointSet:
@param viewport_height The height of the viewport for bounds @param viewport_height The height of the viewport for bounds
calculations. calculations.
""" """
self.__points = [] self._points = []
self.__point_size = point_size self._point_size = point_size
self.__viewport_width = viewport_width self._viewport_width = viewport_width
self.__viewport_height = viewport_height self._viewport_height = viewport_height
def __eq__(self, other): def __eq__(self, other):
other_points = list(other.points) other_points = list(other.points)
return (self.__points == other_points and return (self._points == other_points and
self.__point_size == other.point_size and self._point_size == other.point_size and
self.__viewport_width == other.viewport_width and self._viewport_width == other.viewport_width and
self.__viewport_height == other.viewport_height) self._viewport_height == other.viewport_height)
def __repr__(self): def __repr__(self):
s = [] s = []
for p in self.__points: for p in self._points:
s.append(str(p)) s.append(str(p))
return ",".join(s) return ",".join(s)
def clear(self): def clear(self):
self.__points = [] self._points = []
@property @property
def points(self): def points(self):
@ -260,37 +261,37 @@ class PointSet:
Getter for points. Returns a generator for Getter for points. Returns a generator for
looping. looping.
""" """
for point in self.__points: for point in self._points:
yield point yield point
@property @property
def point_size(self): def point_size(self):
return self.__point_size return self._point_size
@property @property
def viewport_height(self): def viewport_height(self):
return self.__viewport_height return self._viewport_height
@property @property
def viewport_width(self): def viewport_width(self):
return self.__viewport_width return self._viewport_width
@viewport_height.setter @viewport_height.setter
def viewport_height(self, height): def viewport_height(self, height):
self.__viewport_height = height self._viewport_height = height
@viewport_width.setter @viewport_width.setter
def viewport_width(self, width): def viewport_width(self, width):
self.__viewport_width = width self._viewport_width = width
def empty(self): def empty(self):
return len(self.__points) == 0 return len(self._points) == 0
def clear_selection(self): def clear_selection(self):
""" """
Handy helper function to clear all selected points. Handy helper function to clear all selected points.
""" """
for p in self.__points: for p in self._points:
p.unselect() p.unselect()
def add_point(self, x, y, color, attrs=[]): def add_point(self, x, y, color, attrs=[]):
@ -314,17 +315,17 @@ class PointSet:
if not isinstance(color, Color): if not isinstance(color, Color):
raise ValueError("Point color must be a Color enum.") raise ValueError("Point color must be a Color enum.")
point = Point(x, y, color, self.__point_size, point = Point(x, y, color, self._point_size,
self.__viewport_width, self.__viewport_height) self._viewport_width, self._viewport_height)
for attr in attrs: for attr in attrs:
point.add_attribute(attr) point.add_attribute(attr)
if point in self.__points: if point in self._points:
# Silently reject a duplicate point (same center). # Silently reject a duplicate point (same center).
return return
self.__points.append(point) self._points.append(point)
def remove_point(self, x, y): def remove_point(self, x, y):
""" """
@ -342,9 +343,9 @@ class PointSet:
@param x The x-coordinate. @param x The x-coordinate.
@param y The y-coordinate. @param y The y-coordinate.
""" """
for p in self.__points: for p in self._points:
if p.hit(x, y): if p.hit(x, y):
self.__points.remove(p) self._points.remove(p)
def groups(self): def groups(self):
""" """
@ -353,7 +354,7 @@ class PointSet:
""" """
g = {} g = {}
for p in self.__points: for p in self._points:
if p.color not in g: if p.color not in g:
# Create the key for the group color since it does # Create the key for the group color since it does
# not exist. # not exist.

2
requirements.txt

@ -3,4 +3,4 @@ PyOpenGL-accelerate==3.1.3b1
PyQt5==5.13.0 PyQt5==5.13.0
PyQt5-sip==4.19.18 PyQt5-sip==4.19.18
# Add the kmeans thing here. -e git+https://git.xchg.sh/angrygoats/kmeans.git@master#egg=kmeans

Loading…
Cancel
Save