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
TODO
First install the necessary packages:
`pip install -r requirements.txt`
Then launch clusterview2 using:
`python clusterview2.py`
from the root directory.
## Development

155
clusterview2/points.py

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

2
requirements.txt

@ -3,4 +3,4 @@ PyOpenGL-accelerate==3.1.3b1
PyQt5==5.13.0
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