Browse Source

Easy grouping plus notes

tb-init-ui-render
Taylor Bockman 5 years ago
parent
commit
2ca39f0fd7
  1. 52
      CONTRIBUTING.md
  2. 5
      README.md
  3. 17
      clusterview/points.py
  4. 22
      tests/test_point_set.py

52
CONTRIBUTING.md

@ -7,7 +7,7 @@ Before a PR is accepted it must pass the following requirements in CircleCI:
- [ ] All tests must pass - [ ] All tests must pass
- [ ] The code must be lint free as determined by `flake8` - [ ] The code must be lint free as determined by `flake8`
Additionally, any new code included in the PR must be tested fully. Additionally, any new code included in the PR must be tested fully.
## Developer Requirements ## Developer Requirements
@ -23,7 +23,7 @@ This will install all normal requirements as well as testing requirements.
## Linting ## Linting
We use `flake8` for linting. We use `flake8` for linting.
Run `python -m flake8` in order to get a lint report. Run `python -m flake8` in order to get a lint report.
@ -53,14 +53,14 @@ pyuic5 clusterview.ui clusterview_ui.py
### Import Organization ### Import Organization
Import organization is a critical part of good software engineering. In large Import organization is a critical part of good software engineering. In large
projects considerable time can be wasted looking for a specific import. projects considerable time can be wasted looking for a specific import.
The imports must be organized as follows: The imports must be organized as follows:
```python ```python
# System imports first # System imports first
# Third party imports second # Third party imports second
# UNLV/ClusterView modules external to the current module third # UNLV/ClusterView modules external to the current module third
@ -93,7 +93,7 @@ add two underscores to the prefix of the method name:
def hello_world(): def hello_world():
print("Hello, world!") print("Hello, world!")
# This method can only be seen by the module/class it is defined # This method can only be seen by the module/class it is defined
# in. # in.
@ -104,3 +104,45 @@ def __hello_module():
We only want to expose the absolute bare minimum number of functions to the consumers of We only want to expose the absolute bare minimum number of functions to the consumers of
our modules. our modules.
## Overview of Function
In order to understand how things are drawn and maintained there are some classes you need to know.
### Modes
Lambas, partially applied functions, and function passing are used throughout the application to not only improve
readability but also improve modularity of the code. You can see modes in `clusterview/mode.py`. These modes are used
to put the application in a global state for adding, editing, moving, and deleting things.
In order to improve readability `main_window.py`, the main application class module, uses some neat function passing
tricks to determine which modes to use in `clusterview/mode_handlers.py`. The `mode_handlers.py` module is fairly
complicated but defines basically all of the mode handling code used for each mode in the application.
### Point
The `Point` class is the base class for all drawn points. It contains important details for calculating location
in space such as it's containing viewport, it's x and y coordinates in the viewport, it's drawn size, it's color,
and a list of optional attributes.
### PointSet
A `PointSet` is a convenient holder for all points on a screen. It contains methods that simplify adding to, removing,
moving, and deleting points from the canvas. It maintains a constant viewport state, point size, and other useful
attributes so that you do not need to concern yourself with them during use.
### PointManager
The `PointManager` is a global singleton that is shared across the entire application. You can think of the
`PointManager` as the absolute source of truth for the state of points in the application. In addition to maintaining
a global `PointSet`, it also maintains the `save` and `load` configuration features so that they are consistent
each time they are used.
### Grouping Points
Each point can be grouped by color, defined in `clusterview/colors.py` in the global `PointSet`. This way you
do not need to explicitly maintain sets of points representing groups, and can instead call the `groups` function
on the `PointSet` to return to you a dictionary from `color.Color` to `Point` representing each group and their
member points.

5
README.md

@ -8,13 +8,13 @@ A project for viewing, manipulating, and learning clustering algorithms in Compu
First, make sure you have python installed. If not, follow the installation instructions for your First, make sure you have python installed. If not, follow the installation instructions for your
distribution. distribution.
First: First:
```sh ```sh
sudo pip3 install virtualenv sudo pip3 install virtualenv
``` ```
To make sure you have a working `virtualenv`. To make sure you have a working `virtualenv`.
Now, start `virtualenv`: Now, start `virtualenv`:
@ -40,3 +40,4 @@ python3 clusterview.py
``` ```
To start the software. To start the software.

17
clusterview/points.py

@ -341,3 +341,20 @@ class PointSet:
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):
"""
Returns a map from color to point representing each point's group
membership based on color.
"""
g = {}
for p in self.__points:
if p.color not in g:
# Create the key for the group color since it does
# not exist.
g[p.color] = []
g[p.color].append(p)
return g

22
tests/test_point_set.py

@ -90,3 +90,25 @@ def test_clear_all_selected_points():
unselected += 1 unselected += 1
assert unselected == 2 assert unselected == 2
def test_groups():
point_set = PointSet(8, 100, 100)
point_set.add_point(4, 4, Color.GREY)
point_set.add_point(5, 5, Color.GREY)
point_set.add_point(10, 4, Color.BLUE)
point_set.add_point(30, 5, Color.BLUE)
p1 = Point(4, 4, Color.GREY, 8, 100, 100)
p2 = Point(5, 5, Color.GREY, 8, 100, 100)
p3 = Point(10, 4, Color.BLUE, 8, 100, 100)
p4 = Point(30, 5, Color.BLUE, 8, 100, 100)
expected = {
Color.GREY: [p1, p2],
Color.BLUE: [p3, p4]
}
groups = point_set.groups()
assert groups == expected

Loading…
Cancel
Save