ColabTurtlePlus 2.0.2__tar.gz → 2.1.1__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.
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/ColabTurtlePlus/Turtle.py +243 -33
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/ColabTurtlePlus.egg-info/PKG-INFO +49 -3
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/PKG-INFO +49 -3
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/README.md +48 -2
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/setup.cfg +1 -1
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/setup.py +1 -1
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/ColabTurtlePlus/__init__.py +0 -0
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/ColabTurtlePlus.egg-info/SOURCES.txt +0 -0
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/ColabTurtlePlus.egg-info/dependency_links.txt +0 -0
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/ColabTurtlePlus.egg-info/top_level.txt +0 -0
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/LICENSE +0 -0
- {colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/pyproject.toml +0 -0
|
@@ -27,6 +27,18 @@ v2.0.1 Oct. 2021
|
|
|
27
27
|
Lines drawn with drawlines() method now included in saved SVG file.
|
|
28
28
|
Fixes so that graphic window is still displayed when cell executed more than once in Jupyter notebook.
|
|
29
29
|
|
|
30
|
+
v2.0.2 Aug. 2026
|
|
31
|
+
Fixed Python 3.13+ SyntaxWarning by using raw strings in regular expressions.
|
|
32
|
+
|
|
33
|
+
v2.1.0 September 2026
|
|
34
|
+
Added register_shape() (alias addshape) to mimic the role of the function register_shape() from Python's turtle.
|
|
35
|
+
This only works to add a polygonal shape (and now component shapes with v2.1.1). It does not work with images.
|
|
36
|
+
|
|
37
|
+
v2.1.1 September 2026
|
|
38
|
+
Added addcomponent() to create new polygonal turtles. Because turtles are defined as svg strings, also added two
|
|
39
|
+
new functions, addellipsecomponent() and addpathcomponent, to create turtles bassed on ellipical shapes and svg
|
|
40
|
+
paths. To be consistent with Python's turtle, these are first invoked using a call to Shape("compound") and then
|
|
41
|
+
combined using register_shape().
|
|
30
42
|
"""
|
|
31
43
|
|
|
32
44
|
DEFAULT_WINDOW_SIZE = (800, 600)
|
|
@@ -61,12 +73,14 @@ VALID_COLORS = ('black', 'navy', 'darkblue', 'mediumblue', 'blue', 'darkgreen',
|
|
|
61
73
|
'lightgoldenrodyellow', 'oldlace', 'red', 'fuchsia', 'magenta', 'deeppink', 'orangered', 'tomato', 'hotpink', 'coral', 'darkorange',
|
|
62
74
|
'lightsalmon', 'orange', 'lightpink', 'pink', 'gold', 'peachpuff', 'navajowhite', 'moccasin', 'bisque', 'mistyrose', 'blanchedalmond',
|
|
63
75
|
'papayawhip', 'lavenderblush', 'seashell', 'cornsilk', 'lemonchiffon', 'floralwhite', 'snow', 'yellow', 'lightyellow', 'ivory', 'white','none','')
|
|
64
|
-
|
|
76
|
+
VALID_COLORS_SET = set(VALID_COLORS)
|
|
65
77
|
VALID_MODES = ('standard','logo','world','svg')
|
|
66
78
|
DEFAULT_TURTLE_SHAPE = 'classic'
|
|
67
|
-
VALID_TURTLE_SHAPES =
|
|
79
|
+
VALID_TURTLE_SHAPES = {'turtle', 'ring', 'classic', 'arrow', 'square', 'triangle', 'circle', 'turtle2', 'blank', 'user'}
|
|
68
80
|
DEFAULT_MODE = 'standard'
|
|
69
81
|
DEFAULT_ANGLE_MODE = 'degrees'
|
|
82
|
+
DEFAULT_POINTS = '-5,-4.5 0,-2.5 5,-4.5 0,4.5'
|
|
83
|
+
DEFAULT_NAME = 'classic'
|
|
70
84
|
SVG_TEMPLATE = """
|
|
71
85
|
<svg width="{window_width}" height="{window_height}">
|
|
72
86
|
<rect width="100%" height="100%" style="fill:{backcolor};stroke:{kolor};stroke-width:1"/>
|
|
@@ -103,9 +117,34 @@ TURTLE_CIRCLE_SVG_TEMPLATE = """<g id="ellipse" visibility="{visibility}" transf
|
|
|
103
117
|
TURTLE_TURTLE2_SVG_TEMPLATE = """<g id="turtle2" visibility="{visibility}" transform="rotate({degrees},{rotation_x},{rotation_y}) translate({turtle_x}, {turtle_y})">
|
|
104
118
|
<polygon points="0,16 2,14 1,10 4,7 7,9 9,8 6,5 7,1 5,-3 8,-6 6,-8 4,-5 0,-7 -4,-5 -6,-8 -8,-6 -5,-3 -7,1 -6,5 -9,8 -7,9 -4,7 -1,10 -2,14" transform="skewX({sk}) scale({sx},{sy})" style="stroke:{pcolor};stroke-width:1;fill:{turtle_color}" />
|
|
105
119
|
</g>"""
|
|
120
|
+
TURTLE_USER_SVG_TEMPLATE = """<g id="{id}" visibility="{visibility}" transform="rotate({degrees},{rotation_x},{rotation_y}) translate({turtle_x}, {turtle_y})">
|
|
121
|
+
<polygon points="{points}" transform="skewX({sk}) scale({sx},{sy})" style="stroke:{pcolor};fill:{turtle_color};stroke-width:{pw}" />
|
|
122
|
+
</g>"""
|
|
123
|
+
|
|
124
|
+
TURTLE_COMPONENT_SVG_TEMPLATE = """<g id="user" visibility="{visibility}" transform="rotate({degrees},{rotation_x},{rotation_y}) translate({turtle_x}, {turtle_y})">
|
|
125
|
+
"{component}"
|
|
126
|
+
</g>"""
|
|
127
|
+
|
|
128
|
+
POLY_TEMPLATE = """<polygon points="{points}" transform="skewX({sk})
|
|
129
|
+
scale({sx},{sy})" style="stroke:{pcolor};fill:{turtle_color};stroke-width:{pw}" />"""
|
|
130
|
+
ELLIPSE_TEMPLATE = """<ellipse transform="skewX({sk}) scale({sx},{sy})"
|
|
131
|
+
style="stroke:{pcolor};fill:{turtle_color};stroke-width:{pw}" rx="{rx}" ry ="{ry}" cx="{cx}" cy="{cy}" />"""
|
|
132
|
+
PATH_TEMPLATE = """<path d="{path}" style="stroke:{pcolor};fill-rule:evenodd;fill:{turtle_color};fill-opacity:1;"
|
|
133
|
+
transform="skewX({sk}) scale({sx},{sy})" />"""
|
|
134
|
+
|
|
106
135
|
|
|
107
136
|
SPEED_TO_SEC_MAP = {0: 0, 1: 1.0, 2: 0.8, 3: 0.5, 4: 0.3, 5: 0.25, 6: 0.20, 7: 0.15, 8: 0.125, 9: 0.10, 10: 0.08, 11: 0.04, 12: 0.02, 13: 0.005}
|
|
108
137
|
|
|
138
|
+
shapeDict = {"turtle":TURTLE_TURTLE_SVG_TEMPLATE,
|
|
139
|
+
"ring":TURTLE_RING_SVG_TEMPLATE,
|
|
140
|
+
"classic":TURTLE_CLASSIC_SVG_TEMPLATE,
|
|
141
|
+
"arrow":TURTLE_ARROW_SVG_TEMPLATE,
|
|
142
|
+
"square":TURTLE_SQUARE_SVG_TEMPLATE,
|
|
143
|
+
"triangle":TURTLE_TRIANGLE_SVG_TEMPLATE,
|
|
144
|
+
"circle":TURTLE_CIRCLE_SVG_TEMPLATE,
|
|
145
|
+
"turtle2":TURTLE_TURTLE2_SVG_TEMPLATE,
|
|
146
|
+
"blank":""}
|
|
147
|
+
|
|
109
148
|
#------------------------------------------------------------------------------------------------
|
|
110
149
|
|
|
111
150
|
def Screen():
|
|
@@ -163,9 +202,9 @@ class _Screen:
|
|
|
163
202
|
|
|
164
203
|
turtle_x = turtle.turtle_pos[0]
|
|
165
204
|
turtle_y = turtle.turtle_pos[1]
|
|
166
|
-
if self._mode ==
|
|
205
|
+
if self._mode == 'standard':
|
|
167
206
|
degrees = turtle.turtle_degree - turtle.tilt_angle
|
|
168
|
-
elif self._mode ==
|
|
207
|
+
elif self._mode == 'world':
|
|
169
208
|
degrees = turtle.turtle_orient - turtle.tilt_angle
|
|
170
209
|
else:
|
|
171
210
|
degrees = turtle.turtle_degree + turtle.tilt_angle
|
|
@@ -175,17 +214,18 @@ class _Screen:
|
|
|
175
214
|
elif turtle.turtle_shape == 'ring':
|
|
176
215
|
turtle_y += 10*turtle.stretchfactor[1]+4
|
|
177
216
|
degrees -= 90
|
|
178
|
-
else:
|
|
217
|
+
else: #turtle.turtle_shape in {'classic', 'arrow', 'square', 'triangle', 'circle', 'turtle2', 'blank'}:
|
|
179
218
|
degrees -= 90
|
|
219
|
+
|
|
180
220
|
|
|
181
|
-
svg =
|
|
221
|
+
svg = shapeDict[turtle.turtle_shape].format(
|
|
182
222
|
turtle_color=turtle.fill_color,
|
|
183
223
|
pcolor=turtle.pen_color,
|
|
184
224
|
turtle_x=turtle_x,
|
|
185
225
|
turtle_y=turtle_y,
|
|
186
226
|
visibility=vis,
|
|
187
227
|
degrees=degrees,
|
|
188
|
-
sx
|
|
228
|
+
sx=-turtle.stretchfactor[0],
|
|
189
229
|
sy=turtle.stretchfactor[1],
|
|
190
230
|
sk=turtle.shear_factor,
|
|
191
231
|
rx=10*turtle.stretchfactor[0],
|
|
@@ -193,7 +233,8 @@ class _Screen:
|
|
|
193
233
|
cy=-(10*turtle.stretchfactor[1]+4),
|
|
194
234
|
pw = turtle.outline_width,
|
|
195
235
|
rotation_x=turtle.turtle_pos[0],
|
|
196
|
-
rotation_y=turtle.turtle_pos[1]
|
|
236
|
+
rotation_y=turtle.turtle_pos[1],
|
|
237
|
+
id = turtle.turtle_shape)
|
|
197
238
|
return svg
|
|
198
239
|
|
|
199
240
|
# helper function for linking svg strings of text
|
|
@@ -312,6 +353,60 @@ class _Screen:
|
|
|
312
353
|
text_file.write(output)
|
|
313
354
|
text_file.close()
|
|
314
355
|
|
|
356
|
+
def register_shape(self, name, shape=None):
|
|
357
|
+
"""Adds a turtle shape to to the shape list.
|
|
358
|
+
|
|
359
|
+
Arg:
|
|
360
|
+
name is an arbitrary string
|
|
361
|
+
points is a list or tuple of pairs of coordinates that define a polygon,
|
|
362
|
+
or a (compound) Shape object
|
|
363
|
+
|
|
364
|
+
Installs the corresponding polygon shape or the corresponding compound shape.
|
|
365
|
+
If no points are given, the turtle shape will be blank.
|
|
366
|
+
Note: This version does NOT include shapes that are images
|
|
367
|
+
"""
|
|
368
|
+
|
|
369
|
+
if not isinstance(name,str):
|
|
370
|
+
raise TypeError("The name must be a string")
|
|
371
|
+
if shape is None:
|
|
372
|
+
self.points = None
|
|
373
|
+
elif isinstance(shape, (list, tuple)):
|
|
374
|
+
points = shape
|
|
375
|
+
if len(points) < 2:
|
|
376
|
+
raise ValueError("The points must contain at least 2 coordinate pairs.")
|
|
377
|
+
for i, point in enumerate(points):
|
|
378
|
+
if not isinstance(point, (list, tuple)):
|
|
379
|
+
raise TypeError(
|
|
380
|
+
f"The point[{i}] must be a coordinate pair."
|
|
381
|
+
)
|
|
382
|
+
if len(point) != 2:
|
|
383
|
+
raise ValueError(
|
|
384
|
+
f"The point[{i}] must contain exactly two coordinates."
|
|
385
|
+
)
|
|
386
|
+
if not all(isinstance(x, (int, float)) for x in point):
|
|
387
|
+
raise TypeError(
|
|
388
|
+
f"The point[{i}] must contain numeric coordinates."
|
|
389
|
+
)
|
|
390
|
+
name = name.lower()
|
|
391
|
+
VALID_TURTLE_SHAPES.add(name)
|
|
392
|
+
pointstr = " ".join(f"{x},{y}" for x, y in points)
|
|
393
|
+
shapeDict[name] = TURTLE_USER_SVG_TEMPLATE.replace("{points}",pointstr) #TURTLE_USER_SVG_TEMPLATE
|
|
394
|
+
else: #assume compound shape
|
|
395
|
+
tmp=TURTLE_COMPONENT_SVG_TEMPLATE.format(
|
|
396
|
+
component=shape._data,
|
|
397
|
+
visibility="{visibility}",
|
|
398
|
+
degrees="{degrees}",
|
|
399
|
+
rotation_x="{rotation_x}",
|
|
400
|
+
rotation_y="{rotation_y}",
|
|
401
|
+
turtle_x="{turtle_x}",
|
|
402
|
+
turtle_y="{turtle_y}",
|
|
403
|
+
)
|
|
404
|
+
# componentDict[shape] = tm
|
|
405
|
+
name = name.lower()
|
|
406
|
+
VALID_TURTLE_SHAPES.add(name)
|
|
407
|
+
shapeDict[name] = tmp
|
|
408
|
+
addshape=register_shape
|
|
409
|
+
|
|
315
410
|
#=========================
|
|
316
411
|
# screen drawing functions
|
|
317
412
|
#=========================
|
|
@@ -710,8 +805,8 @@ class _Screen:
|
|
|
710
805
|
|
|
711
806
|
def turtles(self):
|
|
712
807
|
"""Return the list of turtles on the screen."""
|
|
713
|
-
return self._turtles
|
|
714
|
-
|
|
808
|
+
return self._turtles
|
|
809
|
+
|
|
715
810
|
def initializescreen(self,window=DEFAULT_WINDOW_SIZE,mode=DEFAULT_MODE):
|
|
716
811
|
"""Initializes the drawing window
|
|
717
812
|
|
|
@@ -720,7 +815,7 @@ class _Screen:
|
|
|
720
815
|
mode: (optional) one of "standard, "logo", "world", or "sv
|
|
721
816
|
|
|
722
817
|
The defaults are (800,600) and "standard".
|
|
723
|
-
|
|
818
|
+
"""
|
|
724
819
|
if window is not None:
|
|
725
820
|
if not (isinstance(window, tuple) and len(window) == 2 and isinstance(
|
|
726
821
|
window[0], int) and isinstance(window[1], int)):
|
|
@@ -774,7 +869,109 @@ class _Screen:
|
|
|
774
869
|
err = 'The color parameter ' + color + ' must be a color string or a tuple'
|
|
775
870
|
raise ValueError(err)
|
|
776
871
|
|
|
872
|
+
#----------------------------------------------------------------------------------------------
|
|
873
|
+
class Shape(object):
|
|
874
|
+
def __init__(self, type_, data=None):
|
|
875
|
+
self._type = type_
|
|
876
|
+
if type_ == "compound":
|
|
877
|
+
data = ""
|
|
878
|
+
self._data = data
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
def addcomponent(self, points, fill=None, outline=None):
|
|
882
|
+
"""Add polygonal component to a shape of type compound.
|
|
883
|
+
|
|
884
|
+
Arguments: poly is a polygon, i. e. a tuple of number pairs.
|
|
885
|
+
fill is the fillcolor of the polygon,
|
|
886
|
+
outline is the outline color of the polygon.
|
|
887
|
+
|
|
888
|
+
Example:
|
|
889
|
+
>>> poly = ((0,0),(10,-5),(0,10),(-10,-5))
|
|
890
|
+
>>> s = Shape("compound")
|
|
891
|
+
>>> s.addcomponent(poly, "red", "blue")
|
|
892
|
+
>>> # .. add more components and then use register_shape()
|
|
893
|
+
"""
|
|
894
|
+
|
|
895
|
+
tmp = self._data
|
|
896
|
+
p = " ".join(f"{x},{y}" for x, y in points)
|
|
897
|
+
template = POLY_TEMPLATE.replace("{points}",p) + "\n"
|
|
898
|
+
if fill is not None:
|
|
899
|
+
template = template.replace("{turtle_color}",fill)
|
|
900
|
+
if outline is None:
|
|
901
|
+
template = template.replace("{pcolor}",fill)
|
|
902
|
+
else:
|
|
903
|
+
template = template.replace("{pcolor}", outline)
|
|
904
|
+
elif outline is not None:
|
|
905
|
+
template = template.replace("{pcolor}",outline)
|
|
906
|
+
self._data = tmp + template
|
|
907
|
+
|
|
908
|
+
def addellipsecomponent(self, center, radii, fill=None, outline=None):
|
|
909
|
+
"""Add elliptical component to a shape of type compound.
|
|
910
|
+
|
|
911
|
+
Arguments: center is a tuple (cx,cy) that is the center of the ellipse
|
|
912
|
+
radii is a tuple (rx, ry) giving the radius of the ellipse in the x and y directions.
|
|
913
|
+
Can use just radii = r as a substitute for (r,r) to do a circle of radius r
|
|
914
|
+
fill is the fillcolor of the ellipse,
|
|
915
|
+
outline is the outline color of the ellipse.
|
|
916
|
+
|
|
917
|
+
Example:
|
|
918
|
+
>>> s = Shape("compound")
|
|
919
|
+
>>> s.addellipsecomponent((0,0), (50,100), "red", "blue")
|
|
920
|
+
>>> # .. add more components and then use register_shape()
|
|
921
|
+
"""
|
|
922
|
+
tmp = self._data
|
|
923
|
+
if isinstance(radii, (float,int)):
|
|
924
|
+
xradius = radii
|
|
925
|
+
yradius = radii
|
|
926
|
+
elif isinstance(radii, tuple):
|
|
927
|
+
xradius = radii[0]
|
|
928
|
+
yradius = radii[1]
|
|
929
|
+
replacements = {
|
|
930
|
+
"{cx}": str(center[0]),
|
|
931
|
+
"{cy}": str(center[1]),
|
|
932
|
+
"{rx}": str(xradius),
|
|
933
|
+
"{ry}": str(yradius)
|
|
934
|
+
}
|
|
935
|
+
pattern = re.compile("|".join(re.escape(key) for key in replacements.keys()))
|
|
936
|
+
template = pattern.sub(lambda match: replacements[match.group(0)], ELLIPSE_TEMPLATE)
|
|
937
|
+
if fill is not None:
|
|
938
|
+
template = template.replace("{turtle_color}",fill)
|
|
939
|
+
if outline is None:
|
|
940
|
+
template = template.replace("{pcolor}",fill)
|
|
941
|
+
else:
|
|
942
|
+
template = template.replace("{pcolor}", outline)
|
|
943
|
+
elif outline is not None:
|
|
944
|
+
template = template.replace("{pcolor}",outline)
|
|
945
|
+
self._data = tmp + template + "\n"
|
|
946
|
+
|
|
947
|
+
def addpathcomponent(self, path, fill=None, outline=None):
|
|
948
|
+
"""Add an SVG path component to a shape of type compound.
|
|
949
|
+
|
|
950
|
+
Arguments: path is an SVG string defining a path
|
|
951
|
+
fill is the fillcolor of the component,
|
|
952
|
+
outline is the outline color of the component.
|
|
953
|
+
|
|
954
|
+
Example:
|
|
955
|
+
>>> curve = "M -50 -50 Q 0 100 50 -50" (quadratic Bezier curve)
|
|
956
|
+
>>> s = Shape("compound")
|
|
957
|
+
>>> s.addpathcomponent(curve, "red", "blue")
|
|
958
|
+
>>> # .. add more components and then use register_shape()
|
|
959
|
+
"""
|
|
960
|
+
tmp = self._data
|
|
961
|
+
template = PATH_TEMPLATE.replace("{path}",path)
|
|
962
|
+
if fill is not None:
|
|
963
|
+
template = template.replace("{turtle_color}",fill)
|
|
964
|
+
if outline is None:
|
|
965
|
+
template = template.replace("{pcolor}",fill)
|
|
966
|
+
else:
|
|
967
|
+
template = template.replace("{pcolor}", outline)
|
|
968
|
+
elif outline is not None:
|
|
969
|
+
template = template.replace("{pcolor}",outline)
|
|
970
|
+
self._data = tmp + template + "\n"
|
|
777
971
|
|
|
972
|
+
addEllipseComponet = addellipsecomponent
|
|
973
|
+
addPathComponent = addpathcomponent
|
|
974
|
+
#-------------------------------------------------------------
|
|
778
975
|
|
|
779
976
|
#----------------------------------------------------------------------------------------------
|
|
780
977
|
|
|
@@ -821,16 +1018,9 @@ class RawTurtle:
|
|
|
821
1018
|
self.stampdictT = {}
|
|
822
1019
|
self.stampnum = 0
|
|
823
1020
|
self.stamplist=[]
|
|
824
|
-
self.
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
"arrow":TURTLE_ARROW_SVG_TEMPLATE,
|
|
828
|
-
"square":TURTLE_SQUARE_SVG_TEMPLATE,
|
|
829
|
-
"triangle":TURTLE_TRIANGLE_SVG_TEMPLATE,
|
|
830
|
-
"circle":TURTLE_CIRCLE_SVG_TEMPLATE,
|
|
831
|
-
"turtle2":TURTLE_TURTLE2_SVG_TEMPLATE,
|
|
832
|
-
"blank":""}
|
|
833
|
-
if screen._mode == "svg": self.shapeDict.update({"circle":TURTLE_RING_SVG_TEMPLATE})
|
|
1021
|
+
self.points = DEFAULT_POINTS
|
|
1022
|
+
|
|
1023
|
+
if screen._mode == "svg": shapeDict.update({"circle":TURTLE_RING_SVG_TEMPLATE})
|
|
834
1024
|
screen._add(self)
|
|
835
1025
|
|
|
836
1026
|
|
|
@@ -906,10 +1096,10 @@ class RawTurtle:
|
|
|
906
1096
|
self.screen._updateDrawing(turtle=self)
|
|
907
1097
|
elif self.turtle_shape != 'ring' and self.stretchfactor[0]==self.stretchfactor[1]:
|
|
908
1098
|
stretchfactor_orig = self.stretchfactor
|
|
909
|
-
template =
|
|
1099
|
+
template = shapeDict[self.turtle_shape]
|
|
910
1100
|
tmp = """<animateTransform id = "one" attributeName="transform"
|
|
911
1101
|
type="scale"
|
|
912
|
-
from="
|
|
1102
|
+
from="{sx} {sy}" to="{sx} {sy}"
|
|
913
1103
|
begin="0s" dur="0.01s"
|
|
914
1104
|
repeatCount="1"
|
|
915
1105
|
additive="sum"
|
|
@@ -923,13 +1113,13 @@ class RawTurtle:
|
|
|
923
1113
|
fill="freeze"
|
|
924
1114
|
/></g>""".format(extent=deg, t=self.timeout*abs(deg)/90, sx=self.stretchfactor[0], sy=self.stretchfactor[1])
|
|
925
1115
|
newtemplate = template.replace("</g>",tmp)
|
|
926
|
-
|
|
1116
|
+
shapeDict.update({self.turtle_shape:newtemplate})
|
|
927
1117
|
self.stretchfactor = 1,1
|
|
928
1118
|
self.timeout = self.timeout*abs(deg)/90+0.001
|
|
929
1119
|
self.screen._updateDrawing(self)
|
|
930
1120
|
self.turtle_degree = (self.turtle_degree + deg) % 360
|
|
931
1121
|
self.turtle_orient = self._turtleOrientation()
|
|
932
|
-
|
|
1122
|
+
shapeDict.update({self.turtle_shape:template})
|
|
933
1123
|
self.stretchfactor = stretchfactor_orig
|
|
934
1124
|
self.timeout = timeout_orig
|
|
935
1125
|
else: #_turtle_shape == 'ring' or _stretchfactor[0] != _stretchfactor[1]
|
|
@@ -1581,6 +1771,19 @@ class RawTurtle:
|
|
|
1581
1771
|
deg = math.degrees(math.atan2(-Dxy[1],Dxy[0])) % 360
|
|
1582
1772
|
return 360-deg
|
|
1583
1773
|
|
|
1774
|
+
def extract_points(self):
|
|
1775
|
+
svg_string = shapeDict[self.turtle_shape]
|
|
1776
|
+
match = re.search(r'points="([^"]*)"', svg_string)
|
|
1777
|
+
if not match:
|
|
1778
|
+
raise ValueError("No points attribute found")
|
|
1779
|
+
def number(s):
|
|
1780
|
+
value = float(s)
|
|
1781
|
+
return int(value) if value.is_integer() else value
|
|
1782
|
+
return tuple(
|
|
1783
|
+
(number(x), number(y))
|
|
1784
|
+
for x, y in (point.split(",") for point in match.group(1).split())
|
|
1785
|
+
)
|
|
1786
|
+
|
|
1584
1787
|
#========================================
|
|
1585
1788
|
# Turtle Motion - Setting and Measurement
|
|
1586
1789
|
#========================================
|
|
@@ -1856,6 +2059,7 @@ class RawTurtle:
|
|
|
1856
2059
|
|
|
1857
2060
|
return self.is_filling
|
|
1858
2061
|
|
|
2062
|
+
|
|
1859
2063
|
# Initialize the string for the svg path of the filled shape.
|
|
1860
2064
|
# Modified from aronma/ColabTurtle_2 github repo
|
|
1861
2065
|
# The current _svg_lines_string is stored to be used when the fill is finished because the svg_fill_string will include
|
|
@@ -2109,10 +2313,11 @@ class RawTurtle:
|
|
|
2109
2313
|
#==========================
|
|
2110
2314
|
# Turtle State - Appearance
|
|
2111
2315
|
#==========================
|
|
2112
|
-
|
|
2316
|
+
|
|
2113
2317
|
# Set turtle shape to shape with given name or, if name is not given, return name of current shape
|
|
2114
2318
|
def shape(self, name=None):
|
|
2115
2319
|
"""Sets turtle shape to shape with given name / return current shapename.
|
|
2320
|
+
Can also create a user-defined custom polygonal shape
|
|
2116
2321
|
|
|
2117
2322
|
Args:
|
|
2118
2323
|
name: an optional string, which is a valid shapename
|
|
@@ -2125,6 +2330,8 @@ class RawTurtle:
|
|
|
2125
2330
|
The 'turtle' shape is the one that Tolga Atam included in his original
|
|
2126
2331
|
ColabTurtle version. Use 'turtle2' for the polygonal turtle shape form
|
|
2127
2332
|
turtle.py. The circle shape from the original ColabTurtle was renamed 'ring'.
|
|
2333
|
+
|
|
2334
|
+
Use register_shape (alias addshape) to create a polygonal shape with a chosen name.
|
|
2128
2335
|
"""
|
|
2129
2336
|
|
|
2130
2337
|
if name is None:
|
|
@@ -2133,7 +2340,7 @@ class RawTurtle:
|
|
|
2133
2340
|
raise ValueError('Shape is invalid. Valid options are: ' + str(VALID_TURTLE_SHAPES))
|
|
2134
2341
|
self.turtle_shape = name.lower()
|
|
2135
2342
|
self.screen._updateDrawing(turtle=self)
|
|
2136
|
-
|
|
2343
|
+
|
|
2137
2344
|
# Scale the size of the turtle
|
|
2138
2345
|
# stretch_wid scales perpendicular to orientation
|
|
2139
2346
|
# stretch_len scales in direction of turtle's orientation
|
|
@@ -2172,7 +2379,8 @@ class RawTurtle:
|
|
|
2172
2379
|
outline = self.outline_width
|
|
2173
2380
|
elif not isinstance(outline, (int,float)):
|
|
2174
2381
|
raise ValueError('The outline must be a positive number.')
|
|
2175
|
-
self.outline_width = outline
|
|
2382
|
+
self.outline_width = outline
|
|
2383
|
+
self.screen._updateDrawing(turtle=self, delay=False)
|
|
2176
2384
|
turtlesize = shapesize #alias
|
|
2177
2385
|
|
|
2178
2386
|
# Set or return the current shearfactor. Shear the turtleshape according to the given shearfactor shear, which is the tangent of the shear angle.
|
|
@@ -2376,16 +2584,18 @@ def getcolor(n):
|
|
|
2376
2584
|
return VALID_COLORS[n]
|
|
2377
2585
|
|
|
2378
2586
|
|
|
2379
|
-
_tg_screen_functions = ['bgcolor', 'clearscreen', 'drawline', 'hideborder',
|
|
2380
|
-
'initializescreen','initializeTurtle', 'showSVG', 'saveSVG', 'line', 'mode', 'resetscreen', 'setup',
|
|
2587
|
+
_tg_screen_functions = ['addshape', 'bgcolor', 'clearscreen', 'drawline', 'hideborder',
|
|
2588
|
+
'initializescreen','initializeTurtle', 'showSVG', 'saveSVG', 'line', 'mode', 'register_shape', 'resetscreen', 'setup',
|
|
2381
2589
|
'setworldcoordinates', 'showborder', 'turtles', 'window_width', 'window_height' ]
|
|
2382
2590
|
|
|
2591
|
+
_tg_shape_functions = ['addcomponent', 'addellipsecomponent', 'addpathcomponent']
|
|
2592
|
+
|
|
2383
2593
|
_tg_turtle_functions = ['animationOff', 'animationOn', 'bk', 'back', 'backward', 'begin_fill',
|
|
2384
2594
|
'circle', 'clear', 'clearstamp', 'clearstamps', 'color', 'degrees', 'delay', 'distance', 'done',
|
|
2385
|
-
'dot', 'down', 'end_fill', 'face', 'fd', 'fillcolor', 'filling', 'fillopacity', 'fillrule', 'forward',
|
|
2595
|
+
'dot', 'down', 'end_fill', 'extract_points', 'face', 'fd', 'fillcolor', 'filling', 'fillopacity', 'fillrule', 'forward',
|
|
2386
2596
|
'getheading', 'getx', 'gety', 'goto', 'heading', 'hideturtle', 'home', 'ht', 'isdown',
|
|
2387
2597
|
'isvisible', 'jumpto', 'left', 'lt', 'pd', 'pen', 'pencolor', 'pensize', 'pendown', 'penup', 'pos',
|
|
2388
|
-
'position', 'pu', 'radians', 'regularPolygon', 'reset', 'right', 'rt',
|
|
2598
|
+
'position', 'pu', 'radians', 'regularPolygon', 'reset', 'right', 'rt', 'setheading', 'seth',
|
|
2389
2599
|
'setpos', 'setposition', 'settiltangle', 'setx','sety', 'shape', 'shapesize', 'shearfactor',
|
|
2390
2600
|
'showturtle', 'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'turtlesize', 'towards', 'up', 'update',
|
|
2391
2601
|
'width', 'write', 'xcor', 'ycor' ]
|
|
@@ -2445,7 +2655,6 @@ def _screen_docrevise(docstr):
|
|
|
2445
2655
|
newdocstr = parexp.sub(":", newdocstr)
|
|
2446
2656
|
return newdocstr
|
|
2447
2657
|
|
|
2448
|
-
|
|
2449
2658
|
__func_body = """\
|
|
2450
2659
|
def {name}{paramslist}:
|
|
2451
2660
|
if {obj} is None:
|
|
@@ -2471,3 +2680,4 @@ _make_global_funcs(_tg_screen_functions, _Screen, 'Turtle._screen', 'Screen()',_
|
|
|
2471
2680
|
|
|
2472
2681
|
|
|
2473
2682
|
|
|
2683
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ColabTurtlePlus
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: An HTML based Turtle implementation with classes for Google Colab and Jupyter Labs
|
|
5
5
|
Home-page: https://github.com/mathriddle/ColabTurtlePlus
|
|
6
6
|
Author: Larry Riddle
|
|
@@ -33,6 +33,12 @@ The ColabTurtlePlus module provides turtle graphics primitives, in both object-o
|
|
|
33
33
|
|
|
34
34
|
To use multiple turtles on a screen one has to use the object-oriented interface for the turtles.
|
|
35
35
|
|
|
36
|
+
What's New:
|
|
37
|
+
----
|
|
38
|
+
Sept. 2026: Version 2.1.0 adds a register_shape (alias addshape) function to create a polygonal turtle shape. It does not work with images.
|
|
39
|
+
|
|
40
|
+
Sept. 2026: Version 2.1.1 allows use of addcomponent() to add a polygon to a component turtle shape. There are two new ways to build additional components: addellipsecomponent() adds an elliptical shape, and addpathcompenent adds a path defined using svg path commands.
|
|
41
|
+
|
|
36
42
|
Installation
|
|
37
43
|
----
|
|
38
44
|
Create an empty code cell and type:
|
|
@@ -53,7 +59,6 @@ Example 1
|
|
|
53
59
|
---
|
|
54
60
|
This example uses the procedure-oriented interface.
|
|
55
61
|
```
|
|
56
|
-
from ColabTurtlePlus.Turtle import *
|
|
57
62
|
clearscreen()
|
|
58
63
|
setup(300,300)
|
|
59
64
|
showborder()
|
|
@@ -77,7 +82,6 @@ Example 2
|
|
|
77
82
|
----
|
|
78
83
|
This example has two turtles and uses the object-oriented interface.
|
|
79
84
|
```
|
|
80
|
-
from ColabTurtlePlus.Turtle import *
|
|
81
85
|
clearscreen()
|
|
82
86
|
setup(500,300)
|
|
83
87
|
T = Turtle()
|
|
@@ -105,6 +109,48 @@ S.end_fill()
|
|
|
105
109
|
The resulting image is
|
|
106
110
|

|
|
107
111
|
|
|
112
|
+
Example 3:
|
|
113
|
+
----
|
|
114
|
+
This example uses components.
|
|
115
|
+
```
|
|
116
|
+
clearscreen()
|
|
117
|
+
setup(300,300)
|
|
118
|
+
|
|
119
|
+
comp_shape = Shape("compound")
|
|
120
|
+
poly = ((-50,0),(-50,100),(50,100),(50,0))
|
|
121
|
+
comp_shape.addcomponent(poly,"blue")
|
|
122
|
+
comp_shape.addellipsecomponent((0,120),50,"red")
|
|
123
|
+
|
|
124
|
+
star_coords = ((-10,-13.8), (0,17), (10,-13.8), (-16.2,5.3), (16.2,5.3))
|
|
125
|
+
|
|
126
|
+
addshape("box_with_ball", comp_shape)
|
|
127
|
+
addshape("star", star_coords)
|
|
128
|
+
|
|
129
|
+
t = Turtle()
|
|
130
|
+
t.shapesize(0.5,0.5)
|
|
131
|
+
t.fillcolor("yellow")
|
|
132
|
+
t.shapesize(0.25)
|
|
133
|
+
t.shape("box_with_ball")
|
|
134
|
+
t.pensize(2)
|
|
135
|
+
t.speed(5)
|
|
136
|
+
t.begin_fill()
|
|
137
|
+
|
|
138
|
+
for _ in range(4):
|
|
139
|
+
t.forward(100)
|
|
140
|
+
t.left(90)
|
|
141
|
+
t.end_fill()
|
|
142
|
+
t.forward(100)
|
|
143
|
+
t.left(90)
|
|
144
|
+
|
|
145
|
+
s = Turtle()
|
|
146
|
+
s.shapesize(1.5)
|
|
147
|
+
s.shape("star")
|
|
148
|
+
s.circle(-50)
|
|
149
|
+
s.color("black","green")
|
|
150
|
+
```
|
|
151
|
+
The resulting image is
|
|
152
|
+

|
|
153
|
+
|
|
108
154
|
Main differences with ColabTurtle
|
|
109
155
|
----
|
|
110
156
|
This version implements classes.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ColabTurtlePlus
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: An HTML based Turtle implementation with classes for Google Colab and Jupyter Labs
|
|
5
5
|
Home-page: https://github.com/mathriddle/ColabTurtlePlus
|
|
6
6
|
Author: Larry Riddle
|
|
@@ -33,6 +33,12 @@ The ColabTurtlePlus module provides turtle graphics primitives, in both object-o
|
|
|
33
33
|
|
|
34
34
|
To use multiple turtles on a screen one has to use the object-oriented interface for the turtles.
|
|
35
35
|
|
|
36
|
+
What's New:
|
|
37
|
+
----
|
|
38
|
+
Sept. 2026: Version 2.1.0 adds a register_shape (alias addshape) function to create a polygonal turtle shape. It does not work with images.
|
|
39
|
+
|
|
40
|
+
Sept. 2026: Version 2.1.1 allows use of addcomponent() to add a polygon to a component turtle shape. There are two new ways to build additional components: addellipsecomponent() adds an elliptical shape, and addpathcompenent adds a path defined using svg path commands.
|
|
41
|
+
|
|
36
42
|
Installation
|
|
37
43
|
----
|
|
38
44
|
Create an empty code cell and type:
|
|
@@ -53,7 +59,6 @@ Example 1
|
|
|
53
59
|
---
|
|
54
60
|
This example uses the procedure-oriented interface.
|
|
55
61
|
```
|
|
56
|
-
from ColabTurtlePlus.Turtle import *
|
|
57
62
|
clearscreen()
|
|
58
63
|
setup(300,300)
|
|
59
64
|
showborder()
|
|
@@ -77,7 +82,6 @@ Example 2
|
|
|
77
82
|
----
|
|
78
83
|
This example has two turtles and uses the object-oriented interface.
|
|
79
84
|
```
|
|
80
|
-
from ColabTurtlePlus.Turtle import *
|
|
81
85
|
clearscreen()
|
|
82
86
|
setup(500,300)
|
|
83
87
|
T = Turtle()
|
|
@@ -105,6 +109,48 @@ S.end_fill()
|
|
|
105
109
|
The resulting image is
|
|
106
110
|

|
|
107
111
|
|
|
112
|
+
Example 3:
|
|
113
|
+
----
|
|
114
|
+
This example uses components.
|
|
115
|
+
```
|
|
116
|
+
clearscreen()
|
|
117
|
+
setup(300,300)
|
|
118
|
+
|
|
119
|
+
comp_shape = Shape("compound")
|
|
120
|
+
poly = ((-50,0),(-50,100),(50,100),(50,0))
|
|
121
|
+
comp_shape.addcomponent(poly,"blue")
|
|
122
|
+
comp_shape.addellipsecomponent((0,120),50,"red")
|
|
123
|
+
|
|
124
|
+
star_coords = ((-10,-13.8), (0,17), (10,-13.8), (-16.2,5.3), (16.2,5.3))
|
|
125
|
+
|
|
126
|
+
addshape("box_with_ball", comp_shape)
|
|
127
|
+
addshape("star", star_coords)
|
|
128
|
+
|
|
129
|
+
t = Turtle()
|
|
130
|
+
t.shapesize(0.5,0.5)
|
|
131
|
+
t.fillcolor("yellow")
|
|
132
|
+
t.shapesize(0.25)
|
|
133
|
+
t.shape("box_with_ball")
|
|
134
|
+
t.pensize(2)
|
|
135
|
+
t.speed(5)
|
|
136
|
+
t.begin_fill()
|
|
137
|
+
|
|
138
|
+
for _ in range(4):
|
|
139
|
+
t.forward(100)
|
|
140
|
+
t.left(90)
|
|
141
|
+
t.end_fill()
|
|
142
|
+
t.forward(100)
|
|
143
|
+
t.left(90)
|
|
144
|
+
|
|
145
|
+
s = Turtle()
|
|
146
|
+
s.shapesize(1.5)
|
|
147
|
+
s.shape("star")
|
|
148
|
+
s.circle(-50)
|
|
149
|
+
s.color("black","green")
|
|
150
|
+
```
|
|
151
|
+
The resulting image is
|
|
152
|
+

|
|
153
|
+
|
|
108
154
|
Main differences with ColabTurtle
|
|
109
155
|
----
|
|
110
156
|
This version implements classes.
|
|
@@ -8,6 +8,12 @@ The ColabTurtlePlus module provides turtle graphics primitives, in both object-o
|
|
|
8
8
|
|
|
9
9
|
To use multiple turtles on a screen one has to use the object-oriented interface for the turtles.
|
|
10
10
|
|
|
11
|
+
What's New:
|
|
12
|
+
----
|
|
13
|
+
Sept. 2026: Version 2.1.0 adds a register_shape (alias addshape) function to create a polygonal turtle shape. It does not work with images.
|
|
14
|
+
|
|
15
|
+
Sept. 2026: Version 2.1.1 allows use of addcomponent() to add a polygon to a component turtle shape. There are two new ways to build additional components: addellipsecomponent() adds an elliptical shape, and addpathcompenent adds a path defined using svg path commands.
|
|
16
|
+
|
|
11
17
|
Installation
|
|
12
18
|
----
|
|
13
19
|
Create an empty code cell and type:
|
|
@@ -28,7 +34,6 @@ Example 1
|
|
|
28
34
|
---
|
|
29
35
|
This example uses the procedure-oriented interface.
|
|
30
36
|
```
|
|
31
|
-
from ColabTurtlePlus.Turtle import *
|
|
32
37
|
clearscreen()
|
|
33
38
|
setup(300,300)
|
|
34
39
|
showborder()
|
|
@@ -52,7 +57,6 @@ Example 2
|
|
|
52
57
|
----
|
|
53
58
|
This example has two turtles and uses the object-oriented interface.
|
|
54
59
|
```
|
|
55
|
-
from ColabTurtlePlus.Turtle import *
|
|
56
60
|
clearscreen()
|
|
57
61
|
setup(500,300)
|
|
58
62
|
T = Turtle()
|
|
@@ -80,6 +84,48 @@ S.end_fill()
|
|
|
80
84
|
The resulting image is
|
|
81
85
|

|
|
82
86
|
|
|
87
|
+
Example 3:
|
|
88
|
+
----
|
|
89
|
+
This example uses components.
|
|
90
|
+
```
|
|
91
|
+
clearscreen()
|
|
92
|
+
setup(300,300)
|
|
93
|
+
|
|
94
|
+
comp_shape = Shape("compound")
|
|
95
|
+
poly = ((-50,0),(-50,100),(50,100),(50,0))
|
|
96
|
+
comp_shape.addcomponent(poly,"blue")
|
|
97
|
+
comp_shape.addellipsecomponent((0,120),50,"red")
|
|
98
|
+
|
|
99
|
+
star_coords = ((-10,-13.8), (0,17), (10,-13.8), (-16.2,5.3), (16.2,5.3))
|
|
100
|
+
|
|
101
|
+
addshape("box_with_ball", comp_shape)
|
|
102
|
+
addshape("star", star_coords)
|
|
103
|
+
|
|
104
|
+
t = Turtle()
|
|
105
|
+
t.shapesize(0.5,0.5)
|
|
106
|
+
t.fillcolor("yellow")
|
|
107
|
+
t.shapesize(0.25)
|
|
108
|
+
t.shape("box_with_ball")
|
|
109
|
+
t.pensize(2)
|
|
110
|
+
t.speed(5)
|
|
111
|
+
t.begin_fill()
|
|
112
|
+
|
|
113
|
+
for _ in range(4):
|
|
114
|
+
t.forward(100)
|
|
115
|
+
t.left(90)
|
|
116
|
+
t.end_fill()
|
|
117
|
+
t.forward(100)
|
|
118
|
+
t.left(90)
|
|
119
|
+
|
|
120
|
+
s = Turtle()
|
|
121
|
+
s.shapesize(1.5)
|
|
122
|
+
s.shape("star")
|
|
123
|
+
s.circle(-50)
|
|
124
|
+
s.color("black","green")
|
|
125
|
+
```
|
|
126
|
+
The resulting image is
|
|
127
|
+

|
|
128
|
+
|
|
83
129
|
Main differences with ColabTurtle
|
|
84
130
|
----
|
|
85
131
|
This version implements classes.
|
|
File without changes
|
|
File without changes
|
{colabturtleplus-2.0.2 → colabturtleplus-2.1.1}/ColabTurtlePlus.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|