GeometricalDomination 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geometricaldomination-0.1.0/GeometricalDomination.egg-info/PKG-INFO +75 -0
- geometricaldomination-0.1.0/GeometricalDomination.egg-info/SOURCES.txt +14 -0
- geometricaldomination-0.1.0/GeometricalDomination.egg-info/dependency_links.txt +1 -0
- geometricaldomination-0.1.0/GeometricalDomination.egg-info/top_level.txt +1 -0
- geometricaldomination-0.1.0/PKG-INFO +75 -0
- geometricaldomination-0.1.0/README.md +67 -0
- geometricaldomination-0.1.0/UniversalFunctions2/DecoratorArchive.py +15 -0
- geometricaldomination-0.1.0/UniversalFunctions2/GetVariable.py +95 -0
- geometricaldomination-0.1.0/UniversalFunctions2/HelperFunctions.py +93 -0
- geometricaldomination-0.1.0/UniversalFunctions2/RepeatlessList.py +26 -0
- geometricaldomination-0.1.0/UniversalFunctions2/Shapes.py +191 -0
- geometricaldomination-0.1.0/UniversalFunctions2/StringCheck.py +23 -0
- geometricaldomination-0.1.0/UniversalFunctions2/TypingVariables.py +3 -0
- geometricaldomination-0.1.0/UniversalFunctions2/__init__.py +6 -0
- geometricaldomination-0.1.0/pyproject.toml +14 -0
- geometricaldomination-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: GeometricalDomination
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python turtle graphics library and DSL for creating geometric drawings.
|
|
5
|
+
Author-email: "Miah M. Sabiq" <miah.sabiq@gibs.at>
|
|
6
|
+
Requires-Python: >=3.14
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
# GeometricalDomination
|
|
10
|
+
|
|
11
|
+
A Python turtle graphics library and DSL for creating drawings, patterns, shapes, and other geometric designs.
|
|
12
|
+
|
|
13
|
+
## What is GeometricalDomination?
|
|
14
|
+
|
|
15
|
+
GeometricalDomination is a personal Python project built around Python's `turtle` module.
|
|
16
|
+
|
|
17
|
+
It provides a collection of tools for controlling turtles, creating geometric patterns, drawing letters and symbols, defining custom commands, and simplifying repetitive turtle operations.
|
|
18
|
+
|
|
19
|
+
The project is structured as a Python package and is currently being prepared for distribution through `pip`.
|
|
20
|
+
|
|
21
|
+
> **Please note:** This package is still under active development and is subject to ongoing updates and changes.
|
|
22
|
+
>
|
|
23
|
+
> The package currently installs successfully, but importing it may fail due to internal import issues that are still being addressed.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
* Chained turtle commands through `ChainTurtle`
|
|
28
|
+
* Geometric shapes and patterns
|
|
29
|
+
* Alphabet and symbol drawing
|
|
30
|
+
* Custom turtle shapes
|
|
31
|
+
* User-defined drawing commands
|
|
32
|
+
* Utility and validation functions
|
|
33
|
+
* Reusable decorators
|
|
34
|
+
* Support for multiple turtles
|
|
35
|
+
* Tools for creating complex turtle-based drawings
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
For local development, the package can currently be installed with:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python -m pip install .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
PyPI installation will be available once the project is published.
|
|
46
|
+
|
|
47
|
+
## Project Structure
|
|
48
|
+
|
|
49
|
+
The main components of the project include:
|
|
50
|
+
|
|
51
|
+
* `TurtleRunner` — main program entry point
|
|
52
|
+
* `TurtleSkeleton` — extended turtle functionality
|
|
53
|
+
* `Designs` — geometric designs and patterns
|
|
54
|
+
* `Alphabets` — letter and symbol drawing
|
|
55
|
+
* `UserCommands` — user-oriented drawing commands
|
|
56
|
+
* `CustomTurtleShapes` — custom turtle shapes
|
|
57
|
+
* `GlobalFunctions` — shared turtle and screen functionality
|
|
58
|
+
* `UniversalFunctions` — reusable helper and utility functions
|
|
59
|
+
|
|
60
|
+
## Requirements
|
|
61
|
+
|
|
62
|
+
* Python 3.14 or newer
|
|
63
|
+
* Python's built-in `turtle` module
|
|
64
|
+
|
|
65
|
+
No external Python packages are currently required.
|
|
66
|
+
|
|
67
|
+
## Project Status
|
|
68
|
+
|
|
69
|
+
GeometricalDomination is under active development.
|
|
70
|
+
|
|
71
|
+
The core functionality has been implemented, while packaging, documentation, testing, and the project's import system are still being developed.
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
License information will be added in a future release.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
GeometricalDomination.egg-info/PKG-INFO
|
|
4
|
+
GeometricalDomination.egg-info/SOURCES.txt
|
|
5
|
+
GeometricalDomination.egg-info/dependency_links.txt
|
|
6
|
+
GeometricalDomination.egg-info/top_level.txt
|
|
7
|
+
UniversalFunctions2/DecoratorArchive.py
|
|
8
|
+
UniversalFunctions2/GetVariable.py
|
|
9
|
+
UniversalFunctions2/HelperFunctions.py
|
|
10
|
+
UniversalFunctions2/RepeatlessList.py
|
|
11
|
+
UniversalFunctions2/Shapes.py
|
|
12
|
+
UniversalFunctions2/StringCheck.py
|
|
13
|
+
UniversalFunctions2/TypingVariables.py
|
|
14
|
+
UniversalFunctions2/__init__.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
UniversalFunctions2
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: GeometricalDomination
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python turtle graphics library and DSL for creating geometric drawings.
|
|
5
|
+
Author-email: "Miah M. Sabiq" <miah.sabiq@gibs.at>
|
|
6
|
+
Requires-Python: >=3.14
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
# GeometricalDomination
|
|
10
|
+
|
|
11
|
+
A Python turtle graphics library and DSL for creating drawings, patterns, shapes, and other geometric designs.
|
|
12
|
+
|
|
13
|
+
## What is GeometricalDomination?
|
|
14
|
+
|
|
15
|
+
GeometricalDomination is a personal Python project built around Python's `turtle` module.
|
|
16
|
+
|
|
17
|
+
It provides a collection of tools for controlling turtles, creating geometric patterns, drawing letters and symbols, defining custom commands, and simplifying repetitive turtle operations.
|
|
18
|
+
|
|
19
|
+
The project is structured as a Python package and is currently being prepared for distribution through `pip`.
|
|
20
|
+
|
|
21
|
+
> **Please note:** This package is still under active development and is subject to ongoing updates and changes.
|
|
22
|
+
>
|
|
23
|
+
> The package currently installs successfully, but importing it may fail due to internal import issues that are still being addressed.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
* Chained turtle commands through `ChainTurtle`
|
|
28
|
+
* Geometric shapes and patterns
|
|
29
|
+
* Alphabet and symbol drawing
|
|
30
|
+
* Custom turtle shapes
|
|
31
|
+
* User-defined drawing commands
|
|
32
|
+
* Utility and validation functions
|
|
33
|
+
* Reusable decorators
|
|
34
|
+
* Support for multiple turtles
|
|
35
|
+
* Tools for creating complex turtle-based drawings
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
For local development, the package can currently be installed with:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python -m pip install .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
PyPI installation will be available once the project is published.
|
|
46
|
+
|
|
47
|
+
## Project Structure
|
|
48
|
+
|
|
49
|
+
The main components of the project include:
|
|
50
|
+
|
|
51
|
+
* `TurtleRunner` — main program entry point
|
|
52
|
+
* `TurtleSkeleton` — extended turtle functionality
|
|
53
|
+
* `Designs` — geometric designs and patterns
|
|
54
|
+
* `Alphabets` — letter and symbol drawing
|
|
55
|
+
* `UserCommands` — user-oriented drawing commands
|
|
56
|
+
* `CustomTurtleShapes` — custom turtle shapes
|
|
57
|
+
* `GlobalFunctions` — shared turtle and screen functionality
|
|
58
|
+
* `UniversalFunctions` — reusable helper and utility functions
|
|
59
|
+
|
|
60
|
+
## Requirements
|
|
61
|
+
|
|
62
|
+
* Python 3.14 or newer
|
|
63
|
+
* Python's built-in `turtle` module
|
|
64
|
+
|
|
65
|
+
No external Python packages are currently required.
|
|
66
|
+
|
|
67
|
+
## Project Status
|
|
68
|
+
|
|
69
|
+
GeometricalDomination is under active development.
|
|
70
|
+
|
|
71
|
+
The core functionality has been implemented, while packaging, documentation, testing, and the project's import system are still being developed.
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
License information will be added in a future release.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# GeometricalDomination
|
|
2
|
+
|
|
3
|
+
A Python turtle graphics library and DSL for creating drawings, patterns, shapes, and other geometric designs.
|
|
4
|
+
|
|
5
|
+
## What is GeometricalDomination?
|
|
6
|
+
|
|
7
|
+
GeometricalDomination is a personal Python project built around Python's `turtle` module.
|
|
8
|
+
|
|
9
|
+
It provides a collection of tools for controlling turtles, creating geometric patterns, drawing letters and symbols, defining custom commands, and simplifying repetitive turtle operations.
|
|
10
|
+
|
|
11
|
+
The project is structured as a Python package and is currently being prepared for distribution through `pip`.
|
|
12
|
+
|
|
13
|
+
> **Please note:** This package is still under active development and is subject to ongoing updates and changes.
|
|
14
|
+
>
|
|
15
|
+
> The package currently installs successfully, but importing it may fail due to internal import issues that are still being addressed.
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
* Chained turtle commands through `ChainTurtle`
|
|
20
|
+
* Geometric shapes and patterns
|
|
21
|
+
* Alphabet and symbol drawing
|
|
22
|
+
* Custom turtle shapes
|
|
23
|
+
* User-defined drawing commands
|
|
24
|
+
* Utility and validation functions
|
|
25
|
+
* Reusable decorators
|
|
26
|
+
* Support for multiple turtles
|
|
27
|
+
* Tools for creating complex turtle-based drawings
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
For local development, the package can currently be installed with:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
python -m pip install .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
PyPI installation will be available once the project is published.
|
|
38
|
+
|
|
39
|
+
## Project Structure
|
|
40
|
+
|
|
41
|
+
The main components of the project include:
|
|
42
|
+
|
|
43
|
+
* `TurtleRunner` — main program entry point
|
|
44
|
+
* `TurtleSkeleton` — extended turtle functionality
|
|
45
|
+
* `Designs` — geometric designs and patterns
|
|
46
|
+
* `Alphabets` — letter and symbol drawing
|
|
47
|
+
* `UserCommands` — user-oriented drawing commands
|
|
48
|
+
* `CustomTurtleShapes` — custom turtle shapes
|
|
49
|
+
* `GlobalFunctions` — shared turtle and screen functionality
|
|
50
|
+
* `UniversalFunctions` — reusable helper and utility functions
|
|
51
|
+
|
|
52
|
+
## Requirements
|
|
53
|
+
|
|
54
|
+
* Python 3.14 or newer
|
|
55
|
+
* Python's built-in `turtle` module
|
|
56
|
+
|
|
57
|
+
No external Python packages are currently required.
|
|
58
|
+
|
|
59
|
+
## Project Status
|
|
60
|
+
|
|
61
|
+
GeometricalDomination is under active development.
|
|
62
|
+
|
|
63
|
+
The core functionality has been implemented, while packaging, documentation, testing, and the project's import system are still being developed.
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
License information will be added in a future release.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from typing import Callable
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def class_decorator(decorator: Callable) -> Callable:
|
|
5
|
+
"""
|
|
6
|
+
DECORATOR!! Creates a class decorator that applies the given decorator to every user defined function
|
|
7
|
+
:param decorator: provided decorator function
|
|
8
|
+
:return: a class decorator that transforms the class (& it's functions) and returns it
|
|
9
|
+
"""
|
|
10
|
+
def inner(cls):
|
|
11
|
+
for name, func in vars(cls).items():
|
|
12
|
+
if callable(func) and not name.startswith("_"):
|
|
13
|
+
setattr(cls, name, decorator(func))
|
|
14
|
+
return cls
|
|
15
|
+
return inner
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
from time import sleep as rest
|
|
2
|
+
from typing import overload
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@overload
|
|
6
|
+
def get_num(TYPE: type[int], entry: str, **options) -> int: ...
|
|
7
|
+
|
|
8
|
+
@overload
|
|
9
|
+
def get_num(TYPE: type[float], entry: str, **options) -> float: ...
|
|
10
|
+
|
|
11
|
+
def get_num(TYPE: type[float]|type[int], entry: str, **options) -> float|int:
|
|
12
|
+
"""
|
|
13
|
+
Gets a real numerical value from the user
|
|
14
|
+
|
|
15
|
+
:param TYPE: float or int; which type of value to check for
|
|
16
|
+
:param entry: str; input string
|
|
17
|
+
:param options: MAX, MIN, STORE
|
|
18
|
+
:return: float or int
|
|
19
|
+
"""
|
|
20
|
+
if TYPE not in (int, float):
|
|
21
|
+
raise TypeError("TYPE must be type float or int")
|
|
22
|
+
|
|
23
|
+
elif not isinstance(entry, str):
|
|
24
|
+
raise TypeError("entry must be a string")
|
|
25
|
+
|
|
26
|
+
if "MIN" in options:
|
|
27
|
+
if not isinstance(options["MIN"], (float, int)):
|
|
28
|
+
raise TypeError("MIN must be type float or int")
|
|
29
|
+
|
|
30
|
+
if "MAX" in options:
|
|
31
|
+
if not isinstance(options["MAX"], (float, int)):
|
|
32
|
+
raise TypeError("MAX must be type float or int")
|
|
33
|
+
|
|
34
|
+
if "MIN" in options and "MAX" in options:
|
|
35
|
+
if options["MIN"] >= options["MAX"]:
|
|
36
|
+
raise ValueError("MIN has to be less than MAX!")
|
|
37
|
+
|
|
38
|
+
if "store" in options:
|
|
39
|
+
if not isinstance(options["store"], (float, int, type(None))):
|
|
40
|
+
raise TypeError("store must be type float or int or None!")
|
|
41
|
+
if not isinstance(options["store"], (TYPE, type(None))):
|
|
42
|
+
raise TypeError(f"store must be type {TYPE} or None!")
|
|
43
|
+
|
|
44
|
+
if (
|
|
45
|
+
"store" in options
|
|
46
|
+
and "MIN" in options
|
|
47
|
+
and "MAX" in options
|
|
48
|
+
and options["store"] is not None
|
|
49
|
+
and (options["MIN"] > options["store"] or options["MAX"] < options["store"])
|
|
50
|
+
):
|
|
51
|
+
raise ValueError("Stored value must be between MIN and MAX!")
|
|
52
|
+
#if "store" and "MIN" and "MAX" in options and options["MIN"] > options["store"] or options["store"] > options["MAX"]:
|
|
53
|
+
# raise ValueError("stored value in store must be: min <= store <= max!")
|
|
54
|
+
|
|
55
|
+
while True:
|
|
56
|
+
try:
|
|
57
|
+
if "store" in options:
|
|
58
|
+
reserve: str = input(entry)
|
|
59
|
+
if reserve == "ans":
|
|
60
|
+
if options["store"] is not None and isinstance(options["store"], (float,int)):
|
|
61
|
+
value: float|int = options["store"]
|
|
62
|
+
else:
|
|
63
|
+
print("\nThere is no value stored yet!")
|
|
64
|
+
continue
|
|
65
|
+
else:
|
|
66
|
+
value: float|int = TYPE(reserve)
|
|
67
|
+
else:
|
|
68
|
+
value: float|int = TYPE(input(entry))
|
|
69
|
+
if "MIN" in options and "MAX" in options and (value < options["MIN"] or value > options["MAX"]):
|
|
70
|
+
if TYPE == int:
|
|
71
|
+
print(f"INTEGER must be between {options['MIN']} and {options['MAX']}!")
|
|
72
|
+
elif TYPE == float:
|
|
73
|
+
print(f"RATIONAL NUMBER must be between {options['MIN']} and {options['MAX']}!")
|
|
74
|
+
rest(1.5); continue
|
|
75
|
+
elif "MIN" in options and value < options["MIN"]:
|
|
76
|
+
if TYPE == int:
|
|
77
|
+
print(f"Enter INTEGER > {options['MIN']}!")
|
|
78
|
+
elif TYPE == float:
|
|
79
|
+
print(f"Enter RATIONAL NUMBER > {options['MIN']}!")
|
|
80
|
+
rest(1.5); continue
|
|
81
|
+
elif "MAX" in options and value > options['MAX']:
|
|
82
|
+
if TYPE == int:
|
|
83
|
+
print(f"Enter INTEGER < {options['MAX']}!")
|
|
84
|
+
elif TYPE == float:
|
|
85
|
+
print(f"Enter RATIONAL NUMBER < {options['MAX']}!")
|
|
86
|
+
rest(1.5); continue
|
|
87
|
+
elif "store" in options:
|
|
88
|
+
options["store"] = value
|
|
89
|
+
return value
|
|
90
|
+
except ValueError:
|
|
91
|
+
if TYPE == int:
|
|
92
|
+
print(f"Enter INTEGER!")
|
|
93
|
+
elif TYPE == float:
|
|
94
|
+
print("Enter RATIONAL NUMBER!")
|
|
95
|
+
rest(1.5)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from typing import Generator, Any, Annotated
|
|
2
|
+
from math import sqrt, sin, radians
|
|
3
|
+
from UniversalFunctions.GetVariable import get_num
|
|
4
|
+
from UniversalFunctions.DecoratorArchive import class_decorator
|
|
5
|
+
from UniversalFunctions.TypingVariables import Real
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@class_decorator(staticmethod)
|
|
9
|
+
class HelperFunctions:
|
|
10
|
+
|
|
11
|
+
def intervals_f() -> Real:
|
|
12
|
+
"""Asks the user for rational intervals"""
|
|
13
|
+
interval_num: float = get_num(float, "Enter intervals(ℚ>0): ", MIN=0)
|
|
14
|
+
return interval_num
|
|
15
|
+
|
|
16
|
+
def length_float() -> Real:
|
|
17
|
+
"""Asks the user for rational lengths"""
|
|
18
|
+
length: float = get_num(float, "Enter side length(ℚ>0): ", MIN=0)
|
|
19
|
+
return length
|
|
20
|
+
|
|
21
|
+
def radius_float() -> Real:
|
|
22
|
+
"""Asks the user for rational radius"""
|
|
23
|
+
radius: float = get_num(float, "Enter radius(ℚ>0): ", MIN=0)
|
|
24
|
+
return radius
|
|
25
|
+
|
|
26
|
+
def object_num() -> int:
|
|
27
|
+
"""Asks the user for the number of objects"""
|
|
28
|
+
object_count: int = get_num(int, "Enter object count(ℕ≥1): ", MIN=1)
|
|
29
|
+
return object_count
|
|
30
|
+
|
|
31
|
+
def sides_num() -> int:
|
|
32
|
+
"""Asks the user for the number of sides"""
|
|
33
|
+
sides: int = get_num(int, "Enter sides count(ℕ≥3): ", MIN=3)
|
|
34
|
+
return sides
|
|
35
|
+
|
|
36
|
+
def row_num() -> int:
|
|
37
|
+
"""Asks the user for the number of rows"""
|
|
38
|
+
row_count: int = get_num(int, "Enter row count(ℕ≥1): ", MIN=1)
|
|
39
|
+
return row_count
|
|
40
|
+
|
|
41
|
+
def row_pair() -> int:
|
|
42
|
+
"""Asks the user for the number of pairs of rows"""
|
|
43
|
+
row_count: int = get_num(int, "Enter row pairs count(ℕ≥1): ", MIN=1)
|
|
44
|
+
return row_count
|
|
45
|
+
|
|
46
|
+
def diameter_sq(length: Real) -> tuple[Real,Real]:
|
|
47
|
+
"""
|
|
48
|
+
Calculates the diameter of a square with given length
|
|
49
|
+
:return: diameter, diameter/2
|
|
50
|
+
"""
|
|
51
|
+
if not isinstance(length, Real):
|
|
52
|
+
raise TypeError("Length must be a real number")
|
|
53
|
+
if length <= 0:
|
|
54
|
+
raise ValueError("Length must be greater than 0")
|
|
55
|
+
|
|
56
|
+
diameter: float = length*sqrt(2); d_half: Real = diameter / 2
|
|
57
|
+
return diameter, d_half
|
|
58
|
+
|
|
59
|
+
def x_ft() -> Real:
|
|
60
|
+
"""Asks the user for the x value (on the coordinate system)"""
|
|
61
|
+
x_val: float = get_num(float, "Enter x value: ")
|
|
62
|
+
return x_val
|
|
63
|
+
|
|
64
|
+
def y_ft() -> Real:
|
|
65
|
+
"""Asks the user for the y value (on the coordinate system)"""
|
|
66
|
+
y_val: float = get_num(float, "Enter y value: ")
|
|
67
|
+
return y_val
|
|
68
|
+
helper = HelperFunctions
|
|
69
|
+
|
|
70
|
+
def sine(angle: Real) -> Real:
|
|
71
|
+
"""
|
|
72
|
+
Calculates the sine of a given angle
|
|
73
|
+
:param angle: value required in degrees
|
|
74
|
+
"""
|
|
75
|
+
if not isinstance(angle, Real):
|
|
76
|
+
raise TypeError("Angle must be a real number")
|
|
77
|
+
return sin(radians(angle))
|
|
78
|
+
|
|
79
|
+
def range_f(start: Real,stop: Annotated[Real, "stop >= start"],step: Annotated[Real, "step > 0"]) -> Generator[Real,Any,None]:
|
|
80
|
+
"""
|
|
81
|
+
Lets the user choose rational inputs for start, stop and step
|
|
82
|
+
:param start: start value; Real number
|
|
83
|
+
:param stop: stop value; Real number >= start
|
|
84
|
+
:param step: step value; Real number > 0
|
|
85
|
+
"""
|
|
86
|
+
if stop < start:
|
|
87
|
+
raise ValueError("Stop value must be greater than start value")
|
|
88
|
+
elif step <= 0:
|
|
89
|
+
raise ValueError("Step value must be greater than 0")
|
|
90
|
+
|
|
91
|
+
while start < stop:
|
|
92
|
+
yield start
|
|
93
|
+
start += step
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def repeatless_list(old_list: list[Any], new_list: list[Any]) -> list[Any]:
|
|
5
|
+
"""
|
|
6
|
+
Takes the 1st list and adds the items to the 2nd list, with no repetitions in the 2nd list
|
|
7
|
+
:param old_list: 1st list
|
|
8
|
+
:param new_list: 2nd list
|
|
9
|
+
:return: 2nd list
|
|
10
|
+
"""
|
|
11
|
+
for item in old_list:
|
|
12
|
+
if item not in new_list:
|
|
13
|
+
new_list.append(item)
|
|
14
|
+
return new_list
|
|
15
|
+
|
|
16
|
+
def repeatless_list2(old_list: list[Any]) -> list[Any]:
|
|
17
|
+
"""
|
|
18
|
+
Takes the items from a list and adds its items to a new made list, with no repetitions in the new list
|
|
19
|
+
:param old_list: 1st list
|
|
20
|
+
:return: 2nd list
|
|
21
|
+
"""
|
|
22
|
+
new_list: list[Any] = []
|
|
23
|
+
for item in old_list:
|
|
24
|
+
if item not in new_list:
|
|
25
|
+
new_list.append(item)
|
|
26
|
+
return new_list
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
from GeometricalDomination.TurtleSkeleton import ChainTurtle
|
|
3
|
+
from UniversalFunctions.HelperFunctions import sine
|
|
4
|
+
from UniversalFunctions.DecoratorArchive import class_decorator
|
|
5
|
+
from UniversalFunctions.TypingVariables import Real
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@class_decorator(staticmethod)
|
|
9
|
+
class Shapes:
|
|
10
|
+
# ====== STAR OF DAVID ======
|
|
11
|
+
def SOD(side: Real,tls_num: ChainTurtle) -> None:
|
|
12
|
+
"""
|
|
13
|
+
Draws a star of David
|
|
14
|
+
:param side: length of star of David
|
|
15
|
+
:param tls_num: a given ChainTurtle
|
|
16
|
+
"""
|
|
17
|
+
for _ in range(6):
|
|
18
|
+
tls_num.pu().fd(side).pd().rt(60)
|
|
19
|
+
for _ in range(3): tls_num.fd(side).rt(120)
|
|
20
|
+
tls_num.lt(60).pu().bk(side).pd().lt(60)
|
|
21
|
+
# ====== STAR OF DAVID FILL ======
|
|
22
|
+
def SOD_fill(side: Real,tls_num: ChainTurtle) -> None:
|
|
23
|
+
"""
|
|
24
|
+
Draws a filled star of David
|
|
25
|
+
:param side: length of star of David
|
|
26
|
+
:param tls_num: a given ChainTurtle
|
|
27
|
+
"""
|
|
28
|
+
for _ in range(6):
|
|
29
|
+
tls_num.pu().fd(side).pd().rt(60).begin_fill()
|
|
30
|
+
for _ in range(3): tls_num.fd(side).rt(120)
|
|
31
|
+
tls_num.end_fill().lt(60).pu().bk(side).pd().lt(60)
|
|
32
|
+
# ====== HEXAGON ======
|
|
33
|
+
def hexagon_ft(side: Real,tls_num: ChainTurtle) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Draws a hexagon
|
|
36
|
+
:param side: length of hexagon
|
|
37
|
+
:param tls_num: a given ChainTurtle
|
|
38
|
+
"""
|
|
39
|
+
tls_num.pu().fd(side).pd().lt(90).circle(side,360,6)
|
|
40
|
+
# ====== TRIANGLE ======
|
|
41
|
+
def triangle_ft(side: Real, tls_num: ChainTurtle) -> None:
|
|
42
|
+
"""
|
|
43
|
+
Draws a triangle
|
|
44
|
+
:param side: length of triangle
|
|
45
|
+
:param tls_num: a given ChainTurtle
|
|
46
|
+
"""
|
|
47
|
+
for _ in range(3): tls_num.fd(side).lt(120)
|
|
48
|
+
|
|
49
|
+
def triangle_fill(side: Real,tls_num: ChainTurtle) -> None:
|
|
50
|
+
"""
|
|
51
|
+
Draws a filled triangle
|
|
52
|
+
:param side: length of triangle
|
|
53
|
+
:param tls_num: a given ChainTurtle
|
|
54
|
+
"""
|
|
55
|
+
tls_num.begin_fill(); Shapes.triangle_ft(side,tls_num); tls_num.end_fill()
|
|
56
|
+
|
|
57
|
+
def triangle_half(side: Real, tls_num: ChainTurtle) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Draws a triangle from the middle of a side
|
|
60
|
+
:param side: length of triangle
|
|
61
|
+
:param tls_num: a given ChainTurtle
|
|
62
|
+
"""
|
|
63
|
+
tls_num.fd(side/2).lt(120)
|
|
64
|
+
for _ in range(2): tls_num.fd(side).lt(120)
|
|
65
|
+
tls_num.fd(side/2)
|
|
66
|
+
# ====== SQUARE ======
|
|
67
|
+
def square(side: Real,tls_num: ChainTurtle) -> None:
|
|
68
|
+
"""
|
|
69
|
+
Draws a square
|
|
70
|
+
:param side: length of square
|
|
71
|
+
:param tls_num: a given ChainTurtle
|
|
72
|
+
"""
|
|
73
|
+
for _ in range(4): tls_num.fd(side).lt(90)
|
|
74
|
+
|
|
75
|
+
def square_fill(side: Real,tls_num: ChainTurtle) -> None:
|
|
76
|
+
"""
|
|
77
|
+
Draws a filled square
|
|
78
|
+
:param side: length of square
|
|
79
|
+
:param tls_num: a given ChainTurtle
|
|
80
|
+
"""
|
|
81
|
+
tls_num.begin_fill(); Shapes.square(side,tls_num); tls_num.end_fill()
|
|
82
|
+
|
|
83
|
+
def square_half(side: Real,tls_num: ChainTurtle) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Draws a square from the middle of a side
|
|
86
|
+
:param side: length of square
|
|
87
|
+
:param tls_num: a given ChainTurtle
|
|
88
|
+
"""
|
|
89
|
+
tls_num.fd(side/2).lt(90)
|
|
90
|
+
for _ in range(3): tls_num.fd(side).lt(90)
|
|
91
|
+
tls_num.fd(side/2)
|
|
92
|
+
# ====== RECTANGLE ======
|
|
93
|
+
|
|
94
|
+
def rectangle(length: Real,width: Real,direction: Literal[-1,1],tls_num: ChainTurtle) -> None:
|
|
95
|
+
"""
|
|
96
|
+
Draws a rectangle
|
|
97
|
+
:param length: longer side
|
|
98
|
+
:param width: shorter side
|
|
99
|
+
:param direction: -1 draws to the right, 1 draws to the left
|
|
100
|
+
:param tls_num: a given ChainTurtle
|
|
101
|
+
"""
|
|
102
|
+
turn = direction * 90
|
|
103
|
+
for _ in range(2): tls_num.fd(length).lt(turn).fd(width).lt(turn)
|
|
104
|
+
|
|
105
|
+
def rectangle_fill(length: Real,width: Real,direction: Literal[-1,1],tls_num: ChainTurtle) -> None:
|
|
106
|
+
"""
|
|
107
|
+
Draws a filled rectangle
|
|
108
|
+
:param length: longer side
|
|
109
|
+
:param width: shorter side
|
|
110
|
+
:param direction: -1 draws to the right, 1 draws to the left
|
|
111
|
+
:param tls_num: a given ChainTurtle
|
|
112
|
+
"""
|
|
113
|
+
tls_num.begin_fill(); Shapes.rectangle(length,width,direction,tls_num); tls_num.end_fill()
|
|
114
|
+
# ====== HEXAFLOWER ======
|
|
115
|
+
|
|
116
|
+
def hexaflower_tri(length: Real,tls_num: ChainTurtle) -> None:
|
|
117
|
+
"""
|
|
118
|
+
Draws a 12 triangled flower
|
|
119
|
+
:param length: side length of triangles
|
|
120
|
+
:param tls_num: a given ChainTurtle
|
|
121
|
+
"""
|
|
122
|
+
diagonal = (length*sine(120))/sine(30)
|
|
123
|
+
for _ in range(6):
|
|
124
|
+
tls_num.fd(diagonal).lt(150).fd(length).rt(120).bk(length)
|
|
125
|
+
tls_num.fd(length).lt(60).fd(length).rt(30).bk(diagonal)
|
|
126
|
+
|
|
127
|
+
def hexa_flower(radius: Real,tls_num: ChainTurtle) -> None:
|
|
128
|
+
"""
|
|
129
|
+
Draws a 6 petalled flower
|
|
130
|
+
:param radius: radius of flower
|
|
131
|
+
:param tls_num: a given ChainTurtle
|
|
132
|
+
"""
|
|
133
|
+
for _ in range(6): tls_num.circle(-radius,60).rt(120).circle(-radius,60).rt(60)
|
|
134
|
+
# ====== LOTUS FLOWER ======
|
|
135
|
+
|
|
136
|
+
def lotus_flower(radius: Real,tls_num: ChainTurtle) -> None:
|
|
137
|
+
"""
|
|
138
|
+
Draws a 12 petalled flower
|
|
139
|
+
:param radius: radius of flower
|
|
140
|
+
:param tls_num: a given ChainTurtle
|
|
141
|
+
"""
|
|
142
|
+
for n in range(2): Shapes.hexa_flower(radius,tls_num); tls_num.lt((-1)**n*30)
|
|
143
|
+
# ====== LINES ======
|
|
144
|
+
|
|
145
|
+
def lines(distance: Real,lines_num: int,tls_num: ChainTurtle) -> None:
|
|
146
|
+
"""
|
|
147
|
+
Draws a chosen number of lines, evenly spaced apart
|
|
148
|
+
|
|
149
|
+
:param distance: length of lines
|
|
150
|
+
:param lines_num: number of lines
|
|
151
|
+
:param tls_num: a given ChainTurtle
|
|
152
|
+
"""
|
|
153
|
+
angle = int(360/lines_num)
|
|
154
|
+
for _ in range(lines_num): tls_num.fd(distance).bk(distance).lt(angle)
|
|
155
|
+
# ====== CIRCLE ======
|
|
156
|
+
|
|
157
|
+
def circle_ft(radius: Real,tls_num: ChainTurtle) -> None:
|
|
158
|
+
"""
|
|
159
|
+
Draws a circle with given radius and turtle
|
|
160
|
+
:param radius: radius of circle
|
|
161
|
+
:param tls_num: a given ChainTurtle
|
|
162
|
+
"""
|
|
163
|
+
tls_num.circle(radius)
|
|
164
|
+
|
|
165
|
+
def circle_filler(radius: Real,tls_num: ChainTurtle) -> None:
|
|
166
|
+
"""
|
|
167
|
+
Draws a filled circle with given radius and turtle
|
|
168
|
+
:param radius: radius of circle
|
|
169
|
+
:param tls_num: a given ChainTurtle
|
|
170
|
+
"""
|
|
171
|
+
tls_num.begin_fill().circle(radius).end_fill()
|
|
172
|
+
# ====== POLYGON ======
|
|
173
|
+
|
|
174
|
+
def polygon(length: Real,sides: int,tls_num: ChainTurtle) -> None:
|
|
175
|
+
"""
|
|
176
|
+
Draws a polygon with given length and sides
|
|
177
|
+
:param length: length of polygon
|
|
178
|
+
:param sides: number of sides
|
|
179
|
+
:param tls_num: a given ChainTurtle
|
|
180
|
+
"""
|
|
181
|
+
radius = length / (2 * sine(180 / sides)); angle_to_right = (180-(180*(sides-2))/sides) / 2
|
|
182
|
+
tls_num.rt(angle_to_right).circle(radius,360,sides).lt(angle_to_right)
|
|
183
|
+
|
|
184
|
+
def polygon_fill(length: Real,sides: int,tls_num: ChainTurtle) -> None:
|
|
185
|
+
"""
|
|
186
|
+
Draws a filled polygon with given length and sides
|
|
187
|
+
:param length: length of polygon
|
|
188
|
+
:param sides: number of sides
|
|
189
|
+
:param tls_num: a given ChainTurtle
|
|
190
|
+
"""
|
|
191
|
+
tls_num.begin_fill(); Shapes.polygon(length,sides,tls_num); tls_num.end_fill()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from time import sleep as rest
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_str(str_input: str, *check_values: str|dict|list|tuple) -> str:
|
|
5
|
+
"""
|
|
6
|
+
Checks whether the input string matches the allowed values (*check_values)
|
|
7
|
+
:param str_input: input string
|
|
8
|
+
:param check_values: allowed string values (all lowercase), options: str, dict, list, tuple
|
|
9
|
+
"""
|
|
10
|
+
if not isinstance(str_input, str):
|
|
11
|
+
raise TypeError("str_input must be a string")
|
|
12
|
+
|
|
13
|
+
while True:
|
|
14
|
+
value: str = input(str_input).lower()
|
|
15
|
+
for check in check_values:
|
|
16
|
+
if not isinstance(check, (str, dict, list, tuple)):
|
|
17
|
+
raise TypeError("check_values must be a string, dict, list, or tuple")
|
|
18
|
+
if isinstance(check, str) and check == value:
|
|
19
|
+
return value
|
|
20
|
+
elif isinstance(check, (dict, list, tuple)) and value in check:
|
|
21
|
+
return value
|
|
22
|
+
print("Enter something VALID!")
|
|
23
|
+
rest(1.5)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "GeometricalDomination"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A Python turtle graphics library and DSL for creating geometric drawings."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.14"
|
|
11
|
+
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Miah M. Sabiq", email = "miah.sabiq@gibs.at"}
|
|
14
|
+
]
|