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.
@@ -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
+ 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,3 @@
1
+ from typing import TypeAlias
2
+
3
+ Real: TypeAlias = float | int
@@ -0,0 +1,6 @@
1
+ from .DecoratorArchive import class_decorator
2
+ from .GetVariable import get_num
3
+ from .HelperFunctions import helper, sine, range_f
4
+ from .RepeatlessList import repeatless_list, repeatless_list2
5
+ from .Shapes import Shapes
6
+ from .StringCheck import get_str
@@ -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
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+